clear(); }); it('deactivates an active client and dispatches event', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $clientId = new ClientId(Uuid::uuid7()); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32)); $name = new ClientName('Test Gateway 1'); $secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86)); $client = Client::hydrate( id: $clientId, name: $name, identifier: $identifier, secret: $secret, isActive: true, createdAt: new \DateTimeImmutable(), updatedAt: new \DateTimeImmutable(), ); $repository->add($client); $dispatcher->expects('dispatch') ->once() ->withArgs(fn ($event): bool => $event instanceof ClientStatusToggled && $event->clientId->equals($clientId) && $event->isActive === false); $input = new Input($identifier, desiredStatus: false); // WHEN $result = $usecase->execute($input); // THEN expect($result)->toBeInstanceOf(Output::class) ->and($result->clientId)->toBe($clientId) ->and($result->clientIdentifier)->toBe($identifier) ->and($result->clientName)->toBe($name) ->and($result->isActive)->toBeFalse(); $saved = $repository->find($clientId); expect($saved?->isActive)->toBeFalse(); }); it('activates an inactive client and dispatches event', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $clientId = new ClientId(Uuid::uuid7()); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32)); $name = new ClientName('Inactive Client'); $secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86)); $client = Client::hydrate( id: $clientId, name: $name, identifier: $identifier, secret: $secret, isActive: false, createdAt: new \DateTimeImmutable(), updatedAt: new \DateTimeImmutable(), ); $repository->add($client); $dispatcher->expects('dispatch') ->once() ->withArgs(fn ($event): bool => $event instanceof ClientStatusToggled && $event->clientId->equals($clientId) && $event->isActive === true); $input = new Input($identifier, desiredStatus: true); // WHEN $result = $usecase->execute($input); // THEN expect($result)->toBeInstanceOf(Output::class) ->and($result->isActive)->toBeTrue(); $saved = $repository->find($clientId); expect($saved?->isActive)->toBeTrue(); }); it('throws ClientNotFoundException when client does not exist', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('9', 32)); $input = new Input($identifier, desiredStatus: true); // WHEN & THEN expect(fn () => $usecase->execute($input)) ->toThrow(ClientNotFoundException::class); }); it('does not dispatch event when status is already the desired value', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $clientId = new ClientId(Uuid::uuid7()); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32)); $name = new ClientName('Already Active Client'); $secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86)); $client = Client::hydrate( id: $clientId, name: $name, identifier: $identifier, secret: $secret, isActive: true, createdAt: new \DateTimeImmutable(), updatedAt: new \DateTimeImmutable(), ); $repository->add($client); $dispatcher->expects('dispatch')->never(); $input = new Input($identifier, desiredStatus: true); // WHEN $result = $usecase->execute($input); // THEN expect($result)->toBeInstanceOf(Output::class) ->and($result->isActive)->toBeTrue(); $saved = $repository->find($clientId); expect($saved?->isActive)->toBeTrue(); }); it('deactivates an active client when desiredStatus is false', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $clientId = new ClientId(Uuid::uuid7()); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32)); $name = new ClientName('Test Gateway 3'); $secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86)); $client = Client::hydrate( id: $clientId, name: $name, identifier: $identifier, secret: $secret, isActive: true, createdAt: new \DateTimeImmutable(), updatedAt: new \DateTimeImmutable(), ); $repository->add($client); $dispatcher->expects('dispatch') ->once() ->withArgs(fn ($event): bool => $event instanceof ClientStatusToggled && $event->clientId->equals($clientId) && $event->isActive === false); $input = new Input($identifier, desiredStatus: false); // WHEN $result = $usecase->execute($input); // THEN expect($result)->toBeInstanceOf(Output::class) ->and($result->isActive)->toBeFalse(); $saved = $repository->find($clientId); expect($saved?->isActive)->toBeFalse(); }); it('activates an inactive client when desiredStatus is true', function () use ($repository): void { // GIVEN $dispatcher = Mockery::mock(DomainEventDispatcher::class); $usecase = new SetClientStatus($repository, $dispatcher); $clientId = new ClientId(Uuid::uuid7()); $identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32)); $name = new ClientName('Test Gateway 2'); $secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86)); $client = Client::hydrate( id: $clientId, name: $name, identifier: $identifier, secret: $secret, isActive: false, createdAt: new \DateTimeImmutable(), updatedAt: new \DateTimeImmutable(), ); $repository->add($client); $dispatcher->expects('dispatch') ->once() ->withArgs(fn ($event): bool => $event instanceof ClientStatusToggled && $event->clientId->equals($clientId) && $event->isActive === true); $input = new Input($identifier, desiredStatus: true); // WHEN $result = $usecase->execute($input); // THEN expect($result)->toBeInstanceOf(Output::class) ->and($result->isActive)->toBeTrue(); $saved = $repository->find($clientId); expect($saved?->isActive)->toBeTrue(); }); });