mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 13:49:36 +01:00
feat: Paginierung für alle GET-List-Endpoints (#61)
Einheitliches Paginierungs-Pattern mit page, size und Multi-Field sort
für alle 14 List-Endpoints. Response-Format ändert sich von [...] zu
{ content: [...], page: { number, size, totalElements, totalPages } }.
Backend:
- Shared Kernel: Page<T>, PageRequest, SortField, SortDirection
- PaginationHelper (SQL ORDER BY mit Whitelist), PageResponse DTO
- Paginated Methoden in allen 14 Domain-Repos + JDBC-Implementierungen
- Safety-Limit (500) für findAllBelowMinimumLevel/ExpiryRelevantBatches
- Alle List-Use-Cases akzeptieren PageRequest, liefern Page<T>
- Alle Controller mit page/size/sort Query-Params + PageResponse
Frontend:
- PagedResponse<T> Type auf nested page-Format aktualisiert
- Alle 14 API-Client-Resourcen liefern PagedResponse mit PaginationParams
- Alle Hooks mit Pagination-State (currentPage, totalPages, pageSize)
- Alle List-Screens mit Seiten-Navigation (Pfeiltasten) und Footer
Loadtest:
- Podman-Support im justfile (DOCKER_HOST auto-detect)
- Verschärfte Performance-Schwellwerte basierend auf Ist-Werten
This commit is contained in:
parent
fc4faafd57
commit
72979c9537
151 changed files with 2880 additions and 1120 deletions
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.inventory;
|
|||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.domain.masterdata.article.ArticleId;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
|
@ -261,10 +263,14 @@ class CheckStockExpiryTest {
|
|||
// Unused methods for this test
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllBelowMinimumLevel() { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, Optional<Stock>> findById(StockId id) { return Result.success(Optional.empty()); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAll(PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAllByStorageLocationId(StorageLocationId storageLocationId, PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAllByArticleId(ArticleId articleId, PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Optional<Stock>> findByArticleIdAndStorageLocationId(ArticleId articleId, StorageLocationId storageLocationId) { return Result.success(Optional.empty()); }
|
||||
@Override public Result<RepositoryError, Boolean> existsByArticleIdAndStorageLocationId(ArticleId articleId, StorageLocationId storageLocationId) { return Result.success(false); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAll() { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByStorageLocationId(StorageLocationId storageLocationId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByArticleId(ArticleId articleId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByBatchId(String batchId) { return Result.success(List.of()); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package de.effigenix.application.inventory;
|
||||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.security.ActorId;
|
||||
|
|
@ -18,6 +20,8 @@ import java.util.List;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
|
@ -31,6 +35,7 @@ class ListInventoryCountsTest {
|
|||
private InventoryCount count1;
|
||||
private InventoryCount count2;
|
||||
private final ActorId actorId = ActorId.of("user-1");
|
||||
private final PageRequest pageRequest = PageRequest.of(0, 100);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
|
@ -65,105 +70,55 @@ class ListInventoryCountsTest {
|
|||
@Test
|
||||
@DisplayName("should return all counts when no filter provided")
|
||||
void shouldReturnAllCountsWhenNoFilter() {
|
||||
when(inventoryCountRepository.findAll()).thenReturn(Result.success(List.of(count1, count2)));
|
||||
when(inventoryCountRepository.findAll(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(List.of(count1, count2), 0, 100, 2)));
|
||||
|
||||
var result = listInventoryCounts.execute(null, null, actorId);
|
||||
var result = listInventoryCounts.execute(null, actorId, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
verify(inventoryCountRepository).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter by storageLocationId")
|
||||
void shouldFilterByStorageLocationId() {
|
||||
when(inventoryCountRepository.findByStorageLocationId(StorageLocationId.of("location-1")))
|
||||
.thenReturn(Result.success(List.of(count1)));
|
||||
|
||||
var result = listInventoryCounts.execute("location-1", null, actorId);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(inventoryCountRepository).findByStorageLocationId(StorageLocationId.of("location-1"));
|
||||
verify(inventoryCountRepository, never()).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails for findAll")
|
||||
void shouldFailWhenRepositoryFailsForFindAll() {
|
||||
when(inventoryCountRepository.findAll())
|
||||
when(inventoryCountRepository.findAll(isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listInventoryCounts.execute(null, null, actorId);
|
||||
var result = listInventoryCounts.execute(null, actorId, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(InventoryCountError.RepositoryFailure.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails for storageLocationId filter")
|
||||
void shouldFailWhenRepositoryFailsForFilter() {
|
||||
when(inventoryCountRepository.findByStorageLocationId(StorageLocationId.of("location-1")))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
@DisplayName("should return empty page when no counts match")
|
||||
void shouldReturnEmptyPageWhenNoCountsMatch() {
|
||||
when(inventoryCountRepository.findAll(eq(InventoryCountStatus.OPEN), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listInventoryCounts.execute("location-1", null, actorId);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(InventoryCountError.RepositoryFailure.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no counts match")
|
||||
void shouldReturnEmptyListWhenNoCountsMatch() {
|
||||
when(inventoryCountRepository.findByStorageLocationId(StorageLocationId.of("unknown")))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
|
||||
var result = listInventoryCounts.execute("unknown", null, actorId);
|
||||
var result = listInventoryCounts.execute("OPEN", actorId, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidStorageLocationId for blank storageLocationId")
|
||||
void shouldFailWhenBlankStorageLocationId() {
|
||||
var result = listInventoryCounts.execute(" ", null, actorId);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(InventoryCountError.InvalidStorageLocationId.class);
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter by status only")
|
||||
void shouldFilterByStatusOnly() {
|
||||
when(inventoryCountRepository.findByStatus(InventoryCountStatus.OPEN))
|
||||
.thenReturn(Result.success(List.of(count1)));
|
||||
when(inventoryCountRepository.findAll(eq(InventoryCountStatus.OPEN), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(List.of(count1), 0, 100, 1)));
|
||||
|
||||
var result = listInventoryCounts.execute(null, "OPEN", actorId);
|
||||
var result = listInventoryCounts.execute("OPEN", actorId, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(inventoryCountRepository).findByStatus(InventoryCountStatus.OPEN);
|
||||
verify(inventoryCountRepository, never()).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter by storageLocationId and status")
|
||||
void shouldFilterByStorageLocationIdAndStatus() {
|
||||
when(inventoryCountRepository.findByStorageLocationId(StorageLocationId.of("location-1")))
|
||||
.thenReturn(Result.success(List.of(count1, count2)));
|
||||
|
||||
var result = listInventoryCounts.execute("location-1", "OPEN", actorId);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().getFirst().status()).isEqualTo(InventoryCountStatus.OPEN);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidStatus for invalid status string")
|
||||
void shouldFailWhenInvalidStatus() {
|
||||
var result = listInventoryCounts.execute(null, "INVALID", actorId);
|
||||
var result = listInventoryCounts.execute("INVALID", actorId, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(InventoryCountError.InvalidStatus.class);
|
||||
|
|
@ -175,7 +130,7 @@ class ListInventoryCountsTest {
|
|||
reset(authPort);
|
||||
when(authPort.can(any(ActorId.class), any())).thenReturn(false);
|
||||
|
||||
var result = listInventoryCounts.execute(null, null, actorId);
|
||||
var result = listInventoryCounts.execute(null, actorId, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(InventoryCountError.Unauthorized.class);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.inventory;
|
|||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.domain.masterdata.article.ArticleId;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
|
@ -36,6 +38,7 @@ class ListStockMovementsTest {
|
|||
private ListStockMovements useCase;
|
||||
private StockMovement sampleMovement;
|
||||
private final ActorId actor = ActorId.of("user-1");
|
||||
private final PageRequest pageRequest = PageRequest.of(0, 100);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
|
@ -62,33 +65,34 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should return all movements when no filter")
|
||||
void shouldReturnAll() {
|
||||
when(repository.findAll()).thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor);
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no movements exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(repository.findAll()).thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor);
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail when repository fails")
|
||||
void shouldFailWhenRepositoryFails() {
|
||||
when(repository.findAll()).thenReturn(
|
||||
Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor);
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.RepositoryFailure.class);
|
||||
|
|
@ -102,21 +106,19 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should filter by stockId")
|
||||
void shouldFilterByStockId() {
|
||||
when(repository.findAllByStockId(StockId.of("stock-1")))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute("stock-1", null, null, null, null, null, actor);
|
||||
var result = useCase.execute("stock-1", null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAllByStockId(StockId.of("stock-1"));
|
||||
verify(repository, never()).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidStockId when format invalid")
|
||||
void shouldFailWhenStockIdInvalid() {
|
||||
var result = useCase.execute(" ", null, null, null, null, null, actor);
|
||||
var result = useCase.execute(" ", null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.InvalidStockId.class);
|
||||
|
|
@ -130,20 +132,19 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should filter by articleId")
|
||||
void shouldFilterByArticleId() {
|
||||
when(repository.findAllByArticleId(ArticleId.of("article-1")))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, "article-1", null, null, null, null, actor);
|
||||
var result = useCase.execute(null, "article-1", null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAllByArticleId(ArticleId.of("article-1"));
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidArticleId when format invalid")
|
||||
void shouldFailWhenArticleIdInvalid() {
|
||||
var result = useCase.execute(null, " ", null, null, null, null, actor);
|
||||
var result = useCase.execute(null, " ", null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.InvalidArticleId.class);
|
||||
|
|
@ -157,32 +158,31 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should filter by batchReference")
|
||||
void shouldFilterByBatchReference() {
|
||||
when(repository.findAllByBatchReference("CHARGE-001"))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", null, null, actor);
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAllByBatchReference("CHARGE-001");
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no movements for batch")
|
||||
void shouldReturnEmptyForUnknownBatch() {
|
||||
when(repository.findAllByBatchReference("UNKNOWN"))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute(null, null, null, "UNKNOWN", null, null, actor);
|
||||
var result = useCase.execute(null, null, null, "UNKNOWN", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidBatchReference when blank")
|
||||
void shouldFailWhenBatchReferenceBlank() {
|
||||
var result = useCase.execute(null, null, null, " ", null, null, actor);
|
||||
var result = useCase.execute(null, null, null, " ", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.InvalidBatchReference.class);
|
||||
|
|
@ -191,10 +191,10 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should fail when repository fails for batchReference")
|
||||
void shouldFailWhenRepositoryFailsForBatch() {
|
||||
when(repository.findAllByBatchReference("CHARGE-001"))
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", null, null, actor);
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.RepositoryFailure.class);
|
||||
|
|
@ -208,20 +208,19 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should filter by movementType")
|
||||
void shouldFilterByMovementType() {
|
||||
when(repository.findAllByMovementType(MovementType.GOODS_RECEIPT))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", null, null, null, actor);
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAllByMovementType(MovementType.GOODS_RECEIPT);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidMovementType when type invalid")
|
||||
void shouldFailWhenMovementTypeInvalid() {
|
||||
var result = useCase.execute(null, null, "INVALID_TYPE", null, null, null, actor);
|
||||
var result = useCase.execute(null, null, "INVALID_TYPE", null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.InvalidMovementType.class);
|
||||
|
|
@ -238,69 +237,64 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("should filter by from and to")
|
||||
void shouldFilterByFromAndTo() {
|
||||
when(repository.findAllByPerformedAtBetween(from, to))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, from, to, actor);
|
||||
var result = useCase.execute(null, null, null, null, from, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(repository).findAllByPerformedAtBetween(from, to);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter with only from (open-ended)")
|
||||
void shouldFilterByFromOnly() {
|
||||
when(repository.findAllByPerformedAtAfter(from))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, from, null, actor);
|
||||
var result = useCase.execute(null, null, null, null, from, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByPerformedAtAfter(from);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter with only to (open-ended)")
|
||||
void shouldFilterByToOnly() {
|
||||
when(repository.findAllByPerformedAtBefore(to))
|
||||
.thenReturn(Result.success(List.of(sampleMovement)));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleMovement), 0, 100, 1)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, null, to, actor);
|
||||
var result = useCase.execute(null, null, null, null, null, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByPerformedAtBefore(to);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidDateRange when from is after to")
|
||||
void shouldFailWhenFromAfterTo() {
|
||||
var result = useCase.execute(null, null, null, null, to, from, actor);
|
||||
var result = useCase.execute(null, null, null, null, to, from, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.InvalidDateRange.class);
|
||||
verify(repository, never()).findAllByPerformedAtBetween(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should succeed when from equals to (same instant)")
|
||||
void shouldSucceedWhenFromEqualsTo() {
|
||||
when(repository.findAllByPerformedAtBetween(from, from))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, from, from, actor);
|
||||
var result = useCase.execute(null, null, null, null, from, from, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByPerformedAtBetween(from, from);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail when repository fails for date range")
|
||||
void shouldFailWhenRepositoryFailsForDateRange() {
|
||||
when(repository.findAllByPerformedAtBetween(from, to))
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = useCase.execute(null, null, null, null, from, to, actor);
|
||||
var result = useCase.execute(null, null, null, null, from, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.RepositoryFailure.class);
|
||||
|
|
@ -314,88 +308,73 @@ class ListStockMovementsTest {
|
|||
@Test
|
||||
@DisplayName("stockId takes priority over articleId, batchReference and movementType")
|
||||
void stockIdTakesPriority() {
|
||||
when(repository.findAllByStockId(StockId.of("stock-1")))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute("stock-1", "article-1", "GOODS_RECEIPT", "CHARGE-001", null, null, actor);
|
||||
var result = useCase.execute("stock-1", "article-1", "GOODS_RECEIPT", "CHARGE-001", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByStockId(StockId.of("stock-1"));
|
||||
verify(repository, never()).findAllByArticleId(any());
|
||||
verify(repository, never()).findAllByBatchReference(any());
|
||||
verify(repository, never()).findAllByMovementType(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("articleId takes priority over batchReference and movementType")
|
||||
void articleIdTakesPriorityOverBatchAndMovementType() {
|
||||
when(repository.findAllByArticleId(ArticleId.of("article-1")))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute(null, "article-1", "GOODS_RECEIPT", "CHARGE-001", null, null, actor);
|
||||
var result = useCase.execute(null, "article-1", "GOODS_RECEIPT", "CHARGE-001", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByArticleId(ArticleId.of("article-1"));
|
||||
verify(repository, never()).findAllByBatchReference(any());
|
||||
verify(repository, never()).findAllByMovementType(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("batchReference takes priority over movementType")
|
||||
void batchReferenceTakesPriorityOverMovementType() {
|
||||
when(repository.findAllByBatchReference("CHARGE-001"))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", "CHARGE-001", null, null, actor);
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", "CHARGE-001", null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByBatchReference("CHARGE-001");
|
||||
verify(repository, never()).findAllByMovementType(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("movementType takes priority over from/to")
|
||||
void movementTypeTakesPriorityOverDateRange() {
|
||||
when(repository.findAllByMovementType(MovementType.GOODS_RECEIPT))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
Instant from = Instant.parse("2026-01-01T00:00:00Z");
|
||||
Instant to = Instant.parse("2026-12-31T23:59:59Z");
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", null, from, to, actor);
|
||||
var result = useCase.execute(null, null, "GOODS_RECEIPT", null, from, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByMovementType(MovementType.GOODS_RECEIPT);
|
||||
verify(repository, never()).findAllByPerformedAtBetween(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("stockId takes priority over from/to")
|
||||
void stockIdTakesPriorityOverDateRange() {
|
||||
when(repository.findAllByStockId(StockId.of("stock-1")))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
Instant from = Instant.parse("2026-01-01T00:00:00Z");
|
||||
Instant to = Instant.parse("2026-12-31T23:59:59Z");
|
||||
var result = useCase.execute("stock-1", null, null, null, from, to, actor);
|
||||
var result = useCase.execute("stock-1", null, null, null, from, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByStockId(StockId.of("stock-1"));
|
||||
verify(repository, never()).findAllByPerformedAtBetween(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("batchReference takes priority over from/to")
|
||||
void batchReferenceTakesPriorityOverDateRange() {
|
||||
when(repository.findAllByBatchReference("CHARGE-001"))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
when(repository.findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
Instant from = Instant.parse("2026-01-01T00:00:00Z");
|
||||
Instant to = Instant.parse("2026-12-31T23:59:59Z");
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", from, to, actor);
|
||||
var result = useCase.execute(null, null, null, "CHARGE-001", from, to, actor, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
verify(repository).findAllByBatchReference("CHARGE-001");
|
||||
verify(repository, never()).findAllByPerformedAtBetween(any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,11 +387,11 @@ class ListStockMovementsTest {
|
|||
void shouldFailWhenUnauthorized() {
|
||||
when(authPort.can(actor, InventoryAction.STOCK_MOVEMENT_READ)).thenReturn(false);
|
||||
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor);
|
||||
var result = useCase.execute(null, null, null, null, null, null, actor, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockMovementError.Unauthorized.class);
|
||||
verify(repository, never()).findAll();
|
||||
verify(repository, never()).findAll(any(), any(), any(), any(), any(), any(), any(PageRequest.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.inventory;
|
|||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.domain.masterdata.article.ArticleId;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
|
@ -140,12 +142,16 @@ class ListStocksBelowMinimumTest {
|
|||
|
||||
// Unused methods for this test
|
||||
@Override public Result<RepositoryError, Optional<Stock>> findById(StockId id) { return Result.success(Optional.empty()); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAll(PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAllByStorageLocationId(StorageLocationId storageLocationId, PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Page<Stock>> findAllByArticleId(ArticleId articleId, PageRequest pageRequest) { return Result.success(Page.empty(pageRequest.size())); }
|
||||
@Override public Result<RepositoryError, Optional<Stock>> findByArticleIdAndStorageLocationId(ArticleId articleId, StorageLocationId storageLocationId) { return Result.success(Optional.empty()); }
|
||||
@Override public Result<RepositoryError, Boolean> existsByArticleIdAndStorageLocationId(ArticleId articleId, StorageLocationId storageLocationId) { return Result.success(false); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAll() { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByStorageLocationId(StorageLocationId storageLocationId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByArticleId(ArticleId articleId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllWithExpiryRelevantBatches(LocalDate referenceDate) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, List<Stock>> findAllByBatchId(String batchId) { return Result.success(List.of()); }
|
||||
@Override public Result<RepositoryError, Void> save(Stock stock) { return Result.success(null); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.inventory;
|
|||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.domain.masterdata.article.ArticleId;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -14,6 +16,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
|
@ -48,47 +52,51 @@ class ListStocksTest {
|
|||
@Test
|
||||
@DisplayName("should return all stocks when no filter provided")
|
||||
void shouldReturnAllStocksWhenNoFilter() {
|
||||
when(stockRepository.findAll()).thenReturn(Result.success(List.of(stock1, stock2)));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAll(any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.of(List.of(stock1, stock2), 0, 100, 2)));
|
||||
|
||||
var result = listStocks.execute(null, null);
|
||||
var result = listStocks.execute(null, null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
verify(stockRepository).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
verify(stockRepository).findAll(pageRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter by storageLocationId")
|
||||
void shouldFilterByStorageLocationId() {
|
||||
when(stockRepository.findAllByStorageLocationId(StorageLocationId.of("location-1")))
|
||||
.thenReturn(Result.success(List.of(stock1, stock2)));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAllByStorageLocationId(StorageLocationId.of("location-1"), pageRequest))
|
||||
.thenReturn(Result.success(Page.of(List.of(stock1, stock2), 0, 100, 2)));
|
||||
|
||||
var result = listStocks.execute("location-1", null);
|
||||
var result = listStocks.execute("location-1", null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
verify(stockRepository).findAllByStorageLocationId(StorageLocationId.of("location-1"));
|
||||
verify(stockRepository, never()).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
verify(stockRepository).findAllByStorageLocationId(StorageLocationId.of("location-1"), pageRequest);
|
||||
verify(stockRepository, never()).findAll(any(PageRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should filter by articleId")
|
||||
void shouldFilterByArticleId() {
|
||||
when(stockRepository.findAllByArticleId(ArticleId.of("article-1")))
|
||||
.thenReturn(Result.success(List.of(stock1)));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAllByArticleId(ArticleId.of("article-1"), pageRequest))
|
||||
.thenReturn(Result.success(Page.of(List.of(stock1), 0, 100, 1)));
|
||||
|
||||
var result = listStocks.execute(null, "article-1");
|
||||
var result = listStocks.execute(null, "article-1", pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(stockRepository).findAllByArticleId(ArticleId.of("article-1"));
|
||||
verify(stockRepository, never()).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
verify(stockRepository).findAllByArticleId(ArticleId.of("article-1"), pageRequest);
|
||||
verify(stockRepository, never()).findAll(any(PageRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail when both filters are provided")
|
||||
void shouldFailWhenBothFiltersProvided() {
|
||||
var result = listStocks.execute("location-1", "article-1");
|
||||
var result = listStocks.execute("location-1", "article-1", PageRequest.of(0, 100));
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockError.InvalidFilterCombination.class);
|
||||
|
|
@ -98,10 +106,11 @@ class ListStocksTest {
|
|||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails for findAll")
|
||||
void shouldFailWhenRepositoryFailsForFindAll() {
|
||||
when(stockRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAll(any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listStocks.execute(null, null);
|
||||
var result = listStocks.execute(null, null, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockError.RepositoryFailure.class);
|
||||
|
|
@ -110,10 +119,11 @@ class ListStocksTest {
|
|||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails for storageLocationId filter")
|
||||
void shouldFailWhenRepositoryFailsForStorageLocationFilter() {
|
||||
when(stockRepository.findAllByStorageLocationId(StorageLocationId.of("location-1")))
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAllByStorageLocationId(eq(StorageLocationId.of("location-1")), any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listStocks.execute("location-1", null);
|
||||
var result = listStocks.execute("location-1", null, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockError.RepositoryFailure.class);
|
||||
|
|
@ -122,10 +132,11 @@ class ListStocksTest {
|
|||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails for articleId filter")
|
||||
void shouldFailWhenRepositoryFailsForArticleIdFilter() {
|
||||
when(stockRepository.findAllByArticleId(ArticleId.of("article-1")))
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAllByArticleId(eq(ArticleId.of("article-1")), any(PageRequest.class)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listStocks.execute(null, "article-1");
|
||||
var result = listStocks.execute(null, "article-1", pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StockError.RepositoryFailure.class);
|
||||
|
|
@ -134,12 +145,13 @@ class ListStocksTest {
|
|||
@Test
|
||||
@DisplayName("should return empty list when no stocks match")
|
||||
void shouldReturnEmptyListWhenNoStocksMatch() {
|
||||
when(stockRepository.findAllByStorageLocationId(StorageLocationId.of("unknown")))
|
||||
.thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(stockRepository.findAllByStorageLocationId(eq(StorageLocationId.of("unknown")), any(PageRequest.class)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listStocks.execute("unknown", null);
|
||||
var result = listStocks.execute("unknown", null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package de.effigenix.application.inventory;
|
||||
|
||||
import de.effigenix.domain.inventory.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -14,6 +16,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
|
@ -58,32 +63,37 @@ class ListStorageLocationsTest {
|
|||
activeLocation("Lager A", StorageType.DRY_STORAGE),
|
||||
inactiveLocation("Lager B", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findAll()).thenReturn(Result.success(locations));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(locations, 0, 100, 2)));
|
||||
|
||||
var result = listStorageLocations.execute(null, null);
|
||||
var result = listStorageLocations.execute(null, null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when none exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(storageLocationRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listStorageLocations.execute(null, null);
|
||||
var result = listStorageLocations.execute(null, null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail when repository fails")
|
||||
void shouldFailWhenRepositoryFails() {
|
||||
when(storageLocationRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listStorageLocations.execute(null, null);
|
||||
var result = listStorageLocations.execute(null, null, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StorageLocationError.RepositoryFailure.class);
|
||||
|
|
@ -99,47 +109,44 @@ class ListStorageLocationsTest {
|
|||
@Test
|
||||
@DisplayName("should return only active locations when active=true")
|
||||
void shouldReturnOnlyActive() {
|
||||
var locations = List.of(
|
||||
activeLocation("Aktiv", StorageType.DRY_STORAGE),
|
||||
inactiveLocation("Inaktiv", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findAll()).thenReturn(Result.success(locations));
|
||||
var activeLocations = List.of(activeLocation("Aktiv", StorageType.DRY_STORAGE));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), eq(true), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(activeLocations, 0, 100, 1)));
|
||||
|
||||
var result = listStorageLocations.execute(null, true);
|
||||
var result = listStorageLocations.execute(null, true, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().get(0).name().value()).isEqualTo("Aktiv");
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content().get(0).name().value()).isEqualTo("Aktiv");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return only inactive locations when active=false")
|
||||
void shouldReturnOnlyInactive() {
|
||||
var locations = List.of(
|
||||
activeLocation("Aktiv", StorageType.DRY_STORAGE),
|
||||
inactiveLocation("Inaktiv", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findAll()).thenReturn(Result.success(locations));
|
||||
var inactiveLocations = List.of(inactiveLocation("Inaktiv", StorageType.COLD_ROOM));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), eq(false), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(inactiveLocations, 0, 100, 1)));
|
||||
|
||||
var result = listStorageLocations.execute(null, false);
|
||||
var result = listStorageLocations.execute(null, false, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().get(0).name().value()).isEqualTo("Inaktiv");
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content().get(0).name().value()).isEqualTo("Inaktiv");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no locations match active filter")
|
||||
void shouldReturnEmptyWhenNoMatch() {
|
||||
var locations = List.of(
|
||||
activeLocation("Aktiv", StorageType.DRY_STORAGE)
|
||||
);
|
||||
when(storageLocationRepository.findAll()).thenReturn(Result.success(locations));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(isNull(), eq(false), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listStorageLocations.execute(null, false);
|
||||
var result = listStorageLocations.execute(null, false, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,23 +159,22 @@ class ListStorageLocationsTest {
|
|||
@Test
|
||||
@DisplayName("should return locations of given storage type")
|
||||
void shouldReturnByStorageType() {
|
||||
var coldRooms = List.of(
|
||||
activeLocation("Kühlraum", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findByStorageType(StorageType.COLD_ROOM))
|
||||
.thenReturn(Result.success(coldRooms));
|
||||
var coldRooms = List.of(activeLocation("Kühlraum", StorageType.COLD_ROOM));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(eq(StorageType.COLD_ROOM), isNull(), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(coldRooms, 0, 100, 1)));
|
||||
|
||||
var result = listStorageLocations.execute("COLD_ROOM", null);
|
||||
var result = listStorageLocations.execute("COLD_ROOM", null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().get(0).storageType()).isEqualTo(StorageType.COLD_ROOM);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content().get(0).storageType()).isEqualTo(StorageType.COLD_ROOM);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with InvalidStorageType for unknown type")
|
||||
void shouldFailForInvalidStorageType() {
|
||||
var result = listStorageLocations.execute("INVALID", null);
|
||||
var result = listStorageLocations.execute("INVALID", null, PageRequest.of(0, 100));
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(StorageLocationError.InvalidStorageType.class);
|
||||
|
|
@ -185,50 +191,44 @@ class ListStorageLocationsTest {
|
|||
@Test
|
||||
@DisplayName("should return only active locations of given type")
|
||||
void shouldReturnActiveOfType() {
|
||||
var coldRooms = List.of(
|
||||
activeLocation("Kühl Aktiv", StorageType.COLD_ROOM),
|
||||
inactiveLocation("Kühl Inaktiv", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findByStorageType(StorageType.COLD_ROOM))
|
||||
.thenReturn(Result.success(coldRooms));
|
||||
var activeOfType = List.of(activeLocation("Kühl Aktiv", StorageType.COLD_ROOM));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(eq(StorageType.COLD_ROOM), eq(true), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(activeOfType, 0, 100, 1)));
|
||||
|
||||
var result = listStorageLocations.execute("COLD_ROOM", true);
|
||||
var result = listStorageLocations.execute("COLD_ROOM", true, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().get(0).name().value()).isEqualTo("Kühl Aktiv");
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content().get(0).name().value()).isEqualTo("Kühl Aktiv");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return only inactive locations of given type")
|
||||
void shouldReturnInactiveOfType() {
|
||||
var coldRooms = List.of(
|
||||
activeLocation("Kühl Aktiv", StorageType.COLD_ROOM),
|
||||
inactiveLocation("Kühl Inaktiv", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findByStorageType(StorageType.COLD_ROOM))
|
||||
.thenReturn(Result.success(coldRooms));
|
||||
var inactiveOfType = List.of(inactiveLocation("Kühl Inaktiv", StorageType.COLD_ROOM));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(eq(StorageType.COLD_ROOM), eq(false), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.of(inactiveOfType, 0, 100, 1)));
|
||||
|
||||
var result = listStorageLocations.execute("COLD_ROOM", false);
|
||||
var result = listStorageLocations.execute("COLD_ROOM", false, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().get(0).name().value()).isEqualTo("Kühl Inaktiv");
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content().get(0).name().value()).isEqualTo("Kühl Inaktiv");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no locations match combined filter")
|
||||
void shouldReturnEmptyWhenNoMatchCombined() {
|
||||
var coldRooms = List.of(
|
||||
activeLocation("Kühl Aktiv", StorageType.COLD_ROOM)
|
||||
);
|
||||
when(storageLocationRepository.findByStorageType(StorageType.COLD_ROOM))
|
||||
.thenReturn(Result.success(coldRooms));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(storageLocationRepository.findAll(eq(StorageType.COLD_ROOM), eq(false), eq(pageRequest)))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listStorageLocations.execute("COLD_ROOM", false);
|
||||
var result = listStorageLocations.execute("COLD_ROOM", false, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import de.effigenix.domain.masterdata.article.*;
|
|||
import de.effigenix.domain.masterdata.productcategory.ProductCategoryId;
|
||||
import de.effigenix.domain.masterdata.supplier.SupplierId;
|
||||
import de.effigenix.shared.common.Money;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
|
|
@ -419,58 +421,37 @@ class ArticleUseCaseTest {
|
|||
@DisplayName("should return all articles")
|
||||
void shouldReturnAllArticles() {
|
||||
var articles = List.of(reconstitutedArticle("a-1"), reconstitutedArticle("a-2"));
|
||||
when(articleRepository.findAll()).thenReturn(Result.success(articles));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(articleRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.of(articles, 0, 100, 2)));
|
||||
|
||||
var result = listArticles.execute();
|
||||
var result = listArticles.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when none exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(articleRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(articleRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listArticles.execute();
|
||||
var result = listArticles.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findAll fails")
|
||||
void shouldFailWhenRepositoryFails() {
|
||||
when(articleRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(articleRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listArticles.execute();
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ArticleError.RepositoryFailure.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return articles by category")
|
||||
void shouldReturnByCategory() {
|
||||
var catId = ProductCategoryId.of(CATEGORY_ID);
|
||||
var articles = List.of(reconstitutedArticle("a-1"));
|
||||
when(articleRepository.findByCategory(catId)).thenReturn(Result.success(articles));
|
||||
|
||||
var result = listArticles.executeByCategory(catId);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findByCategory fails")
|
||||
void shouldFailWhenFindByCategoryFails() {
|
||||
var catId = ProductCategoryId.of(CATEGORY_ID);
|
||||
when(articleRepository.findByCategory(catId))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listArticles.executeByCategory(catId);
|
||||
var result = listArticles.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ArticleError.RepositoryFailure.class);
|
||||
|
|
@ -479,23 +460,25 @@ class ArticleUseCaseTest {
|
|||
@Test
|
||||
@DisplayName("should return articles by status")
|
||||
void shouldReturnByStatus() {
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
var articles = List.of(reconstitutedArticle("a-1"));
|
||||
when(articleRepository.findByStatus(ArticleStatus.ACTIVE))
|
||||
.thenReturn(Result.success(articles));
|
||||
when(articleRepository.findAll(ArticleStatus.ACTIVE, pageRequest))
|
||||
.thenReturn(Result.success(Page.of(articles, 0, 100, 1)));
|
||||
|
||||
var result = listArticles.executeByStatus(ArticleStatus.ACTIVE);
|
||||
var result = listArticles.execute(ArticleStatus.ACTIVE, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findByStatus fails")
|
||||
void shouldFailWhenFindByStatusFails() {
|
||||
when(articleRepository.findByStatus(ArticleStatus.ACTIVE))
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(articleRepository.findAll(ArticleStatus.ACTIVE, pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listArticles.executeByStatus(ArticleStatus.ACTIVE);
|
||||
var result = listArticles.execute(ArticleStatus.ACTIVE, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ArticleError.RepositoryFailure.class);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,14 @@ import de.effigenix.application.masterdata.customer.command.*;
|
|||
import de.effigenix.domain.masterdata.*;
|
||||
import de.effigenix.domain.masterdata.article.ArticleId;
|
||||
import de.effigenix.domain.masterdata.customer.*;
|
||||
import de.effigenix.shared.common.*;
|
||||
import de.effigenix.shared.common.Address;
|
||||
import de.effigenix.shared.common.ContactInfo;
|
||||
import de.effigenix.shared.common.Money;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.PaymentTerms;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
import de.effigenix.shared.security.ActorId;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -386,81 +393,37 @@ class CustomerUseCaseTest {
|
|||
@DisplayName("should return all customers")
|
||||
void shouldReturnAllCustomers() {
|
||||
var customers = List.of(existingB2BCustomer("c1"), existingB2CCustomer("c2"));
|
||||
when(customerRepository.findAll()).thenReturn(Result.success(customers));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(customerRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.of(customers, 0, 100, 2)));
|
||||
|
||||
var result = listCustomers.execute();
|
||||
var result = listCustomers.execute(pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no customers exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(customerRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(customerRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listCustomers.execute();
|
||||
var result = listCustomers.execute(pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findAll fails")
|
||||
void shouldFailWhenFindAllFails() {
|
||||
when(customerRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(customerRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("timeout")));
|
||||
|
||||
var result = listCustomers.execute();
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(CustomerError.RepositoryFailure.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return customers by type")
|
||||
void shouldReturnCustomersByType() {
|
||||
var b2bCustomers = List.of(existingB2BCustomer("c1"));
|
||||
when(customerRepository.findByType(CustomerType.B2B)).thenReturn(Result.success(b2bCustomers));
|
||||
|
||||
var result = listCustomers.executeByType(CustomerType.B2B);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().getFirst().type()).isEqualTo(CustomerType.B2B);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findByType fails")
|
||||
void shouldFailWhenFindByTypeFails() {
|
||||
when(customerRepository.findByType(CustomerType.B2B))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("error")));
|
||||
|
||||
var result = listCustomers.executeByType(CustomerType.B2B);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(CustomerError.RepositoryFailure.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return customers by status")
|
||||
void shouldReturnCustomersByStatus() {
|
||||
var activeCustomers = List.of(existingB2BCustomer("c1"), existingB2CCustomer("c2"));
|
||||
when(customerRepository.findByStatus(CustomerStatus.ACTIVE)).thenReturn(Result.success(activeCustomers));
|
||||
|
||||
var result = listCustomers.executeByStatus(CustomerStatus.ACTIVE);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findByStatus fails")
|
||||
void shouldFailWhenFindByStatusFails() {
|
||||
when(customerRepository.findByStatus(CustomerStatus.ACTIVE))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("error")));
|
||||
|
||||
var result = listCustomers.executeByStatus(CustomerStatus.ACTIVE);
|
||||
var result = listCustomers.execute(pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(CustomerError.RepositoryFailure.class);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import de.effigenix.application.masterdata.productcategory.UpdateProductCategory
|
|||
import de.effigenix.domain.masterdata.article.Article;
|
||||
import de.effigenix.domain.masterdata.article.ArticleRepository;
|
||||
import de.effigenix.domain.masterdata.productcategory.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
|
|
@ -346,32 +348,37 @@ class ProductCategoryUseCaseTest {
|
|||
existingCategory("cat-1", "Backwaren"),
|
||||
existingCategory("cat-2", "Getränke")
|
||||
);
|
||||
when(categoryRepository.findAll()).thenReturn(Result.success(categories));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(categoryRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.of(categories, 0, 100, 2)));
|
||||
|
||||
var result = useCase.execute();
|
||||
var result = useCase.execute(pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no categories exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(categoryRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(categoryRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = useCase.execute();
|
||||
var result = useCase.execute(pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when repository fails")
|
||||
void shouldFailWhenRepositoryFails() {
|
||||
when(categoryRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(categoryRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = useCase.execute();
|
||||
var result = useCase.execute(pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ProductCategoryError.RepositoryFailure.class);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import de.effigenix.application.masterdata.supplier.*;
|
|||
import de.effigenix.application.masterdata.supplier.command.*;
|
||||
import de.effigenix.domain.masterdata.supplier.*;
|
||||
import de.effigenix.shared.common.ContactInfo;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
|
|
@ -388,32 +390,37 @@ class SupplierUseCaseTest {
|
|||
@DisplayName("should return all suppliers")
|
||||
void shouldReturnAllSuppliers() {
|
||||
var suppliers = List.of(existingSupplier("s-1"), existingSupplier("s-2"));
|
||||
when(supplierRepository.findAll()).thenReturn(Result.success(suppliers));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(supplierRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.of(suppliers, 0, 100, 2)));
|
||||
|
||||
var result = listSuppliers.execute();
|
||||
var result = listSuppliers.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no suppliers exist")
|
||||
void shouldReturnEmptyList() {
|
||||
when(supplierRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(supplierRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listSuppliers.execute();
|
||||
var result = listSuppliers.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findAll fails")
|
||||
void shouldFailWhenFindAllFails() {
|
||||
when(supplierRepository.findAll())
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(supplierRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listSuppliers.execute();
|
||||
var result = listSuppliers.execute(null, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(SupplierError.RepositoryFailure.class);
|
||||
|
|
@ -423,22 +430,24 @@ class SupplierUseCaseTest {
|
|||
@DisplayName("should return suppliers filtered by status")
|
||||
void shouldReturnSuppliersByStatus() {
|
||||
var activeSuppliers = List.of(existingSupplier("s-1"));
|
||||
when(supplierRepository.findByStatus(SupplierStatus.ACTIVE))
|
||||
.thenReturn(Result.success(activeSuppliers));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(supplierRepository.findAll(SupplierStatus.ACTIVE, pageRequest))
|
||||
.thenReturn(Result.success(Page.of(activeSuppliers, 0, 100, 1)));
|
||||
|
||||
var result = listSuppliers.executeByStatus(SupplierStatus.ACTIVE);
|
||||
var result = listSuppliers.execute(SupplierStatus.ACTIVE, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findByStatus fails")
|
||||
void shouldFailWhenFindByStatusFails() {
|
||||
when(supplierRepository.findByStatus(SupplierStatus.ACTIVE))
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(supplierRepository.findAll(SupplierStatus.ACTIVE, pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listSuppliers.executeByStatus(SupplierStatus.ACTIVE);
|
||||
var result = listSuppliers.execute(SupplierStatus.ACTIVE, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(SupplierError.RepositoryFailure.class);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package de.effigenix.application.production;
|
||||
|
||||
import de.effigenix.domain.production.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
|
@ -80,34 +82,39 @@ class ListBatchesTest {
|
|||
@DisplayName("should return all batches")
|
||||
void should_ReturnAllBatches() {
|
||||
var batches = List.of(sampleBatch("b1", BatchStatus.PLANNED), sampleBatch("b2", BatchStatus.PLANNED));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.BATCH_READ)).thenReturn(true);
|
||||
when(batchRepository.findAllSummary()).thenReturn(Result.success(batches));
|
||||
when(batchRepository.findAllSummary(pageRequest))
|
||||
.thenReturn(Result.success(Page.of(batches, 0, 100, 2)));
|
||||
|
||||
var result = listBatches.execute(performedBy);
|
||||
var result = listBatches.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty list when no batches exist")
|
||||
void should_ReturnEmptyList_When_NoBatchesExist() {
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.BATCH_READ)).thenReturn(true);
|
||||
when(batchRepository.findAllSummary()).thenReturn(Result.success(List.of()));
|
||||
when(batchRepository.findAllSummary(pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
var result = listBatches.execute(performedBy);
|
||||
var result = listBatches.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should fail with RepositoryFailure when findAll fails")
|
||||
void should_FailWithRepositoryFailure_When_FindAllFails() {
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.BATCH_READ)).thenReturn(true);
|
||||
when(batchRepository.findAllSummary()).thenReturn(Result.failure(DB_ERROR));
|
||||
when(batchRepository.findAllSummary(pageRequest)).thenReturn(Result.failure(DB_ERROR));
|
||||
|
||||
var result = listBatches.execute(performedBy);
|
||||
var result = listBatches.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(BatchError.RepositoryFailure.class);
|
||||
|
|
@ -118,7 +125,7 @@ class ListBatchesTest {
|
|||
void should_FailWithUnauthorized() {
|
||||
when(authPort.can(performedBy, ProductionAction.BATCH_READ)).thenReturn(false);
|
||||
|
||||
var result = listBatches.execute(performedBy);
|
||||
var result = listBatches.execute(performedBy, PageRequest.of(0, 100));
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(BatchError.Unauthorized.class);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package de.effigenix.application.production;
|
||||
|
||||
import de.effigenix.domain.production.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
|
|
@ -61,14 +63,16 @@ class ListProductionOrdersTest {
|
|||
@Test
|
||||
@DisplayName("should list all orders")
|
||||
void should_ListAll() {
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.PRODUCTION_ORDER_READ)).thenReturn(true);
|
||||
when(productionOrderRepository.findAll()).thenReturn(Result.success(List.of(sampleOrder())));
|
||||
when(productionOrderRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.of(List.of(sampleOrder()), 0, 100, 1)));
|
||||
|
||||
var result = listProductionOrders.execute(performedBy);
|
||||
var result = listProductionOrders.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(1);
|
||||
verify(productionOrderRepository).findAll();
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(1);
|
||||
verify(productionOrderRepository).findAll(pageRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -118,7 +122,7 @@ class ListProductionOrdersTest {
|
|||
void should_Fail_When_Unauthorized() {
|
||||
when(authPort.can(performedBy, ProductionAction.PRODUCTION_ORDER_READ)).thenReturn(false);
|
||||
|
||||
var result = listProductionOrders.execute(performedBy);
|
||||
var result = listProductionOrders.execute(performedBy, PageRequest.of(0, 100));
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ProductionOrderError.Unauthorized.class);
|
||||
|
|
@ -128,11 +132,12 @@ class ListProductionOrdersTest {
|
|||
@Test
|
||||
@DisplayName("should fail when repository returns error")
|
||||
void should_Fail_When_RepositoryError() {
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.PRODUCTION_ORDER_READ)).thenReturn(true);
|
||||
when(productionOrderRepository.findAll())
|
||||
when(productionOrderRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.failure(new RepositoryError.DatabaseError("connection lost")));
|
||||
|
||||
var result = listProductionOrders.execute(performedBy);
|
||||
var result = listProductionOrders.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(ProductionOrderError.RepositoryFailure.class);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package de.effigenix.application.production;
|
||||
|
||||
import de.effigenix.domain.production.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.common.UnitOfMeasure;
|
||||
|
|
@ -54,13 +56,15 @@ class ListRecipesTest {
|
|||
recipeWithStatus("r1", RecipeStatus.DRAFT),
|
||||
recipeWithStatus("r2", RecipeStatus.ACTIVE)
|
||||
);
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(authPort.can(performedBy, ProductionAction.RECIPE_READ)).thenReturn(true);
|
||||
when(recipeRepository.findAll()).thenReturn(Result.success(recipes));
|
||||
when(recipeRepository.findAll(pageRequest))
|
||||
.thenReturn(Result.success(Page.of(recipes, 0, 100, 2)));
|
||||
|
||||
var result = listRecipes.execute(performedBy);
|
||||
var result = listRecipes.execute(performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -82,7 +86,7 @@ class ListRecipesTest {
|
|||
void should_FailWithUnauthorized_When_ActorLacksPermission() {
|
||||
when(authPort.can(performedBy, ProductionAction.RECIPE_READ)).thenReturn(false);
|
||||
|
||||
var result = listRecipes.execute(performedBy);
|
||||
var result = listRecipes.execute(performedBy, PageRequest.of(0, 100));
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(RecipeError.Unauthorized.class);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.shared;
|
|||
|
||||
import de.effigenix.shared.common.Country;
|
||||
import de.effigenix.shared.common.CountryRepository;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
|
|
@ -23,12 +25,45 @@ class ListCountriesTest {
|
|||
@InjectMocks
|
||||
private ListCountries listCountries;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToFindAllWithPageRequest() {
|
||||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
var pageRequest = PageRequest.of(0, 100);
|
||||
when(countryRepository.findAll(pageRequest))
|
||||
.thenReturn(Page.of(expected, 0, 100, 1));
|
||||
|
||||
var result = listCountries.execute(pageRequest);
|
||||
|
||||
assertThat(result.content()).isEqualTo(expected);
|
||||
verify(countryRepository).findAll(pageRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDelegateToSearchWhenQueryIsProvided() {
|
||||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
when(countryRepository.search("deutsch")).thenReturn(expected);
|
||||
|
||||
var result = listCountries.search("deutsch");
|
||||
|
||||
assertThat(result).isEqualTo(expected);
|
||||
verify(countryRepository).search("deutsch");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyListWhenNoMatch() {
|
||||
when(countryRepository.search("xyz")).thenReturn(List.of());
|
||||
|
||||
var result = listCountries.search("xyz");
|
||||
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDelegateToFindAllWhenQueryIsNull() {
|
||||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
when(countryRepository.findAll()).thenReturn(expected);
|
||||
|
||||
var result = listCountries.execute(null);
|
||||
var result = listCountries.search(null);
|
||||
|
||||
assertThat(result).isEqualTo(expected);
|
||||
verify(countryRepository).findAll();
|
||||
|
|
@ -39,38 +74,18 @@ class ListCountriesTest {
|
|||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
when(countryRepository.findAll()).thenReturn(expected);
|
||||
|
||||
var result = listCountries.execute(" ");
|
||||
var result = listCountries.search(" ");
|
||||
|
||||
assertThat(result).isEqualTo(expected);
|
||||
verify(countryRepository).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDelegateToSearchWhenQueryIsProvided() {
|
||||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
when(countryRepository.search("deutsch")).thenReturn(expected);
|
||||
|
||||
var result = listCountries.execute("deutsch");
|
||||
|
||||
assertThat(result).isEqualTo(expected);
|
||||
verify(countryRepository).search("deutsch");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEmptyListWhenNoMatch() {
|
||||
when(countryRepository.search("xyz")).thenReturn(List.of());
|
||||
|
||||
var result = listCountries.execute("xyz");
|
||||
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDelegateToFindAllWhenQueryIsEmpty() {
|
||||
var expected = List.of(new Country("DE", "Deutschland"));
|
||||
when(countryRepository.findAll()).thenReturn(expected);
|
||||
|
||||
var result = listCountries.execute("");
|
||||
var result = listCountries.search("");
|
||||
|
||||
assertThat(result).isEqualTo(expected);
|
||||
verify(countryRepository).findAll();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package de.effigenix.application.usermanagement;
|
|||
|
||||
import de.effigenix.application.usermanagement.dto.UserDTO;
|
||||
import de.effigenix.domain.usermanagement.*;
|
||||
import de.effigenix.shared.common.Page;
|
||||
import de.effigenix.shared.common.PageRequest;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.security.ActorId;
|
||||
import de.effigenix.shared.security.AuthorizationPort;
|
||||
|
|
@ -32,6 +34,7 @@ class ListUsersTest {
|
|||
private ActorId performedBy;
|
||||
private User user1;
|
||||
private User user2;
|
||||
private final PageRequest pageRequest = PageRequest.of(0, 100);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
|
@ -53,13 +56,14 @@ class ListUsersTest {
|
|||
@DisplayName("should_ReturnAllUsers_When_Authorized")
|
||||
void should_ReturnAllUsers_When_Authorized() {
|
||||
when(authPort.can(performedBy, UserManagementAction.USER_LIST)).thenReturn(true);
|
||||
when(userRepository.findAll()).thenReturn(Result.success(List.of(user1, user2)));
|
||||
when(userRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.of(List.of(user1, user2), 0, 100, 2)));
|
||||
|
||||
Result<UserError, List<UserDTO>> result = listUsers.execute(performedBy);
|
||||
Result<UserError, Page<UserDTO>> result = listUsers.execute(null, performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue()).extracting(UserDTO::username)
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).extracting(UserDTO::username)
|
||||
.containsExactlyInAnyOrder("john.doe", "jane.doe");
|
||||
}
|
||||
|
||||
|
|
@ -67,12 +71,13 @@ class ListUsersTest {
|
|||
@DisplayName("should_ReturnEmptyList_When_NoUsersExist")
|
||||
void should_ReturnEmptyList_When_NoUsersExist() {
|
||||
when(authPort.can(performedBy, UserManagementAction.USER_LIST)).thenReturn(true);
|
||||
when(userRepository.findAll()).thenReturn(Result.success(List.of()));
|
||||
when(userRepository.findAll(null, pageRequest))
|
||||
.thenReturn(Result.success(Page.empty(100)));
|
||||
|
||||
Result<UserError, List<UserDTO>> result = listUsers.execute(performedBy);
|
||||
Result<UserError, Page<UserDTO>> result = listUsers.execute(null, performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).isEmpty();
|
||||
assertThat(result.unsafeGetValue().content()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -80,23 +85,24 @@ class ListUsersTest {
|
|||
void should_FailWithUnauthorized_When_ActorLacksPermission() {
|
||||
when(authPort.can(performedBy, UserManagementAction.USER_LIST)).thenReturn(false);
|
||||
|
||||
Result<UserError, List<UserDTO>> result = listUsers.execute(performedBy);
|
||||
Result<UserError, Page<UserDTO>> result = listUsers.execute(null, performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(UserError.Unauthorized.class);
|
||||
verify(userRepository, never()).findAll();
|
||||
verify(userRepository, never()).findAll(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should_ReturnBranchUsers_When_FilteredByBranch")
|
||||
void should_ReturnBranchUsers_When_FilteredByBranch() {
|
||||
when(authPort.can(performedBy, UserManagementAction.USER_LIST)).thenReturn(true);
|
||||
when(userRepository.findByBranchId("branch-1")).thenReturn(Result.success(List.of(user1, user2)));
|
||||
when(userRepository.findAll("branch-1", pageRequest))
|
||||
.thenReturn(Result.success(Page.of(List.of(user1, user2), 0, 100, 2)));
|
||||
|
||||
Result<UserError, List<UserDTO>> result = listUsers.executeForBranch(BranchId.of("branch-1"), performedBy);
|
||||
Result<UserError, Page<UserDTO>> result = listUsers.execute("branch-1", performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isSuccess()).isTrue();
|
||||
assertThat(result.unsafeGetValue()).hasSize(2);
|
||||
assertThat(result.unsafeGetValue().content()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -104,10 +110,10 @@ class ListUsersTest {
|
|||
void should_FailWithUnauthorized_When_ActorLacksPermissionForBranchList() {
|
||||
when(authPort.can(performedBy, UserManagementAction.USER_LIST)).thenReturn(false);
|
||||
|
||||
Result<UserError, List<UserDTO>> result = listUsers.executeForBranch(BranchId.of("branch-1"), performedBy);
|
||||
Result<UserError, Page<UserDTO>> result = listUsers.execute("branch-1", performedBy, pageRequest);
|
||||
|
||||
assertThat(result.isFailure()).isTrue();
|
||||
assertThat(result.unsafeGetError()).isInstanceOf(UserError.Unauthorized.class);
|
||||
verify(userRepository, never()).findByBranchId(anyString());
|
||||
verify(userRepository, never()).findAll(any(), any());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ package de.effigenix.domain.production;
|
|||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||
import de.effigenix.shared.common.Quantity;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.common.UnitOfMeasure;
|
||||
import de.effigenix.shared.common.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
|
@ -237,6 +234,7 @@ class BatchTraceabilityServiceFuzzTest {
|
|||
@Override public Result<RepositoryError, List<Batch>> findByStatus(BatchStatus s) { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, List<Batch>> findByProductionDate(LocalDate d) { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, List<Batch>> findByRecipeIds(List<RecipeId> ids) { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, Page<Batch>> findAllSummary(PageRequest pr) { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, List<Batch>> findAllSummary() { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, List<Batch>> findByStatusSummary(BatchStatus s) { throw new UnsupportedOperationException(); }
|
||||
@Override public Result<RepositoryError, List<Batch>> findByProductionDateSummary(LocalDate d) { throw new UnsupportedOperationException(); }
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ class InventoryCountControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/inventory-counts")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -175,11 +175,10 @@ class InventoryCountControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.andExpect(status().isCreated());
|
||||
|
||||
mockMvc.perform(get("/api/inventory/inventory-counts")
|
||||
.param("storageLocationId", storageLocationId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].storageLocationId").value(storageLocationId));
|
||||
.andExpect(jsonPath("$.content.length()").value(1))
|
||||
.andExpect(jsonPath("$.content[0].storageLocationId").value(storageLocationId));
|
||||
}
|
||||
|
||||
// ==================== Security ====================
|
||||
|
|
@ -298,7 +297,7 @@ class InventoryCountControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("storageLocationId", UUID.randomUUID().toString())
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
|
||||
// ==================== US-6.2: Inventur starten ====================
|
||||
|
|
@ -554,8 +553,8 @@ class InventoryCountControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("movementType", "ADJUSTMENT")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$[0].movementType").value("ADJUSTMENT"));
|
||||
.andExpect(jsonPath("$.content.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$.content[0].movementType").value("ADJUSTMENT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -783,8 +782,8 @@ class InventoryCountControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/inventory-counts?status=OPEN")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].status").value("OPEN"));
|
||||
.andExpect(jsonPath("$.content.length()").value(1))
|
||||
.andExpect(jsonPath("$.content[0].status").value("OPEN"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -924,7 +924,7 @@ class StockControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/stocks")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(2));
|
||||
.andExpect(jsonPath("$.content.length()").value(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -938,8 +938,8 @@ class StockControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("storageLocationId", storageLocationId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].storageLocationId").value(storageLocationId));
|
||||
.andExpect(jsonPath("$.content.length()").value(1))
|
||||
.andExpect(jsonPath("$.content[0].storageLocationId").value(storageLocationId));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -952,8 +952,8 @@ class StockControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("articleId", articleId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].articleId").value(articleId));
|
||||
.andExpect(jsonPath("$.content.length()").value(1))
|
||||
.andExpect(jsonPath("$.content[0].articleId").value(articleId));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -962,7 +962,7 @@ class StockControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/stocks")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -974,9 +974,9 @@ class StockControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/stocks")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].batches.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].totalQuantity").value(10))
|
||||
.andExpect(jsonPath("$[0].availableQuantity").value(10));
|
||||
.andExpect(jsonPath("$.content[0].batches.length()").value(1))
|
||||
.andExpect(jsonPath("$.content[0].totalQuantity").value(10))
|
||||
.andExpect(jsonPath("$.content[0].availableQuantity").value(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -407,8 +407,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/stock-movements")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -420,7 +420,7 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("stockId", stockId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
.andExpect(jsonPath("$.content").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -432,7 +432,7 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("movementType", "GOODS_RECEIPT")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
.andExpect(jsonPath("$.content").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -444,8 +444,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("articleId", articleId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -472,8 +472,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/stock-movements")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -485,8 +485,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("batchReference", "CHARGE-001")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -499,8 +499,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("to", "2030-12-31T23:59:59Z")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -512,8 +512,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("from", "2020-01-01T00:00:00Z")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -525,8 +525,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("to", "2030-12-31T23:59:59Z")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(1));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -550,7 +550,7 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("batchReference", "CHARGE-001")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
.andExpect(jsonPath("$.content").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -572,8 +572,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("batchReference", "UNKNOWN-CHARGE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -586,8 +586,8 @@ class StockMovementControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("to", "2099-12-31T23:59:59Z")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isArray())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content").isArray())
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -500,11 +500,11 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/storage-locations")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(2)))
|
||||
.andExpect(jsonPath("$[*].name", containsInAnyOrder("Lager A", "Lager B")))
|
||||
.andExpect(jsonPath("$[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].storageType").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].active").isBoolean());
|
||||
.andExpect(jsonPath("$.content", hasSize(2)))
|
||||
.andExpect(jsonPath("$.content[*].name", containsInAnyOrder("Lager A", "Lager B")))
|
||||
.andExpect(jsonPath("$.content[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].storageType").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].active").isBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -518,8 +518,8 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("storageType", "COLD_ROOM")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].storageType").value("COLD_ROOM"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].storageType").value("COLD_ROOM"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -537,8 +537,8 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("active", "true")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Aktiv"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].name").value("Aktiv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -555,8 +555,8 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("active", "false")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Inaktiv"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].name").value("Inaktiv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -575,8 +575,8 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("active", "true")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Kühl Aktiv"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].name").value("Kühl Aktiv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -595,8 +595,8 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("active", "false")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Kühl Inaktiv"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].name").value("Kühl Inaktiv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -617,7 +617,7 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/storage-locations")
|
||||
.header("Authorization", "Bearer " + readerToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -641,7 +641,7 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/storage-locations")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(0)));
|
||||
.andExpect(jsonPath("$.content", hasSize(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -652,12 +652,12 @@ class StorageLocationControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/inventory/storage-locations")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].name").value("Vollständig"))
|
||||
.andExpect(jsonPath("$[0].storageType").value("COLD_ROOM"))
|
||||
.andExpect(jsonPath("$[0].temperatureRange.minTemperature").value(-2))
|
||||
.andExpect(jsonPath("$[0].temperatureRange.maxTemperature").value(8))
|
||||
.andExpect(jsonPath("$[0].active").value(true));
|
||||
.andExpect(jsonPath("$.content[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].name").value("Vollständig"))
|
||||
.andExpect(jsonPath("$.content[0].storageType").value("COLD_ROOM"))
|
||||
.andExpect(jsonPath("$.content[0].temperatureRange.minTemperature").value(-2))
|
||||
.andExpect(jsonPath("$.content[0].temperatureRange.maxTemperature").value(8))
|
||||
.andExpect(jsonPath("$.content[0].active").value(true));
|
||||
}
|
||||
|
||||
// ==================== Hilfsmethoden ====================
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ class ArticleControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "ACTIVE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].status", everyItem(is("ACTIVE"))));
|
||||
.andExpect(jsonPath("$.content[*].status", everyItem(is("ACTIVE"))));
|
||||
}
|
||||
|
||||
// ==================== TC-ART-07: Verkaufseinheit hinzufügen ====================
|
||||
|
|
@ -372,21 +372,19 @@ class ArticleControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.andExpect(jsonPath("$.supplierIds", hasSize(0)));
|
||||
}
|
||||
|
||||
// ==================== Artikel nach Kategorie filtern ====================
|
||||
// ==================== Artikel auflisten ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("Artikel nach categoryId filtern → nur passende zurückgegeben")
|
||||
void filterByCategory_returnsOnlyMatching() throws Exception {
|
||||
String otherCategoryId = createCategory("Milchprodukte");
|
||||
@DisplayName("Alle Artikel auflisten → alle vorhanden")
|
||||
void listArticles_returnsAll() throws Exception {
|
||||
createArticle("Äpfel", "FI-001", Unit.PIECE_FIXED, PriceModel.FIXED, "1.99");
|
||||
String otherCategoryId = createCategory("Milchprodukte");
|
||||
createArticleInCategory("Milch", "MI-001", Unit.KG, PriceModel.WEIGHT_BASED, "1.29", otherCategoryId);
|
||||
|
||||
mockMvc.perform(get("/api/articles")
|
||||
.param("categoryId", otherCategoryId)
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Milch"));
|
||||
.andExpect(jsonPath("$.content", hasSize(2)));
|
||||
}
|
||||
|
||||
// ==================== Artikel aktualisieren ====================
|
||||
|
|
|
|||
|
|
@ -181,45 +181,15 @@ class CustomerControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
// ==================== TC-CUS-06: Filter ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("TC-CUS-06: Nur B2B-Kunden filtern → nur B2B")
|
||||
void listCustomers_filterByB2B_returnsOnlyB2B() throws Exception {
|
||||
@DisplayName("TC-CUS-06: Alle Kunden auflisten → verschiedene Typen enthalten")
|
||||
void listCustomers_returnsAll() throws Exception {
|
||||
createB2bCustomer("Gastro GmbH");
|
||||
createB2cCustomer("Max Mustermann");
|
||||
|
||||
mockMvc.perform(get("/api/customers")
|
||||
.param("type", "B2B")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].type", everyItem(is("B2B"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("TC-CUS-06: Nur B2C-Kunden filtern → nur B2C")
|
||||
void listCustomers_filterByB2C_returnsOnlyB2C() throws Exception {
|
||||
createB2bCustomer("Gastro GmbH");
|
||||
createB2cCustomer("Max Mustermann");
|
||||
|
||||
mockMvc.perform(get("/api/customers")
|
||||
.param("type", "B2C")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].type", everyItem(is("B2C"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("TC-CUS-06: Nur aktive Kunden filtern → nur ACTIVE")
|
||||
void listCustomers_filterByActive_returnsOnlyActive() throws Exception {
|
||||
String id = createB2cCustomer("Inaktiver Kunde");
|
||||
mockMvc.perform(post("/api/customers/{id}/deactivate", id)
|
||||
.header("Authorization", "Bearer " + adminToken)).andReturn();
|
||||
|
||||
createB2cCustomer("Aktiver Kunde");
|
||||
|
||||
mockMvc.perform(get("/api/customers")
|
||||
.param("status", "ACTIVE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].status", everyItem(is("ACTIVE"))));
|
||||
.andExpect(jsonPath("$.content", hasSize(greaterThanOrEqualTo(2))));
|
||||
}
|
||||
|
||||
// ==================== TC-CUS-07: Lieferadresse hinzufügen ====================
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class ProductCategoryControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/categories")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[?(@.id == '" + categoryId + "')]").isEmpty());
|
||||
.andExpect(jsonPath("$.content[?(@.id == '" + categoryId + "')]").isEmpty());
|
||||
}
|
||||
|
||||
// ==================== TC-CAT-06: Leerer Name wird abgelehnt ====================
|
||||
|
|
@ -160,7 +160,7 @@ class ProductCategoryControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/categories")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2))));
|
||||
.andExpect(jsonPath("$.content", hasSize(greaterThanOrEqualTo(2))));
|
||||
}
|
||||
|
||||
// ==================== TC-AUTH: Autorisierung ====================
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ class SupplierControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "ACTIVE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].status", everyItem(is("ACTIVE"))));
|
||||
.andExpect(jsonPath("$.content[*].status", everyItem(is("ACTIVE"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -187,7 +187,7 @@ class SupplierControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "INACTIVE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[*].status", everyItem(is("INACTIVE"))));
|
||||
.andExpect(jsonPath("$.content[*].status", everyItem(is("INACTIVE"))));
|
||||
}
|
||||
|
||||
// ==================== TC-SUP-07: Lieferant bewerten ====================
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/production/batches")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(2)))
|
||||
.andExpect(jsonPath("$[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].batchNumber").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].status").value("PLANNED"));
|
||||
.andExpect(jsonPath("$.content", hasSize(2)))
|
||||
.andExpect(jsonPath("$.content[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].batchNumber").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].status").value("PLANNED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -54,7 +54,7 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/production/batches")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(0)));
|
||||
.andExpect(jsonPath("$.content", hasSize(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -66,8 +66,8 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "PLANNED")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].status").value("PLANNED"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].status").value("PLANNED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -90,8 +90,8 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("productionDate", "2026-03-01")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].productionDate").value("2026-03-01"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].productionDate").value("2026-03-01"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -103,7 +103,7 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("articleId", "article-123")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -113,7 +113,7 @@ class ListBatchesIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("articleId", "unknown-article")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(0)));
|
||||
.andExpect(jsonPath("$.content", hasSize(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ class ListRecipesIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/recipes")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(2)))
|
||||
.andExpect(jsonPath("$[0].ingredientCount").isNumber())
|
||||
.andExpect(jsonPath("$[0].stepCount").isNumber())
|
||||
.andExpect(jsonPath("$[0].ingredients").doesNotExist())
|
||||
.andExpect(jsonPath("$[0].productionSteps").doesNotExist());
|
||||
.andExpect(jsonPath("$.content", hasSize(2)))
|
||||
.andExpect(jsonPath("$.content[0].ingredientCount").isNumber())
|
||||
.andExpect(jsonPath("$.content[0].stepCount").isNumber())
|
||||
.andExpect(jsonPath("$.content[0].ingredients").doesNotExist())
|
||||
.andExpect(jsonPath("$.content[0].productionSteps").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -62,9 +62,9 @@ class ListRecipesIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "ACTIVE")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name").value("Bratwurst"))
|
||||
.andExpect(jsonPath("$[0].status").value("ACTIVE"));
|
||||
.andExpect(jsonPath("$.content", hasSize(1)))
|
||||
.andExpect(jsonPath("$.content[0].name").value("Bratwurst"))
|
||||
.andExpect(jsonPath("$.content[0].status").value("ACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -83,7 +83,7 @@ class ListRecipesIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/recipes")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(0)));
|
||||
.andExpect(jsonPath("$.content", hasSize(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -915,7 +915,7 @@ class ProductionOrderControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/production/production-orders")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(2)));
|
||||
.andExpect(jsonPath("$.content.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -928,7 +928,7 @@ class ProductionOrderControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "PLANNED")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].status").value("PLANNED"));
|
||||
.andExpect(jsonPath("$.content[0].status").value("PLANNED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -941,7 +941,7 @@ class ProductionOrderControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("dateTo", LocalDate.now().plusDays(30).toString())
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(1)));
|
||||
.andExpect(jsonPath("$.content.length()").value(org.hamcrest.Matchers.greaterThanOrEqualTo(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -955,7 +955,7 @@ class ProductionOrderControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("status", "PLANNED")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].status").value("PLANNED"));
|
||||
.andExpect(jsonPath("$.content[0].status").value("PLANNED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -968,7 +968,7 @@ class ProductionOrderControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.param("dateTo", LocalDate.now().plusYears(11).toString())
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(0));
|
||||
.andExpect(jsonPath("$.content.length()").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package de.effigenix.infrastructure.shared.persistence;
|
||||
|
||||
import de.effigenix.shared.common.SortField;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("PaginationHelper")
|
||||
class PaginationHelperTest {
|
||||
|
||||
private static final Map<String, String> ALLOWED = Map.of(
|
||||
"name", "name",
|
||||
"createdAt", "created_at",
|
||||
"status", "status"
|
||||
);
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty string for empty sort list")
|
||||
void emptySort() {
|
||||
assertThat(PaginationHelper.buildOrderByClause(List.of(), ALLOWED)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty string for null sort list")
|
||||
void nullSort() {
|
||||
assertThat(PaginationHelper.buildOrderByClause(null, ALLOWED)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build single field ORDER BY")
|
||||
void singleField() {
|
||||
var sort = List.of(SortField.desc("createdAt"));
|
||||
assertThat(PaginationHelper.buildOrderByClause(sort, ALLOWED))
|
||||
.isEqualTo(" ORDER BY created_at DESC");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build multi-field ORDER BY")
|
||||
void multiField() {
|
||||
var sort = List.of(SortField.asc("name"), SortField.desc("createdAt"));
|
||||
assertThat(PaginationHelper.buildOrderByClause(sort, ALLOWED))
|
||||
.isEqualTo(" ORDER BY name ASC, created_at DESC");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should ignore unknown fields")
|
||||
void unknownFields() {
|
||||
var sort = List.of(SortField.asc("unknown"), SortField.desc("createdAt"));
|
||||
assertThat(PaginationHelper.buildOrderByClause(sort, ALLOWED))
|
||||
.isEqualTo(" ORDER BY created_at DESC");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should return empty when all fields unknown")
|
||||
void allUnknown() {
|
||||
var sort = List.of(SortField.asc("unknown"));
|
||||
assertThat(PaginationHelper.buildOrderByClause(sort, ALLOWED)).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,12 +15,13 @@ class CountryControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
@Test
|
||||
void shouldReturnCountriesWithDachFirst() throws Exception {
|
||||
mockMvc.perform(get("/api/countries")
|
||||
.param("size", "100")
|
||||
.header("Authorization", "Bearer " + validToken()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(greaterThan(200))))
|
||||
.andExpect(jsonPath("$[0].code").value("DE"))
|
||||
.andExpect(jsonPath("$[1].code").value("AT"))
|
||||
.andExpect(jsonPath("$[2].code").value("CH"));
|
||||
.andExpect(jsonPath("$.page.totalElements", greaterThan(200)))
|
||||
.andExpect(jsonPath("$.content[0].code").value("DE"))
|
||||
.andExpect(jsonPath("$.content[1].code").value("AT"))
|
||||
.andExpect(jsonPath("$.content[2].code").value("CH"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class RoleControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
mockMvc.perform(get("/api/roles")
|
||||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2))));
|
||||
.andExpect(jsonPath("$.content", hasSize(greaterThanOrEqualTo(2))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -207,10 +207,10 @@ class UserControllerIntegrationTest extends AbstractIntegrationTest {
|
|||
.header("Authorization", "Bearer " + adminToken))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2))))
|
||||
.andExpect(jsonPath("$[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].username").isNotEmpty())
|
||||
.andExpect(jsonPath("$[0].email").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content", hasSize(greaterThanOrEqualTo(2))))
|
||||
.andExpect(jsonPath("$.content[0].id").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].username").isNotEmpty())
|
||||
.andExpect(jsonPath("$.content[0].email").isNotEmpty())
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package de.effigenix.shared.common;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@DisplayName("PageRequest")
|
||||
class PageRequestTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("of()")
|
||||
class Of {
|
||||
|
||||
@Test
|
||||
@DisplayName("should create valid page request")
|
||||
void valid() {
|
||||
var pr = PageRequest.of(2, 20);
|
||||
assertThat(pr.page()).isEqualTo(2);
|
||||
assertThat(pr.size()).isEqualTo(20);
|
||||
assertThat(pr.sort()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should create with sort fields")
|
||||
void withSort() {
|
||||
var sort = List.of(SortField.asc("name"), SortField.desc("createdAt"));
|
||||
var pr = PageRequest.of(0, 10, sort);
|
||||
assertThat(pr.sort()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should accept page 0")
|
||||
void pageZero() {
|
||||
var pr = PageRequest.of(0, 20);
|
||||
assertThat(pr.page()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should reject negative page")
|
||||
void negativePage() {
|
||||
assertThatThrownBy(() -> PageRequest.of(-1, 20))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should reject size 0")
|
||||
void sizeZero() {
|
||||
assertThatThrownBy(() -> PageRequest.of(0, 0))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should reject size > 100")
|
||||
void sizeTooBig() {
|
||||
assertThatThrownBy(() -> PageRequest.of(0, 101))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should accept size 100")
|
||||
void sizeMax() {
|
||||
var pr = PageRequest.of(0, 100);
|
||||
assertThat(pr.size()).isEqualTo(100);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("offset()")
|
||||
class Offset {
|
||||
|
||||
@Test
|
||||
@DisplayName("should calculate correct offset")
|
||||
void calculatesOffset() {
|
||||
assertThat(PageRequest.of(0, 20).offset()).isEqualTo(0);
|
||||
assertThat(PageRequest.of(1, 20).offset()).isEqualTo(20);
|
||||
assertThat(PageRequest.of(3, 10).offset()).isEqualTo(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package de.effigenix.shared.common;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("Page")
|
||||
class PageTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("of()")
|
||||
class Of {
|
||||
|
||||
@Test
|
||||
@DisplayName("should create page with calculated totalPages")
|
||||
void calculatesTotalPages() {
|
||||
var page = Page.of(List.of("a", "b"), 0, 2, 5);
|
||||
assertThat(page.content()).containsExactly("a", "b");
|
||||
assertThat(page.number()).isEqualTo(0);
|
||||
assertThat(page.size()).isEqualTo(2);
|
||||
assertThat(page.totalElements()).isEqualTo(5);
|
||||
assertThat(page.totalPages()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should handle exact division")
|
||||
void exactDivision() {
|
||||
var page = Page.of(List.of("a", "b"), 0, 2, 4);
|
||||
assertThat(page.totalPages()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should handle single element")
|
||||
void singleElement() {
|
||||
var page = Page.of(List.of("a"), 0, 20, 1);
|
||||
assertThat(page.totalPages()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("empty()")
|
||||
class Empty {
|
||||
|
||||
@Test
|
||||
@DisplayName("should create empty page")
|
||||
void emptyPage() {
|
||||
var page = Page.<String>empty(20);
|
||||
assertThat(page.content()).isEmpty();
|
||||
assertThat(page.totalElements()).isEqualTo(0);
|
||||
assertThat(page.totalPages()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("map()")
|
||||
class Map {
|
||||
|
||||
@Test
|
||||
@DisplayName("should map content while preserving pagination info")
|
||||
void mapsContent() {
|
||||
var page = Page.of(List.of(1, 2, 3), 0, 10, 3);
|
||||
var mapped = page.map(String::valueOf);
|
||||
assertThat(mapped.content()).containsExactly("1", "2", "3");
|
||||
assertThat(mapped.number()).isEqualTo(0);
|
||||
assertThat(mapped.size()).isEqualTo(10);
|
||||
assertThat(mapped.totalElements()).isEqualTo(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package de.effigenix.shared.common;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@DisplayName("SortField")
|
||||
class SortFieldTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("parse()")
|
||||
class Parse {
|
||||
|
||||
@Test
|
||||
@DisplayName("should parse field with desc direction")
|
||||
void fieldWithDesc() {
|
||||
var sf = SortField.parse("createdAt,desc");
|
||||
assertThat(sf.field()).isEqualTo("createdAt");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.DESC);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should parse field with asc direction")
|
||||
void fieldWithAsc() {
|
||||
var sf = SortField.parse("name,asc");
|
||||
assertThat(sf.field()).isEqualTo("name");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.ASC);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should default to ASC when no direction given")
|
||||
void fieldOnly() {
|
||||
var sf = SortField.parse("name");
|
||||
assertThat(sf.field()).isEqualTo("name");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.ASC);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should be case-insensitive for direction")
|
||||
void caseInsensitive() {
|
||||
var sf = SortField.parse("name,DESC");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.DESC);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should throw on blank input")
|
||||
void blankInput() {
|
||||
assertThatThrownBy(() -> SortField.parse(""))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should throw on null input")
|
||||
void nullInput() {
|
||||
assertThatThrownBy(() -> SortField.parse(null))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("factories")
|
||||
class Factories {
|
||||
|
||||
@Test
|
||||
@DisplayName("asc() should create ascending sort field")
|
||||
void ascFactory() {
|
||||
var sf = SortField.asc("name");
|
||||
assertThat(sf.field()).isEqualTo("name");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.ASC);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("desc() should create descending sort field")
|
||||
void descFactory() {
|
||||
var sf = SortField.desc("createdAt");
|
||||
assertThat(sf.field()).isEqualTo("createdAt");
|
||||
assertThat(sf.direction()).isEqualTo(SortDirection.DESC);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue