From fde12ad5614fac5af5b85e9a4a261d7552cee8c8 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Fri, 31 Jul 2026 10:58:32 +0300 Subject: [PATCH] test persisted set ordering --- backend/tests/Feature/SetsEndpointTest.php | 92 ++++++++++++ .../Unit/Set/UseCases/ReorderSetsTest.php | 135 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 backend/tests/Unit/Set/UseCases/ReorderSetsTest.php diff --git a/backend/tests/Feature/SetsEndpointTest.php b/backend/tests/Feature/SetsEndpointTest.php index b2afe90..d648b40 100644 --- a/backend/tests/Feature/SetsEndpointTest.php +++ b/backend/tests/Feature/SetsEndpointTest.php @@ -73,6 +73,98 @@ class SetsEndpointTest extends TestCase ]); } + public function testReorderSetsRequiresAuthentication(): void + { + $response = $this->putJson('/api/sets/order', [ + 'setIds' => [1, 2], + ]); + + $response->assertUnauthorized(); + $response->assertExactJson([ + 'error' => 'unauthenticated', + ]); + } + + public function testAuthenticatedReorderSetsPersistsPublicOrder(): void + { + $setRepository = app(SetRepository::class); + $firstSet = $setRepository->create(new CreateSetDto( + name: 'First Set', + description: 'First set description', + iconImageUrl: '/assets/first.png', + )); + $secondSet = $setRepository->create(new CreateSetDto( + name: 'Second Set', + description: 'Second set description', + iconImageUrl: '/assets/second.png', + )); + $thirdSet = $setRepository->create(new CreateSetDto( + name: 'Third Set', + description: 'Third set description', + iconImageUrl: '/assets/third.png', + )); + $this->createSession('valid-token'); + + $response = $this->withCredentials() + ->withUnencryptedCookie('auth_token', 'valid-token') + ->putJson('/api/sets/order', [ + 'setIds' => [ + $thirdSet->getId(), + $firstSet->getId(), + $secondSet->getId(), + ], + ]); + + $response->assertOk(); + $response->assertJsonCount(3, 'sets'); + $response->assertJsonPath('sets.0.id', $thirdSet->getId()); + $response->assertJsonPath('sets.1.id', $firstSet->getId()); + $response->assertJsonPath('sets.2.id', $secondSet->getId()); + + $publicResponse = $this->getJson('/api/sets'); + $publicResponse->assertOk(); + $publicResponse->assertJsonPath('sets.0.id', $thirdSet->getId()); + $publicResponse->assertJsonPath('sets.1.id', $firstSet->getId()); + $publicResponse->assertJsonPath('sets.2.id', $secondSet->getId()); + } + + public function testCreatedSetAppendsToSavedOrder(): void + { + $setRepository = app(SetRepository::class); + $firstSet = $setRepository->create(new CreateSetDto( + name: 'First Set', + description: 'First set description', + iconImageUrl: '/assets/first.png', + )); + $secondSet = $setRepository->create(new CreateSetDto( + name: 'Second Set', + description: 'Second set description', + iconImageUrl: '/assets/second.png', + )); + $this->createSession('valid-token'); + $this->withCredentials() + ->withUnencryptedCookie('auth_token', 'valid-token') + ->putJson('/api/sets/order', [ + 'setIds' => [ + $secondSet->getId(), + $firstSet->getId(), + ], + ]) + ->assertOk(); + + $thirdSet = $setRepository->create(new CreateSetDto( + name: 'Third Set', + description: 'Third set description', + iconImageUrl: '/assets/third.png', + )); + + $publicResponse = $this->getJson('/api/sets'); + $publicResponse->assertOk(); + $publicResponse->assertJsonPath('sets.0.id', $secondSet->getId()); + $publicResponse->assertJsonPath('sets.1.id', $firstSet->getId()); + $publicResponse->assertJsonPath('sets.2.id', $thirdSet->getId()); + } + public function testCreateSetRequiresAuthentication(): void { $response = $this->postJson('/api/sets', [ diff --git a/backend/tests/Unit/Set/UseCases/ReorderSetsTest.php b/backend/tests/Unit/Set/UseCases/ReorderSetsTest.php new file mode 100644 index 0000000..e323a72 --- /dev/null +++ b/backend/tests/Unit/Set/UseCases/ReorderSetsTest.php @@ -0,0 +1,135 @@ +setRepository = new FakeSetRepository(); + $this->reorderSets = new ReorderSets($this->setRepository); + } + + public function testReordersEverySet(): void + { + $firstSet = $this->createSet('First Set'); + $secondSet = $this->createSet('Second Set'); + $thirdSet = $this->createSet('Third Set'); + + $sets = $this->reorderSets->execute(new ReorderSetsRequest( + setIds: [ + $thirdSet->getId(), + $firstSet->getId(), + $secondSet->getId(), + ], + )); + + $expectedSetIds = [ + $thirdSet->getId(), + $firstSet->getId(), + $secondSet->getId(), + ]; + $this->assertSame($expectedSetIds, $this->setIds($sets)); + $this->assertSame( + $expectedSetIds, + $this->setIds($this->setRepository->getAll()), + ); + } + + public function testThrowsWhenSetIdsAreMissing(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('setIds is required'); + + $this->reorderSets->execute(new ReorderSetsRequest(setIds: null)); + } + + public function testThrowsWhenSetIdsAreNotIntegers(): void + { + $firstSet = $this->createSet('First Set'); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('setIds must contain integers'); + + $this->reorderSets->execute(new ReorderSetsRequest( + setIds: [$firstSet->getId(), 'invalid'], + )); + } + + public function testThrowsWhenSetIdsContainDuplicates(): void + { + $firstSet = $this->createSet('First Set'); + $secondSet = $this->createSet('Second Set'); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Set order contains duplicate ids'); + + $this->reorderSets->execute(new ReorderSetsRequest( + setIds: [ + $firstSet->getId(), + $firstSet->getId(), + $secondSet->getId(), + ], + )); + } + + public function testThrowsWhenSetOrderContainsUnknownSet(): void + { + $firstSet = $this->createSet('First Set'); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Set order contains invalid set'); + + $this->reorderSets->execute(new ReorderSetsRequest( + setIds: [$firstSet->getId(), 999], + )); + } + + public function testThrowsWhenSetOrderOmitsSet(): void + { + $firstSet = $this->createSet('First Set'); + $this->createSet('Second Set'); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('Set order must include every set'); + + $this->reorderSets->execute(new ReorderSetsRequest( + setIds: [$firstSet->getId()], + )); + } + + private function createSet(string $name): DomainSet + { + return $this->setRepository->create(new CreateSetDto( + name: $name, + description: "$name description", + iconImageUrl: "/assets/$name.png", + )); + } + + /** + * @param DomainSet[] $sets + * @return int[] + */ + private function setIds(array $sets): array + { + $setIds = []; + foreach ($sets as $set) { + $setIds[] = $set->getId(); + } + + return $setIds; + } +}