From 19c1c5395e9ab59d90fd9b933bdc6f4295358e4c Mon Sep 17 00:00:00 2001 From: Supun Wimalasena Date: Sun, 1 Feb 2026 15:45:20 +0100 Subject: [PATCH 1/4] wip phpstan, phpunit --- CHANGELOG.md | 3 + bundle/src/Api/ApiExceptionListener.php | 10 ++- bundle/src/Api/SudoAuthorizationListener.php | 5 +- bundle/src/BillingFakeLicenseProvider.php | 14 +-- bundle/src/Command/Sudo/SudoAddCommand.php | 5 +- bundle/src/Comms/Comms.php | 2 +- bundle/src/Comms/MockComms.php | 13 +-- .../EventDispatcher/TestEventDispatcher.php | 17 +--- compose.yaml | 6 +- phpstan.neon => phpstan.dist.neon | 0 phpunit.xml => phpunit.dist.xml | 0 src/Auth/AuthFake.php | 3 +- src/Auth/Oidc/OidcAuth.php | 8 +- src/Billing/BillingFake.php | 23 +++-- src/Billing/License/Plan/PlanAbstract.php | 4 +- src/Billing/License/PostLicense.php | 2 +- src/InternalFake.php | 24 +++--- src/Laravel/AuthController.php | 64 -------------- src/routes/auth.php | 11 --- .../Api/AbstractApiExceptionListenerTest.php | 12 +++ .../Bundle/BillingFakeLicenseProviderTest.php | 7 +- .../Command/Sudo/SudoAddCommandTest.php | 5 +- .../Command/Sudo/SudoRemoveCommandTest.php | 5 +- tests/Bundle/Controller/OidcCallbackTest.php | 4 +- tests/Bundle/Testing/ApiTestingTraitTest.php | 5 +- tests/Feature/Auth/AuthRoutesLaravelTest.php | 86 ------------------- tests/Feature/ServiceProvider/FakeTest.php | 4 +- .../ServiceProvider/internalfakextended.php | 6 +- tests/SymfonyTestCase.php | 11 ++- tests/Unit/Auth/AuthTestTrait.php | 6 +- tests/Unit/Auth/Oidc/OidcAuthTest.php | 8 +- tests/Unit/Billing/BillingFakeLaravelTest.php | 8 +- tests/Unit/Billing/BillingFakeSymfonyTest.php | 3 +- tests/Unit/Billing/BillingFakeTestTrait.php | 66 ++++++-------- tests/Unit/Billing/BillingLaravelTest.php | 4 - tests/Unit/Billing/BillingSymfonyTest.php | 8 +- tests/Unit/Billing/BillingTestTrait.php | 34 ++++---- tests/Unit/Billing/LicenseTest.php | 1 - .../Billing/Usage/ExampleStorageUsage.php | 33 ------- .../Unit/Billing/Usage/UsageAbstractTest.php | 31 ------- .../Middleware/AuthMiddlewareLaravelTest.php | 38 -------- tests/Unit/InternalConfigTest.php | 12 ++- tests/Unit/Laravel/LogFakeLaravelTest.php | 50 ----------- 43 files changed, 165 insertions(+), 496 deletions(-) rename phpstan.neon => phpstan.dist.neon (100%) rename phpunit.xml => phpunit.dist.xml (100%) delete mode 100644 src/Laravel/AuthController.php delete mode 100644 src/routes/auth.php delete mode 100644 tests/Feature/Auth/AuthRoutesLaravelTest.php delete mode 100644 tests/Unit/Billing/Usage/ExampleStorageUsage.php delete mode 100644 tests/Unit/Billing/Usage/UsageAbstractTest.php delete mode 100644 tests/Unit/Http/Middleware/AuthMiddlewareLaravelTest.php delete mode 100644 tests/Unit/Laravel/LogFakeLaravelTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f1682..c2b7266 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Organization support - Hyvor\Internal\Laravel\LogFake removed - TestEventDispatcher moved + - ::enable() is removed, and no longer needed. Test env automatically sets event_dispatcher to TestEventDispatcher - BillingInterface license() and licenses() method signatures changed - Comms API - a shared COMMS_KEY env variable is required for component-to-componet communication @@ -16,6 +17,8 @@ - AuthMethod removed. Deployment added. - CommsInterface instead of using Comms directly - UsageAbstract removed +- AuthMiddleware removed in Laravel +- Laravel built-in auth routes removed (/api/auth/check, /api/auth/login, etc.) ## 3.1.8 - 2025-11-03 diff --git a/bundle/src/Api/ApiExceptionListener.php b/bundle/src/Api/ApiExceptionListener.php index b74d6ae..5eb9e00 100644 --- a/bundle/src/Api/ApiExceptionListener.php +++ b/bundle/src/Api/ApiExceptionListener.php @@ -108,10 +108,12 @@ private function hideEnum(string $message): string '/App\\\\[A-Za-z0-9_\\\\]+/', function ($matches) { $class = $matches[0]; - // it should definitely be an enum - assert(enum_exists($class)); - $values = array_column($class::cases(), 'value'); - return implode('|', $values); + if (enum_exists($class)) { + $values = array_column($class::cases(), 'value'); + return implode('|', $values); + } else { + return $class; + } }, $message ); diff --git a/bundle/src/Api/SudoAuthorizationListener.php b/bundle/src/Api/SudoAuthorizationListener.php index 86e7ae9..e750318 100644 --- a/bundle/src/Api/SudoAuthorizationListener.php +++ b/bundle/src/Api/SudoAuthorizationListener.php @@ -36,9 +36,9 @@ public function __invoke(ControllerEvent $event): void } $request = $event->getRequest(); - $user = $this->auth->check($request); + $me = $this->auth->me($request); - if ($user === false) { + if (!$me) { throw new DataCarryingHttpException( 403, [ @@ -48,6 +48,7 @@ public function __invoke(ControllerEvent $event): void ); } + $user = $me->getUser(); $sudoUser = $this->sudoUserService->get($user->id); if ($sudoUser === null) { diff --git a/bundle/src/BillingFakeLicenseProvider.php b/bundle/src/BillingFakeLicenseProvider.php index 0b88045..c9a695c 100644 --- a/bundle/src/BillingFakeLicenseProvider.php +++ b/bundle/src/BillingFakeLicenseProvider.php @@ -2,9 +2,8 @@ namespace Hyvor\Internal\Bundle; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\License; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalFake; @@ -21,17 +20,18 @@ public function __construct(string $internalFakeClass) $this->internalFake = new $internalFakeClass(); } - public function license(int $userId, ?int $blogId, Component $component): ?License + public function license(int $userId, Component $component): ?License { - return $this->internalFake->license($userId, $blogId, $component); + return $this->internalFake->license($userId, $component); } /** - * @param LicenseOf[] $of + * @param int[] $organizationIds + * @return array */ - public function licenses(array $of, Component $component): LicensesCollection + public function licenses(array $organizationIds, Component $component): array { - return $this->internalFake->licenses($of, $component); + return $this->internalFake->licenses($organizationIds, $component); } } diff --git a/bundle/src/Command/Sudo/SudoAddCommand.php b/bundle/src/Command/Sudo/SudoAddCommand.php index 01cc8e0..bd4782f 100644 --- a/bundle/src/Command/Sudo/SudoAddCommand.php +++ b/bundle/src/Command/Sudo/SudoAddCommand.php @@ -47,6 +47,7 @@ public function __invoke( if (count($usersWithThatEmail) === 1) { $user = $usersWithThatEmail[0]; } else { + /** @var array<\Stringable> $answers */ $answers = array_map(fn($u) => $this->userRow($u), $usersWithThatEmail); $helper = new QuestionHelper(); $question = new ChoiceQuestion( @@ -84,7 +85,7 @@ public function __invoke( private function userRow(AuthUser $user): object { - return new readonly class($user) { + return new readonly class($user) implements \Stringable { public function __construct(public AuthUser $user) { @@ -107,4 +108,4 @@ public function __toString(): string }; } -} \ No newline at end of file +} diff --git a/bundle/src/Comms/Comms.php b/bundle/src/Comms/Comms.php index 6285084..0f82a52 100644 --- a/bundle/src/Comms/Comms.php +++ b/bundle/src/Comms/Comms.php @@ -116,7 +116,7 @@ public function sendAsync(AbstractEvent $event, ?Component $to = null, string $t ]); } - public function validateAndGetTo(AbstractEvent $event, ?Component $to): Component + protected function validateAndGetTo(AbstractEvent $event, ?Component $to): Component { $allowedFrom = $event->from(); $allowedTo = $event->to(); diff --git a/bundle/src/Comms/MockComms.php b/bundle/src/Comms/MockComms.php index 1203384..7b1af56 100644 --- a/bundle/src/Comms/MockComms.php +++ b/bundle/src/Comms/MockComms.php @@ -6,9 +6,7 @@ use Hyvor\Internal\Component\Component; use PHPUnit\Framework\Assert; -class MockComms implements CommsInterface { - - public function __construct(private Comms $comms) {} +class MockComms extends Comms { /** * @var array{event: AbstractEvent, to: Component, async: bool}[] @@ -20,14 +18,9 @@ public function __construct(private Comms $comms) {} */ private array $responses = []; - public function signature(string $content): string - { - throw new \RuntimeException('not implemented'); - } - public function send(AbstractEvent $event, ?Component $to = null,): object|null { - $to = $this->comms->validateAndGetTo($event, $to); + $to = $this->validateAndGetTo($event, $to); $this->sent[] = [ 'event' => $event, @@ -47,7 +40,7 @@ public function send(AbstractEvent $event, ?Component $to = null,): object|null public function sendAsync(AbstractEvent $event, ?Component $to = null, string $transport = 'async'): void { - $to = $this->comms->validateAndGetTo($event, $to); + $to = $this->validateAndGetTo($event, $to); $this->sent[] = [ 'event' => $event, diff --git a/bundle/src/EventDispatcher/TestEventDispatcher.php b/bundle/src/EventDispatcher/TestEventDispatcher.php index 32bc165..a2b8c62 100644 --- a/bundle/src/EventDispatcher/TestEventDispatcher.php +++ b/bundle/src/EventDispatcher/TestEventDispatcher.php @@ -90,19 +90,4 @@ public function assertDispatchedCount(string $eventName, int $count): void ); } - /** - * @param false|string[] $mockEvents false to not mock any events or an array of event names to mock. - * Listeners of those events will not be called when the event is dispatched. - * Useful to prevent side effects. - */ - public static function enable(Container $container, false|array $mockEvents = false): self - { - $dispatcher = new self($mockEvents); - $container->set( - EventDispatcherInterface::class, - $dispatcher - ); - return $dispatcher; - } - -} \ No newline at end of file +} diff --git a/compose.yaml b/compose.yaml index 7f94873..a8d8bf0 100644 --- a/compose.yaml +++ b/compose.yaml @@ -13,6 +13,6 @@ services: - ./types:/app/types - ./composer.json:/app/composer.json - ./composer.lock:/app/composer.lock - - ./phpunit.xml:/app/phpunit.xml - - ./phpstan.neon:/app/phpstan.neon - - ./extension.neon:/app/extension.neon \ No newline at end of file + - ./phpunit.dist.xml:/app/phpunit.dist.xml + - ./phpstan.dist.neon:/app/phpstan.dist.neon + - ./extension.neon:/app/extension.neon diff --git a/phpstan.neon b/phpstan.dist.neon similarity index 100% rename from phpstan.neon rename to phpstan.dist.neon diff --git a/phpunit.xml b/phpunit.dist.xml similarity index 100% rename from phpunit.xml rename to phpunit.dist.xml diff --git a/src/Auth/AuthFake.php b/src/Auth/AuthFake.php index c410705..a14b9ca 100644 --- a/src/Auth/AuthFake.php +++ b/src/Auth/AuthFake.php @@ -86,8 +86,7 @@ public static function enableForSymfony( public function me(string|Request $request): ?Me { - return null; // TODO - return $this->user ?: false; + return $this->user ? new Me($this->user, null) : null; } public function authUrl(string $page, null|string|Request $redirect = null): string diff --git a/src/Auth/Oidc/OidcAuth.php b/src/Auth/Oidc/OidcAuth.php index 9c74aaa..265ebb9 100644 --- a/src/Auth/Oidc/OidcAuth.php +++ b/src/Auth/Oidc/OidcAuth.php @@ -5,6 +5,7 @@ use Hyvor\Internal\Auth\Auth; use Hyvor\Internal\Auth\AuthInterface; use Hyvor\Internal\Auth\AuthUser; +use Hyvor\Internal\Auth\AuthUserOrganization; use Hyvor\Internal\Auth\Dto\Me; use Symfony\Component\HttpFoundation\Request; @@ -19,7 +20,6 @@ public function __construct( ) { } - // TODO: organization public function me(Request $request): ?Me { $session = $request->getSession(); @@ -31,7 +31,11 @@ public function me(Request $request): ?Me return new Me( AuthUser::fromOidcUser($oidcUser), - null, // TODO + new AuthUserOrganization( + 0, + 'Default', + 'admin' + ), ); } diff --git a/src/Billing/BillingFake.php b/src/Billing/BillingFake.php index 515a74a..f67d73a 100644 --- a/src/Billing/BillingFake.php +++ b/src/Billing/BillingFake.php @@ -2,10 +2,9 @@ namespace Hyvor\Internal\Billing; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\License; use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalConfig; use Symfony\Component\DependencyInjection\Container; @@ -15,12 +14,12 @@ class BillingFake implements BillingInterface /** * @param License|(callable(int $organizationId, ?int $blogId, Component $component) : ?License)|null $license - * @param LicensesCollection|(callable(LicenseOf[] $of, Component $component) : LicensesCollection)|null $licenses + * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses * @return void */ public static function enable( null|License|callable $license = null, - null|LicensesCollection|callable $licenses = null + null|array|callable $licenses = null ): void { app()->singleton(Billing::class, function () use ($license, $licenses) { return new BillingFake( @@ -33,13 +32,13 @@ public static function enable( /** * @param License|(callable(int $organizationId, ?int $blogId, Component $component) : ?License)|null $license - * @param LicensesCollection|(callable(LicenseOf[] $of, Component $component) : LicensesCollection)|null $licenses + * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses * @return void */ public static function enableForSymfony( Container $container, null|License|callable $license = null, - null|LicensesCollection|callable $licenses = null + null|array|callable $licenses = null ): void { $internalConfig = $container->get(InternalConfig::class); assert($internalConfig instanceof InternalConfig); @@ -56,12 +55,12 @@ public function __construct( private InternalConfig $internalConfig, /** - * @param License|(callable(int $organizationId, ?int $resouceId, Component $component) : ?License)|null $license + * @param ResolvedLicense|(callable(int $organizationId, Component $component) : ?ResolvedLicense)|null $license */ private readonly mixed $license = null, /** - * @param LicensesCollection|(callable(LicenseOf[] $of, Component $component) : LicensesCollection)|null $licenses + * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses */ private readonly mixed $licenses = null ) { @@ -72,10 +71,10 @@ public function license(int $organizationId, ?Component $component = null): Reso $component ??= $this->internalConfig->getComponent(); if ($this->license === null) { - return null; + return new ResolvedLicense(ResolvedLicenseType::NONE); } - if ($this->license instanceof License) { + if ($this->license instanceof ResolvedLicense) { return $this->license; } @@ -96,11 +95,11 @@ public function licenses(array $organizationIds, ?Component $component = null): // @codeCoverageIgnoreEnd } - if ($this->licenses instanceof LicensesCollection) { + if (is_array($this->licenses)) { return $this->licenses; } - return ($this->licenses)($of, $component); + return ($this->licenses)($organizationIds, $component); } } diff --git a/src/Billing/License/Plan/PlanAbstract.php b/src/Billing/License/Plan/PlanAbstract.php index 2dc3f5c..ea796fb 100644 --- a/src/Billing/License/Plan/PlanAbstract.php +++ b/src/Billing/License/Plan/PlanAbstract.php @@ -83,7 +83,9 @@ public function getCurrentVersion(): int */ public function getCurrentPlans(): array { - return $this->versions[array_key_last($this->versions)]; + $version = array_key_last($this->versions); + assert(is_int($version)); + return $this->versions[$version]; } /** diff --git a/src/Billing/License/PostLicense.php b/src/Billing/License/PostLicense.php index 738d6b6..9f16c41 100644 --- a/src/Billing/License/PostLicense.php +++ b/src/Billing/License/PostLicense.php @@ -8,7 +8,7 @@ final class PostLicense extends License { public function __construct( - public int $emails = 0, // 0 = email sending not allowed + public int $emails, // 0 = email sending not allowed public bool $allowRemoveBranding, ) { diff --git a/src/InternalFake.php b/src/InternalFake.php index 22e7915..2e7e2b2 100644 --- a/src/InternalFake.php +++ b/src/InternalFake.php @@ -3,9 +3,9 @@ namespace Hyvor\Internal; use Hyvor\Internal\Auth\AuthUser; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\License; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; use Hyvor\Internal\Component\Component; /** @@ -39,29 +39,25 @@ public function usersDatabase(): ?array /** * Returns a default (trial) license of the component */ - public function license(int $userId, ?int $resourceId, Component $component): ?License + public function license(int $userId, Component $component): ?License { $licenseClass = $component->license(); - return new $licenseClass; // trial defaults + return $licenseClass::trial(); // trial defaults } /** * Returns a collection of licenses for the given LicenseOf objects. - * @codeCoverageIgnore TODO: add coverage later - * @param LicenseOf[] $of + * @param int[] $organizationIds + * @return array */ - public function licenses(array $of, Component $component): LicensesCollection + public function licenses(array $organizationIds, Component $component): array { $licenses = []; $licenseClass = $component->license(); - foreach ($of as $licenseOf) { - $licenses[] = [ - 'organization_id' => $licenseOf->organizationId, - 'resource_id' => $licenseOf->resourceId, - 'license' => (new $licenseClass)->serialize(), - ]; + foreach ($organizationIds as $organizationId) { + $licenses[$organizationId] = new ResolvedLicense(ResolvedLicenseType::TRIAL, $licenseClass::trial()); } - return new LicensesCollection($licenses, $component); + return $licenses; } /** diff --git a/src/Laravel/AuthController.php b/src/Laravel/AuthController.php deleted file mode 100644 index 9ef778a..0000000 --- a/src/Laravel/AuthController.php +++ /dev/null @@ -1,64 +0,0 @@ -getAuthInterface(); - assert($auth instanceof Auth); - return $auth; - } - - public function check(): JsonResponse - { - $user = $this->getAuthInterface()->check(request()); - - return Response::json([ - 'is_logged_in' => $user !== false, - 'user' => $user ? $user : null, - ]); - } - - public function login(Request $request): RedirectResponse - { - return $this->redirectTo('login', $request); - } - - public function signup(Request $request): RedirectResponse - { - return $this->redirectTo('signup', $request); - } - - public function logout(Request $request): RedirectResponse - { - return $this->redirectTo('logout', $request); - } - - /** - * @param 'login'|'signup'|'logout' $page - */ - private function redirectTo(string $page, Request $request): RedirectResponse - { - $url = $this->getAuth()->authUrl($page, $request->get('redirect') ?? $request->getUri()); - return Response::redirectTo($url, 302, [], false); - } - -} diff --git a/src/routes/auth.php b/src/routes/auth.php deleted file mode 100644 index fc86889..0000000 --- a/src/routes/auth.php +++ /dev/null @@ -1,11 +0,0 @@ -group(function () { - Route::post('/api/auth/check', [AuthController::class, 'check']); - Route::get('/api/auth/login', [AuthController::class, 'login']); - Route::get('/api/auth/signup', [AuthController::class, 'signup']); - Route::get('/api/auth/logout', [AuthController::class, 'logout']); -}); diff --git a/tests/Bundle/Api/AbstractApiExceptionListenerTest.php b/tests/Bundle/Api/AbstractApiExceptionListenerTest.php index 10d5582..bafe17d 100644 --- a/tests/Bundle/Api/AbstractApiExceptionListenerTest.php +++ b/tests/Bundle/Api/AbstractApiExceptionListenerTest.php @@ -196,3 +196,15 @@ public function test_data_carrying_http_exception(): void } } + + +// Helpers + +namespace App\Enum; + +enum TestEnum: string +{ + case TEST = 'test'; + case TEST2 = 'test2'; + case TEST3 = 'test3'; +} diff --git a/tests/Bundle/BillingFakeLicenseProviderTest.php b/tests/Bundle/BillingFakeLicenseProviderTest.php index 0ed0245..2509007 100644 --- a/tests/Bundle/BillingFakeLicenseProviderTest.php +++ b/tests/Bundle/BillingFakeLicenseProviderTest.php @@ -2,7 +2,6 @@ namespace Bundle; -use Hyvor\Internal\Billing\Dto\LicenseOf; use Hyvor\Internal\Bundle\BillingFakeLicenseProvider; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalFake; @@ -15,11 +14,11 @@ public function test_test(): void { $fake = new BillingFakeLicenseProvider(InternalFake::class); - $license = $fake->license(1, null, Component::BLOGS); + $license = $fake->license(1, Component::BLOGS); $this->assertNotNull($license); - $licenses = $fake->licenses([new LicenseOf(1)], Component::BLOGS); - $this->assertCount(1, $licenses->all()); + $licenses = $fake->licenses([1], Component::BLOGS); + $this->assertCount(1, $licenses); } diff --git a/tests/Bundle/Command/Sudo/SudoAddCommandTest.php b/tests/Bundle/Command/Sudo/SudoAddCommandTest.php index 97e2058..2c41da7 100644 --- a/tests/Bundle/Command/Sudo/SudoAddCommandTest.php +++ b/tests/Bundle/Command/Sudo/SudoAddCommandTest.php @@ -72,7 +72,6 @@ public function test_fails_when_user_is_already_sudo(): void public function test_adds_user_when_one_user_found(): void { - $eventDispatcher = TestEventDispatcher::enable($this->container); AuthFake::enableForSymfony($this->container, usersDatabase: [ ['id' => 1, 'email' => 'supun@hyvor.com', 'name' => 'Supun'], ]); @@ -92,7 +91,7 @@ public function test_adds_user_when_one_user_found(): void $this->assertInstanceOf(\DateTimeImmutable::class, $sudoUsers[0]->getCreatedAt()); $this->assertInstanceOf(\DateTimeImmutable::class, $sudoUsers[0]->getUpdatedAt()); - $event = $eventDispatcher->getFirstEvent(SudoAddedEvent::class); + $event = $this->getEd()->getFirstEvent(SudoAddedEvent::class); $this->assertSame(1, $event->getSudoUser()->getUserId()); } @@ -120,4 +119,4 @@ public function test_asks_question_when_multiple_users_found(): void $this->assertSame($oidcUser2->getId(), $sudoUsers[0]->getUserId()); } -} \ No newline at end of file +} diff --git a/tests/Bundle/Command/Sudo/SudoRemoveCommandTest.php b/tests/Bundle/Command/Sudo/SudoRemoveCommandTest.php index 4a678d1..9f7beb0 100644 --- a/tests/Bundle/Command/Sudo/SudoRemoveCommandTest.php +++ b/tests/Bundle/Command/Sudo/SudoRemoveCommandTest.php @@ -33,7 +33,6 @@ public function test_fails_when_no_sudo_user_found(): void public function test_removes_sudo_user_successfully(): void { - $eventDispatcher = TestEventDispatcher::enable($this->container); $sudoUser = $this->createSudoUser(userId: 42, em: $this->em); $command = $this->getCommandTester('sudo:remove'); @@ -49,8 +48,8 @@ public function test_removes_sudo_user_successfully(): void $sudoUsers = $this->em->getRepository(SudoUser::class)->findAll(); $this->assertCount(0, $sudoUsers); - $event = $eventDispatcher->getFirstEvent(SudoRemovedEvent::class); + $event = $this->getEd()->getFirstEvent(SudoRemovedEvent::class); $this->assertSame(42, $event->getSudoUser()->getUserId()); } -} \ No newline at end of file +} diff --git a/tests/Bundle/Controller/OidcCallbackTest.php b/tests/Bundle/Controller/OidcCallbackTest.php index 8b66196..998f092 100644 --- a/tests/Bundle/Controller/OidcCallbackTest.php +++ b/tests/Bundle/Controller/OidcCallbackTest.php @@ -180,8 +180,6 @@ private function createIdToken( public function test_gets_id_token_and_signs_up(): void { - $eventDispatcher = TestEventDispatcher::enable($this->container); - [ 'privateKeyPem' => $privateKeyPem, 'jwks' => $jwks @@ -227,7 +225,7 @@ public function test_gets_id_token_and_signs_up(): void $this->assertSame('test_client_id', $parsedBody['client_id']); $this->assertSame('test_client_secret', $parsedBody['client_secret']); - $event = $eventDispatcher->getFirstEvent(UserSignedUpEvent::class); + $event = $this->getEd()->getFirstEvent(UserSignedUpEvent::class); $this->assertSame('user123', $event->getUser()->oidc_sub); } diff --git a/tests/Bundle/Testing/ApiTestingTraitTest.php b/tests/Bundle/Testing/ApiTestingTraitTest.php index 421e6df..76424ce 100644 --- a/tests/Bundle/Testing/ApiTestingTraitTest.php +++ b/tests/Bundle/Testing/ApiTestingTraitTest.php @@ -4,6 +4,7 @@ use Hyvor\Internal\Bundle\Testing\ApiTestingTrait; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Container; class ApiTestingTraitTest extends TestCase { @@ -12,6 +13,8 @@ class ApiTestingTraitTest extends TestCase private static string $json; private static int $status; + public Container $container; + /** * @param array $json */ @@ -62,4 +65,4 @@ public function test_assert_has_violations(): void $this->assertHasViolation('username', 'Username is required'); } -} \ No newline at end of file +} diff --git a/tests/Feature/Auth/AuthRoutesLaravelTest.php b/tests/Feature/Auth/AuthRoutesLaravelTest.php deleted file mode 100644 index 5806601..0000000 --- a/tests/Feature/Auth/AuthRoutesLaravelTest.php +++ /dev/null @@ -1,86 +0,0 @@ - false]); - Route::setRoutes(new RouteCollection()); - - $app = $this->app; - assert($app !== null); - (new InternalServiceProvider($app))->boot(); - $this->get('/api/auth/check')->assertNotFound(); - } - - public function testCheckWhenNotLoggedIn(): void - { - AuthFake::enable(null); - - $this - ->post('/api/auth/check') - ->assertOk() - ->assertJsonPath('is_logged_in', false) - ->assertJsonPath('user', null); - } - - public function testCheckWhenLoggedIn(): void - { - AuthFake::enable(['id' => 1]); - - $this - ->post('/api/auth/check') - ->assertJsonPath('is_logged_in', true) - ->assertJsonPath('user.id', 1); - } - - public function testRedirects(): void - { - $this - ->get('/api/auth/login') - ->assertRedirectContains('https://hyvor.com/login?redirect='); - - $this - ->get('/api/auth/signup') - ->assertRedirectContains('https://hyvor.com/signup?redirect='); - - $this - ->get('/api/auth/logout') - ->assertRedirectContains('https://hyvor.com/logout?redirect='); - } - - public function testRespectsDomain(): void - { - AuthFake::enable(null); - - $app = $this->app; - assert($app !== null); - - $app->register(InternalServiceProvider::class, true); - - config(['internal.auth.routes_domain' => 'hyvor.cluster']); - Route::setRoutes(new RouteCollection()); - (new InternalServiceProvider($app))->boot(); - - $this - ->post('https://hyvor.com/api/auth/check') - ->assertStatus(404); - - $this - ->post('https://hyvor.cluster/api/auth/check') - ->assertOk(); - } - -} diff --git a/tests/Feature/ServiceProvider/FakeTest.php b/tests/Feature/ServiceProvider/FakeTest.php index e05feb2..18a0db3 100644 --- a/tests/Feature/ServiceProvider/FakeTest.php +++ b/tests/Feature/ServiceProvider/FakeTest.php @@ -47,7 +47,7 @@ public function testFakes(): void // billing $this->assertTrue($app->bound(BillingInterface::class)); - $license = $app->get(BillingInterface::class)->license(1, null, Component::BLOGS); + $license = $app->get(BillingInterface::class)->license(1, Component::BLOGS); $this->assertInstanceOf(BlogsLicense::class, $license); $this->assertEquals(2, $license->users); } @@ -95,7 +95,7 @@ public function testUsesExtendedClassIfThatIsAvailable(): void // billing $this->assertTrue($app->bound(Billing::class)); - $license = $app->get(Billing::class)->license(1, null, Component::BLOGS); + $license = $app->get(Billing::class)->license(1, Component::BLOGS); $this->assertInstanceOf(BlogsLicense::class, $license); $this->assertEquals(3, $license->users); } diff --git a/tests/Feature/ServiceProvider/internalfakextended.php b/tests/Feature/ServiceProvider/internalfakextended.php index 8722c5c..13de182 100644 --- a/tests/Feature/ServiceProvider/internalfakextended.php +++ b/tests/Feature/ServiceProvider/internalfakextended.php @@ -15,9 +15,11 @@ public function user(): ?AuthUser return null; } - public function license(int $userId, ?int $resourceId, Component $component): ?License + public function license(int $userId, Component $component): ?License { - return new BlogsLicense(users: 3); + $license = BlogsLicense::trial(); + $license->users = 3; + return $license; } } diff --git a/tests/SymfonyTestCase.php b/tests/SymfonyTestCase.php index fc2a248..47ee3ee 100644 --- a/tests/SymfonyTestCase.php +++ b/tests/SymfonyTestCase.php @@ -5,11 +5,13 @@ use Doctrine\Bundle\DoctrineBundle\Registry; use Doctrine\DBAL\Connection; use Doctrine\ORM\EntityManagerInterface; +use Hyvor\Internal\Bundle\EventDispatcher\TestEventDispatcher; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -121,4 +123,11 @@ protected function setHttpClientResponse(MockResponse|array $response): void $this->container->set(HttpClientInterface::class, $client); } -} \ No newline at end of file + public function getEd(): TestEventDispatcher + { + $ed = $this->getContainer()->get(EventDispatcherInterface::class); + assert($ed instanceof TestEventDispatcher); + return $ed; + } + +} diff --git a/tests/Unit/Auth/AuthTestTrait.php b/tests/Unit/Auth/AuthTestTrait.php index d10668a..8a3ce02 100644 --- a/tests/Unit/Auth/AuthTestTrait.php +++ b/tests/Unit/Auth/AuthTestTrait.php @@ -42,7 +42,7 @@ private function requestWithCookie(string $cookie): Request public function testCheckWhenNoCookieSet(): void { - $this->assertFalse($this->getAuth()->check($this->requestWithCookie(''))); + $this->assertFalse($this->getAuth()->me($this->requestWithCookie(''))); } public function testCheckWhenCookieIsSet(): void @@ -57,7 +57,7 @@ public function testCheckWhenCookieIsSet(): void ]); $this->setResponseFactory($response); - $user = $this->getAuth()->check($this->requestWithCookie('test-cookie')); + $user = $this->getAuth()->me($this->requestWithCookie('test-cookie')); $this->assertInstanceOf(AuthUser::class, $user); $this->assertEquals(1, $user->id); @@ -80,7 +80,7 @@ public function testReturnsFalseWhenUserIsNull(): void 'user' => null ]); $this->setResponseFactory($response); - $this->assertFalse($this->getAuth()->check($this->requestWithCookie('test'))); + $this->assertFalse($this->getAuth()->me($this->requestWithCookie('test'))); } public function test_auth_url(): void diff --git a/tests/Unit/Auth/Oidc/OidcAuthTest.php b/tests/Unit/Auth/Oidc/OidcAuthTest.php index 0821211..5dbf571 100644 --- a/tests/Unit/Auth/Oidc/OidcAuthTest.php +++ b/tests/Unit/Auth/Oidc/OidcAuthTest.php @@ -34,7 +34,7 @@ public function test_check_not_logged_in(): void $oidc = $this->getOidcAuth(); $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($this->createMock(SessionInterface::class)); - $this->assertFalse($oidc->check($requestNotLoggedIn)); + $this->assertFalse($oidc->me($requestNotLoggedIn)); } public function test_check_has_session_but_wrong_user_id(): void @@ -49,7 +49,7 @@ public function test_check_has_session_but_wrong_user_id(): void $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($session); - $this->assertFalse($oidc->check($requestNotLoggedIn)); + $this->assertFalse($oidc->me($requestNotLoggedIn)); } public function test_check_logged_in(): void @@ -68,7 +68,7 @@ public function test_check_logged_in(): void $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($session); - $user = $oidc->check($requestNotLoggedIn); + $user = $oidc->me($requestNotLoggedIn); $this->assertInstanceOf(AuthUser::class, $user); $this->assertSame($oidcUser->getId(), $user->id); @@ -180,4 +180,4 @@ public function test_from_emails(): void $this->assertSame($email2User1->getId(), $two[0]->id); } -} \ No newline at end of file +} diff --git a/tests/Unit/Billing/BillingFakeLaravelTest.php b/tests/Unit/Billing/BillingFakeLaravelTest.php index 29e7a9c..d3a3e6e 100644 --- a/tests/Unit/Billing/BillingFakeLaravelTest.php +++ b/tests/Unit/Billing/BillingFakeLaravelTest.php @@ -2,16 +2,10 @@ namespace Hyvor\Internal\Tests\Unit\Billing; -use Hyvor\Internal\Billing\Billing; use Hyvor\Internal\Billing\BillingFake; -use Hyvor\Internal\Billing\BillingInterface; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\BlogsLicense; -use Hyvor\Internal\Component\Component; use Hyvor\Internal\Tests\LaravelTestCase; use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\TestWith; #[CoversClass(BillingFake::class)] class BillingFakeLaravelTest extends LaravelTestCase @@ -19,7 +13,7 @@ class BillingFakeLaravelTest extends LaravelTestCase use BillingFakeTestTrait; - protected function enable(?BlogsLicense $license = null, LicensesCollection|callable|null $licenses = null): void + protected function enable(?BlogsLicense $license = null, array|callable|null $licenses = null): void { BillingFake::enable(license: $license, licenses: $licenses); } diff --git a/tests/Unit/Billing/BillingFakeSymfonyTest.php b/tests/Unit/Billing/BillingFakeSymfonyTest.php index 50ca086..04a1162 100644 --- a/tests/Unit/Billing/BillingFakeSymfonyTest.php +++ b/tests/Unit/Billing/BillingFakeSymfonyTest.php @@ -3,7 +3,6 @@ namespace Hyvor\Internal\Tests\Unit\Billing; use Hyvor\Internal\Billing\BillingFake; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\BlogsLicense; use Hyvor\Internal\Tests\SymfonyTestCase; @@ -12,7 +11,7 @@ class BillingFakeSymfonyTest extends SymfonyTestCase use BillingFakeTestTrait; - protected function enable(?BlogsLicense $license = null, LicensesCollection|callable|null $licenses = null): void + protected function enable(?BlogsLicense $license = null, array|callable|null $licenses = null): void { BillingFake::enableForSymfony($this->container, $license, $licenses); } diff --git a/tests/Unit/Billing/BillingFakeTestTrait.php b/tests/Unit/Billing/BillingFakeTestTrait.php index b5cfac0..ea613e0 100644 --- a/tests/Unit/Billing/BillingFakeTestTrait.php +++ b/tests/Unit/Billing/BillingFakeTestTrait.php @@ -4,26 +4,29 @@ use Hyvor\Internal\Billing\BillingFake; use Hyvor\Internal\Billing\BillingInterface; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\License\BlogsLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; use Hyvor\Internal\Component\Component; use PHPUnit\Framework\Attributes\TestWith; trait BillingFakeTestTrait { + /** + * @param array|callable|null $licenses + */ protected abstract function enable( ?BlogsLicense $license = null, - LicensesCollection|callable|null $licenses = null + array|callable|null $licenses = null ): void; public function testEnableAndLicense(): void { - $this->enable(license: new BlogsLicense); + $this->enable(license: BlogsLicense::trial()); $fake = $this->getContainer()->get(BillingInterface::class); $this->assertInstanceOf(BillingFake::class, $fake); - $this->assertInstanceOf(BlogsLicense::class, $fake->license(1, 1)); + $this->assertInstanceOf(BlogsLicense::class, $fake->license(1)); } public function testEnableAndLicenseNull(): void @@ -31,56 +34,43 @@ public function testEnableAndLicenseNull(): void $this->enable(null); $fake = $this->getContainer()->get(BillingInterface::class); $this->assertInstanceOf(BillingFake::class, $fake); - $this->assertNull($fake->license(1, 1)); + + $license = $fake->license(1); + // TODO: } #[TestWith([true])] #[TestWith([false])] public function test_enable_and_licenses(bool $callback): void { - $license1 = new BlogsLicense; - $license2 = new BlogsLicense(users: 5); - - $collection = new LicensesCollection([ - [ - 'user_id' => 1, - 'resource_id' => 1, - 'license' => $license1->serialize() - ], - [ - 'user_id' => 2, - 'resource_id' => 2, - 'license' => $license2->serialize() - ], - [ - 'user_id' => 3, - 'resource_id' => null, - 'license' => null - ] - ], Component::BLOGS); - - $this->enable(licenses: $callback ? fn() => $collection : $collection); + $license1 = BlogsLicense::trial(); + $license2 = BlogsLicense::trial(); + $license2->users = 5; + + $data = [ + 1 => new ResolvedLicense(ResolvedLicenseType::SUBSCRIPTION, $license1), + 2 => new ResolvedLicense(ResolvedLicenseType::ENTERPRISE_CONTRACT, $license2), + 3 => new ResolvedLicense(ResolvedLicenseType::NONE) + ]; + + $this->enable(licenses: $callback ? fn() => $data : $data); $fake = $this->getContainer()->get(BillingInterface::class); $this->assertInstanceOf(BillingFake::class, $fake); - $allLicenses = $fake->licenses([ - new LicenseOf(1, 1), - new LicenseOf(2, 2), - new LicenseOf(3, null) - ]); + $allLicenses = $fake->licenses([1, 2, 3]); - $this->assertCount(3, $allLicenses->all()); + $this->assertCount(3, $allLicenses); - $license1 = $allLicenses->of(1, 1); + $license1 = $allLicenses[1]; $this->assertInstanceOf(BlogsLicense::class, $license1); $this->assertEquals(2, $license1->users); - $license2 = $allLicenses->of(2, 2); + $license2 = $allLicenses[2]; $this->assertInstanceOf(BlogsLicense::class, $license2); $this->assertEquals(5, $license2->users); - $license3 = $allLicenses->of(3, null); - $this->assertNull($license3); + $license3 = $allLicenses[3]; + // TODO: } } diff --git a/tests/Unit/Billing/BillingLaravelTest.php b/tests/Unit/Billing/BillingLaravelTest.php index 2327b01..5d6b0a6 100644 --- a/tests/Unit/Billing/BillingLaravelTest.php +++ b/tests/Unit/Billing/BillingLaravelTest.php @@ -3,8 +3,6 @@ namespace Hyvor\Internal\Tests\Unit\Billing; use Hyvor\Internal\Billing\Billing; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\SubscriptionIntent; use Hyvor\Internal\InternalApi\InternalApi; use Hyvor\Internal\Tests\LaravelTestCase; @@ -15,8 +13,6 @@ #[CoversClass(Billing::class)] #[CoversClass(SubscriptionIntent::class)] -#[CoversClass(LicensesCollection::class)] -#[CoversClass(LicenseOf::class)] class BillingLaravelTest extends LaravelTestCase { diff --git a/tests/Unit/Billing/BillingSymfonyTest.php b/tests/Unit/Billing/BillingSymfonyTest.php index 9a7a0a1..993f84f 100644 --- a/tests/Unit/Billing/BillingSymfonyTest.php +++ b/tests/Unit/Billing/BillingSymfonyTest.php @@ -3,20 +3,14 @@ namespace Hyvor\Internal\Tests\Unit\Billing; use Hyvor\Internal\Billing\Billing; -use Hyvor\Internal\Billing\Dto\LicenseOf; -use Hyvor\Internal\Billing\Dto\LicensesCollection; use Hyvor\Internal\Billing\SubscriptionIntent; use Hyvor\Internal\InternalApi\InternalApi; use Hyvor\Internal\Tests\SymfonyTestCase; use PHPUnit\Framework\Attributes\CoversClass; -use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Contracts\HttpClient\HttpClientInterface; #[CoversClass(Billing::class)] #[CoversClass(SubscriptionIntent::class)] -#[CoversClass(LicensesCollection::class)] -#[CoversClass(LicenseOf::class)] class BillingSymfonyTest extends SymfonyTestCase { @@ -40,4 +34,4 @@ protected function getInternalApi(): InternalApi assert($internalApi instanceof InternalApi); return $internalApi; } -} \ No newline at end of file +} diff --git a/tests/Unit/Billing/BillingTestTrait.php b/tests/Unit/Billing/BillingTestTrait.php index 85195f3..f870603 100644 --- a/tests/Unit/Billing/BillingTestTrait.php +++ b/tests/Unit/Billing/BillingTestTrait.php @@ -3,7 +3,6 @@ namespace Hyvor\Internal\Tests\Unit\Billing; use Hyvor\Internal\Billing\Billing; -use Hyvor\Internal\Billing\Dto\LicenseOf; use Hyvor\Internal\Billing\License\BlogsLicense; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalApi\InternalApi; @@ -24,11 +23,16 @@ public function testSubscriptionIntent(): void $billing = $this->getBilling(); $intent = $billing->subscriptionIntent(1, 'starter', true, Component::BLOGS); - $token = $intent['token']; - $this->assertEquals("https://hyvor.com/account/billing/subscription?token=$token", $intent['urlNew']); - $this->assertEquals( - "https://hyvor.com/account/billing/subscription?token=$token&change=1", + $this->assertStringContainsString( + "https://hyvor.com/account/billing/subscription?intent=", $intent['urlNew'] + ); + $this->assertStringContainsString( + "https://hyvor.com/account/billing/subscription?intent=", + $intent['urlChange'] + ); + $this->assertStringContainsString( + "&change=1", $intent['urlChange'] ); } @@ -39,13 +43,13 @@ public function testGetLicense(): void [ 'user_id' => 1, 'resource_id' => 10, - 'license' => new BlogsLicense()->serialize() + 'license' => BlogsLicense::trial()->serialize() ] ]); $this->setHttpResponse($mockResponse); $billing = $this->getBilling(); - $license = $billing->license(1, 10, Component::BLOGS); + $license = $billing->license(1, Component::BLOGS); $this->assertInstanceOf(BlogsLicense::class, $license); $this->assertEquals(2, $license->users); @@ -68,7 +72,7 @@ public function test_get_licenses(): void [ 'user_id' => 1, 'resource_id' => null, - 'license' => new BlogsLicense()->serialize() + 'license' => BlogsLicense::trial()->serialize() ], [ 'user_id' => 2, @@ -79,18 +83,14 @@ public function test_get_licenses(): void $this->setHttpResponse($mockResponse); $billing = $this->getBilling(); - $licenses = $billing->licenses([ - new LicenseOf(1, null), - new LicenseOf(2, null), - ], Component::BLOGS); + $licenses = $billing->licenses([1, 2], Component::BLOGS); - $this->assertCount(2, $licenses->all()); + $this->assertCount(2, $licenses); - $user1License = $licenses->of(1, null); + $user1License = $licenses[1]; $this->assertInstanceOf(BlogsLicense::class, $user1License); - $user2License = $licenses->of(2, null); - $this->assertNull($user2License); + $user2License = $licenses[2]; // HTTP Request $data = $this->getInternalApi()->dataFromMockResponse($mockResponse); @@ -108,4 +108,4 @@ public function test_get_licenses(): void } -} \ No newline at end of file +} diff --git a/tests/Unit/Billing/LicenseTest.php b/tests/Unit/Billing/LicenseTest.php index 66f7a8a..9ed7935 100644 --- a/tests/Unit/Billing/LicenseTest.php +++ b/tests/Unit/Billing/LicenseTest.php @@ -82,7 +82,6 @@ public function test_build_from_array(): void { $license = BlogsLicense::fromArray( - // @phpstan-ignore-next-line [ 'users' => 1000, diff --git a/tests/Unit/Billing/Usage/ExampleStorageUsage.php b/tests/Unit/Billing/Usage/ExampleStorageUsage.php deleted file mode 100644 index 6cf1a1f..0000000 --- a/tests/Unit/Billing/Usage/ExampleStorageUsage.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -class ExampleStorageUsage extends UsageAbstract -{ - - public function getLicenseType(): string - { - return BlogsLicense::class; - } - - public function getKey(): string - { - return 'storage'; - } - - public function usageOfResource(int $resourceId): int - { - return 100; - } - - public function usageOfOrganization(int $userId): int - { - return 200; - } -} diff --git a/tests/Unit/Billing/Usage/UsageAbstractTest.php b/tests/Unit/Billing/Usage/UsageAbstractTest.php deleted file mode 100644 index c571895..0000000 --- a/tests/Unit/Billing/Usage/UsageAbstractTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals(100, $usage->usageOfResource(1)); - $this->assertEquals(200, $usage->usageOfOrganization(1)); - - // user - $licenseWithoutDerived = new BlogsLicense(storage: 300); - $this->assertFalse($usage->hasReached($licenseWithoutDerived, 1, 1)); - - // resource - $resourceLicense = new BlogsLicense(storage: 100)->setDerivedFrom(DerivedFrom::CUSTOM_RESOURCE); - $this->assertTrue($usage->hasReached($resourceLicense, 1, 1)); - $this->assertFalse($usage->hasExceeded($resourceLicense, 1, 1)); - } - -} diff --git a/tests/Unit/Http/Middleware/AuthMiddlewareLaravelTest.php b/tests/Unit/Http/Middleware/AuthMiddlewareLaravelTest.php deleted file mode 100644 index 592e853..0000000 --- a/tests/Unit/Http/Middleware/AuthMiddlewareLaravelTest.php +++ /dev/null @@ -1,38 +0,0 @@ -expectException(HttpException::class); - $this->expectExceptionMessage('Unauthorized'); - - AuthFake::enable(null); - $request = new Request(); - (new AuthMiddleware())->handle($request, function () { - }); - } - - public function testSetsAccessAuthUserWhenUserLoggedIn(): void - { - AuthFake::enable(['id' => 15]); - - $request = new Request(); - (new AuthMiddleware())->handle($request, function () { - $user = app(AccessAuthUser::class); - $this->assertInstanceOf(AccessAuthUser::class, $user); - $this->assertEquals(15, $user->id); - }); - } - -} diff --git a/tests/Unit/InternalConfigTest.php b/tests/Unit/InternalConfigTest.php index 3722b7b..135366c 100644 --- a/tests/Unit/InternalConfigTest.php +++ b/tests/Unit/InternalConfigTest.php @@ -4,6 +4,7 @@ use Hyvor\Internal\Auth\AuthMethod; use Hyvor\Internal\Component\Component; +use Hyvor\Internal\Deployment; use Hyvor\Internal\InternalConfig; use Hyvor\Internal\Tests\SymfonyTestCase; @@ -14,8 +15,9 @@ public function test_internal_config(): void { $internalConfig = new InternalConfig( appSecret: 'c2VjcmV0', + commsKey: base64_encode('commskey'), component: 'core', - authMethod: 'hyvor', + deployment: 'cloud', instance: 'https://hyvor.com', privateInstance: 'https://hyvor.internal', fake: false, @@ -25,6 +27,7 @@ public function test_internal_config(): void $this->assertSame('c2VjcmV0', $internalConfig->getAppSecretRaw()); $this->assertSame('secret', $internalConfig->getAppSecret()); + $this->assertSame('commskey', $internalConfig->getCommsKey()); $this->assertSame(Component::CORE, $internalConfig->getComponent()); $this->assertSame('https://hyvor.com', $internalConfig->getInstance()); $this->assertSame('https://hyvor.internal', $internalConfig->getPrivateInstance()); @@ -32,15 +35,16 @@ public function test_internal_config(): void $this->assertFalse($internalConfig->isFake()); $this->assertSame('i18n', $internalConfig->getI18nFolder()); $this->assertSame('en', $internalConfig->getI18nDefaultLocale()); - $this->assertSame(AuthMethod::HYVOR, $internalConfig->getAuthMethod()); + $this->assertSame(Deployment::CLOUD, $internalConfig->getDeployment()); } public function test_internal_config_i18n_realpath(): void { $internalConfig = new InternalConfig( appSecret: 'c2VjcmV0', + commsKey: 'commskey', component: 'core', - authMethod: 'hyvor', + deployment: 'cloud', instance: 'https://hyvor.com', privateInstance: 'https://hyvor.internal', fake: false, @@ -50,4 +54,4 @@ public function test_internal_config_i18n_realpath(): void $this->assertStringEndsWith('/tests/Unit/Resource', $internalConfig->getI18nFolder()); } -} \ No newline at end of file +} diff --git a/tests/Unit/Laravel/LogFakeLaravelTest.php b/tests/Unit/Laravel/LogFakeLaravelTest.php deleted file mode 100644 index 5b56e28..0000000 --- a/tests/Unit/Laravel/LogFakeLaravelTest.php +++ /dev/null @@ -1,50 +0,0 @@ - 'production']); - - $this->expectException(\Exception::class); - $this->expectExceptionMessage('Cannot fake log in non-testing environment'); - - LogFake::enable(); - } - - public function testLogFake(): void - { - LogFake::enable(); - Log::info('Some info', ['id' => 1]); - LogFake::assertLogged('info', 'Some info', ['id' => 1]); - } - - public function testLogFakeCallback(): void - { - LogFake::enable(); - Log::alert('Some alert', ['id' => 1]); - LogFake::assertLoggedCallback(function (string $level, string $message, array $data) { - $this->assertEquals('alert', $level); - $this->assertEquals('Some alert', $message); - $this->assertEquals(['id' => 1], $data); - - return true; - }); - } - - public function testLogNothingLogged(): void - { - LogFake::enable(); - LogFake::assertNothingLogged(); - } - -} From 453499bd60377891bf3be30faa08f90797c98dea Mon Sep 17 00:00:00 2001 From: Supun Wimalasena Date: Sun, 1 Feb 2026 16:30:49 +0100 Subject: [PATCH 2/4] wip errors --- CHANGELOG.md | 1 + bundle/config/services.php | 2 + bundle/src/Controller/OidcController.php | 1 + bundle/src/InternalBundle.php | 20 +++----- src/Auth/Auth.php | 4 +- src/Billing/BillingFake.php | 37 ++++---------- src/InternalServiceProvider.php | 4 -- src/config.php | 21 -------- tests/Bundle/Comms/CommsTest.php | 2 +- tests/Unit/Auth/AuthFactoryTest.php | 14 ++--- tests/Unit/Auth/AuthLaravelTest.php | 7 +++ tests/Unit/Auth/AuthSymfonyTest.php | 8 ++- tests/Unit/Auth/AuthTestTrait.php | 51 +++++++++++-------- tests/Unit/Auth/Oidc/OidcAuthTest.php | 9 ++-- tests/Unit/Billing/BillingFakeLaravelTest.php | 5 +- tests/Unit/Billing/BillingFakeSymfonyTest.php | 2 +- tests/Unit/Billing/BillingFakeTestTrait.php | 28 +++++----- 17 files changed, 95 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b7266..b08e969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - TestEventDispatcher moved - ::enable() is removed, and no longer needed. Test env automatically sets event_dispatcher to TestEventDispatcher - BillingInterface license() and licenses() method signatures changed +- BillingFake $license argument removed. license() calls licenses() now. Setting licenses for all called organizations is required now - Comms API - a shared COMMS_KEY env variable is required for component-to-componet communication - ResourceInterface and resource registering in the core is removed diff --git a/bundle/config/services.php b/bundle/config/services.php index 0f5dcf7..acba44c 100644 --- a/bundle/config/services.php +++ b/bundle/config/services.php @@ -1,5 +1,6 @@ set(\Hyvor\Internal\Bundle\Mail\Component\Brand::class)->public(); + $services->set(Comms::class)->public(); } // $services->load('Hyvor\\Internal\\User\\', '../../src/User'); diff --git a/bundle/src/Controller/OidcController.php b/bundle/src/Controller/OidcController.php index b011213..56827a8 100644 --- a/bundle/src/Controller/OidcController.php +++ b/bundle/src/Controller/OidcController.php @@ -8,6 +8,7 @@ use Hyvor\Internal\Auth\Oidc\OidcConfig; use Hyvor\Internal\Auth\Oidc\OidcApiService; use Hyvor\Internal\Auth\Oidc\OidcUserService; +use Hyvor\Internal\Bundle\Comms\Comms; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; diff --git a/bundle/src/InternalBundle.php b/bundle/src/InternalBundle.php index 4de2244..007b4e6 100644 --- a/bundle/src/InternalBundle.php +++ b/bundle/src/InternalBundle.php @@ -71,8 +71,10 @@ public function loadExtension(array $config, ContainerConfigurator $container, C ->set('internal.default_private_instance', null) ->set('internal.default_fake', false); + $services = $container->services(); + // InternalConfig class - $container->services() + $services ->get(InternalConfig::class) ->args([ '%env(APP_SECRET)%', @@ -86,29 +88,23 @@ public function loadExtension(array $config, ContainerConfigurator $container, C $config['i18n']['default'], ]); - $container - ->services() + $services ->set(AuthInterface::class) ->factory([service(AuthFactory::class), 'create']); - $container - ->services() + $services ->set(BillingInterface::class) ->public() // because this is not used from outside, so tests fail (inlined) ->factory([service(BillingFactory::class), 'create']); if ($container->env() === 'test') { - $container - ->services() - ->alias(CommsInterface::class, MockComms::class); + $services->alias(CommsInterface::class, MockComms::class); } else { - $container - ->services() - ->alias(CommsInterface::class, Comms::class); + $services->alias(CommsInterface::class, Comms::class); } // other services - $container->services()->alias(SelfHostedTelemetryInterface::class, SelfHostedTelemetry::class); + $services->alias(SelfHostedTelemetryInterface::class, SelfHostedTelemetry::class); } } diff --git a/src/Auth/Auth.php b/src/Auth/Auth.php index 74e438e..99ed856 100644 --- a/src/Auth/Auth.php +++ b/src/Auth/Auth.php @@ -3,7 +3,7 @@ namespace Hyvor\Internal\Auth; use Hyvor\Internal\Auth\Dto\Me; -use Hyvor\Internal\Bundle\Comms\Comms; +use Hyvor\Internal\Bundle\Comms\CommsInterface; use Hyvor\Internal\Bundle\Comms\Event\ToCore\User\GetMe; use Hyvor\Internal\Bundle\Comms\Exception\CommsApiFailedException; use Hyvor\Internal\Component\Component; @@ -22,7 +22,7 @@ class Auth implements AuthInterface public function __construct( private InternalApi $internalApi, private InstanceUrlResolver $instanceUrlResolver, - private Comms $comms, + private CommsInterface $comms, ) { } diff --git a/src/Billing/BillingFake.php b/src/Billing/BillingFake.php index f67d73a..8d88ac8 100644 --- a/src/Billing/BillingFake.php +++ b/src/Billing/BillingFake.php @@ -2,9 +2,7 @@ namespace Hyvor\Internal\Billing; -use Hyvor\Internal\Billing\License\License; use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; -use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalConfig; use Symfony\Component\DependencyInjection\Container; @@ -13,39 +11,31 @@ class BillingFake implements BillingInterface { /** - * @param License|(callable(int $organizationId, ?int $blogId, Component $component) : ?License)|null $license - * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses + * @param array|(callable(int[] $organizationIds, Component $component) : array) $licenses * @return void */ - public static function enable( - null|License|callable $license = null, - null|array|callable $licenses = null - ): void { - app()->singleton(Billing::class, function () use ($license, $licenses) { + public static function enable(array|callable $licenses): void { + app()->singleton(Billing::class, function () use ($licenses) { return new BillingFake( app(InternalConfig::class), - $license, $licenses ); }); } /** - * @param License|(callable(int $organizationId, ?int $blogId, Component $component) : ?License)|null $license - * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses + * @param array|(callable(int[] $organizationIds, Component $component) : array) $licenses * @return void */ public static function enableForSymfony( Container $container, - null|License|callable $license = null, - null|array|callable $licenses = null + array|callable $licenses ): void { $internalConfig = $container->get(InternalConfig::class); assert($internalConfig instanceof InternalConfig); $fake = new self( $internalConfig, - $license, $licenses ); $container->set(BillingInterface::class, $fake); @@ -54,11 +44,6 @@ public static function enableForSymfony( public function __construct( private InternalConfig $internalConfig, - /** - * @param ResolvedLicense|(callable(int $organizationId, Component $component) : ?ResolvedLicense)|null $license - */ - private readonly mixed $license = null, - /** * @param array|(callable(int[] $organizationIds, Component $component) : array)|null $licenses */ @@ -68,17 +53,13 @@ public function __construct( public function license(int $organizationId, ?Component $component = null): ResolvedLicense { - $component ??= $this->internalConfig->getComponent(); - - if ($this->license === null) { - return new ResolvedLicense(ResolvedLicenseType::NONE); - } + $license = $this->licenses([$organizationId], $component)[$organizationId] ?? null; - if ($this->license instanceof ResolvedLicense) { - return $this->license; + if (!$license) { + throw new \Exception("No license found for organization ID {$organizationId} in BillingFake"); } - return ($this->license)($organizationId, $component); + return $license; } /** diff --git a/src/InternalServiceProvider.php b/src/InternalServiceProvider.php index 1486637..9243b3b 100644 --- a/src/InternalServiceProvider.php +++ b/src/InternalServiceProvider.php @@ -74,10 +74,6 @@ private function config(): void private function routes(): void { - // auth routes - if (config('internal.auth.routes')) { - $this->loadRoutesFrom(__DIR__ . '/routes/auth.php'); - } // testing routes if (App::environment('testing')) { $this->loadRoutesFrom(__DIR__ . '/routes/testing.php'); diff --git a/src/config.php b/src/config.php index 41eacee..a906bf1 100644 --- a/src/config.php +++ b/src/config.php @@ -47,27 +47,6 @@ */ 'fake' => env('HYVOR_FAKE', false), - /** - * User settings - */ - 'auth' => [ - - /** - * Whether to add auth routes - * /api/auth/check - get the current user - * /api/auth/login - login redirect - * /api/auth/signup - signup redirect - */ - 'routes' => true, - - /** - * If routes is true, set the domain restriction - * By default, added to all domains - */ - 'routes_domain' => '{any}', - - ], - 'i18n' => [ /** diff --git a/tests/Bundle/Comms/CommsTest.php b/tests/Bundle/Comms/CommsTest.php index 61bf38b..059ef34 100644 --- a/tests/Bundle/Comms/CommsTest.php +++ b/tests/Bundle/Comms/CommsTest.php @@ -142,4 +142,4 @@ public function test_sends(): void $this->assertInstanceOf(TestEvent\TestEventToCore::class, $event); $this->assertSame(1, $event->id); } -} \ No newline at end of file +} diff --git a/tests/Unit/Auth/AuthFactoryTest.php b/tests/Unit/Auth/AuthFactoryTest.php index 6298c29..dcc4298 100644 --- a/tests/Unit/Auth/AuthFactoryTest.php +++ b/tests/Unit/Auth/AuthFactoryTest.php @@ -14,7 +14,7 @@ class AuthFactoryTest extends SymfonyTestCase public function test_create_hyvor_fake(): void { $_ENV['HYVOR_FAKE'] = '1'; - $_ENV['AUTH_METHOD'] = 'hyvor'; + $_ENV['DEPLOYMENT'] = 'cloud'; /** @var AuthFactory $factory */ $factory = $this->container->get(AuthFactory::class); @@ -23,12 +23,12 @@ public function test_create_hyvor_fake(): void $this->assertInstanceOf(AuthFake::class, $auth); unset($_ENV['HYVOR_FAKE']); - unset($_ENV['AUTH_METHOD']); + unset($_ENV['DEPLOYMENT']); } public function test_create_hyvor(): void { - $_ENV['AUTH_METHOD'] = 'hyvor'; + $_ENV['DEPLOYMENT'] = 'cloud'; /** @var AuthFactory $factory */ $factory = $this->container->get(AuthFactory::class); @@ -36,12 +36,12 @@ public function test_create_hyvor(): void $this->assertInstanceOf(Auth::class, $auth); - unset($_ENV['AUTH_METHOD']); + unset($_ENV['DEPLOYMENT']); } public function test_create_oidc(): void { - $_ENV['AUTH_METHOD'] = 'oidc'; + $_ENV['DEPLOYMENT'] = 'on-prem'; /** @var AuthFactory $factory */ $factory = $this->container->get(AuthFactory::class); @@ -49,7 +49,7 @@ public function test_create_oidc(): void $this->assertInstanceOf(OidcAuth::class, $auth); - unset($_ENV['AUTH_METHOD']); + unset($_ENV['DEPLOYMENT']); } -} \ No newline at end of file +} diff --git a/tests/Unit/Auth/AuthLaravelTest.php b/tests/Unit/Auth/AuthLaravelTest.php index 135e5f4..fbb2906 100644 --- a/tests/Unit/Auth/AuthLaravelTest.php +++ b/tests/Unit/Auth/AuthLaravelTest.php @@ -3,6 +3,8 @@ namespace Hyvor\Internal\Tests\Unit\Auth; use Hyvor\Internal\Auth\Auth; +use Hyvor\Internal\Bundle\Comms\CommsInterface; +use Hyvor\Internal\Bundle\Comms\MockComms; use Hyvor\Internal\Tests\LaravelTestCase; use PHPUnit\Framework\Attributes\CoversClass; @@ -10,4 +12,9 @@ class AuthLaravelTest extends LaravelTestCase { use AuthTestTrait; + + public function setComms(MockComms $comms): void + { + app()->singleton(CommsInterface::class, fn() => $comms); + } } diff --git a/tests/Unit/Auth/AuthSymfonyTest.php b/tests/Unit/Auth/AuthSymfonyTest.php index 8c78374..6463c5a 100644 --- a/tests/Unit/Auth/AuthSymfonyTest.php +++ b/tests/Unit/Auth/AuthSymfonyTest.php @@ -2,9 +2,15 @@ namespace Hyvor\Internal\Tests\Unit\Auth; +use Hyvor\Internal\Bundle\Comms\MockComms; use Hyvor\Internal\Tests\SymfonyTestCase; class AuthSymfonyTest extends SymfonyTestCase { use AuthTestTrait; -} \ No newline at end of file + + function setComms(MockComms $comms): void + { + return; // already set + } +} diff --git a/tests/Unit/Auth/AuthTestTrait.php b/tests/Unit/Auth/AuthTestTrait.php index 8a3ce02..c8ee45f 100644 --- a/tests/Unit/Auth/AuthTestTrait.php +++ b/tests/Unit/Auth/AuthTestTrait.php @@ -4,12 +4,14 @@ use Hyvor\Internal\Auth\Auth; use Hyvor\Internal\Auth\AuthUser; +use Hyvor\Internal\Auth\Dto\Me; +use Hyvor\Internal\Bundle\Comms\Event\ToCore\User\GetMe; +use Hyvor\Internal\Bundle\Comms\Event\ToCore\User\GetMeResponse; +use Hyvor\Internal\Bundle\Comms\MockComms; +use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalApi\InternalApi; -use Illuminate\Support\Collection; -use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Contracts\HttpClient\HttpClientInterface; trait AuthTestTrait { @@ -42,45 +44,50 @@ private function requestWithCookie(string $cookie): Request public function testCheckWhenNoCookieSet(): void { - $this->assertFalse($this->getAuth()->me($this->requestWithCookie(''))); + $this->assertNull($this->getAuth()->me($this->requestWithCookie(''))); } + abstract function setComms(MockComms $comms): void; + public function testCheckWhenCookieIsSet(): void { - $response = new JsonMockResponse([ - 'user' => [ + /** @var MockComms $mockComms */ + $mockComms = $this->getContainer()->get(MockComms::class); + $mockComms->addResponse(GetMe::class, new GetMeResponse( + user: AuthUser::fromArray([ 'id' => 1, 'name' => 'test', 'username' => 'test', 'email' => 'test@test.com' - ] - ]); - $this->setResponseFactory($response); + ]) + )); + $this->setComms($mockComms); + + $me = $this->getAuth()->me($this->requestWithCookie('test-cookie')); - $user = $this->getAuth()->me($this->requestWithCookie('test-cookie')); + $this->assertInstanceOf(Me::class, $me); + $user = $me->getUser(); $this->assertInstanceOf(AuthUser::class, $user); $this->assertEquals(1, $user->id); $this->assertEquals('test', $user->name); $this->assertEquals('test', $user->username); $this->assertEquals('test@test.com', $user->email); - $this->assertSame( - 'https://hyvor.internal/api/internal/auth/check', - $response->getRequestUrl() - ); - - $data = $this->getInternalApi()->dataFromMockResponse($response); - $this->assertEquals('test-cookie', $data['cookie']); + $mockComms->assertSent(GetMe::class, Component::CORE, + eventValidator: fn ($me) => $this->assertSame('test-cookie', $me->getCookie())); } public function testReturnsFalseWhenUserIsNull(): void { - $response = new JsonMockResponse([ - 'user' => null - ]); - $this->setResponseFactory($response); - $this->assertFalse($this->getAuth()->me($this->requestWithCookie('test'))); + + /** @var MockComms $mockComms */ + $mockComms = $this->getContainer()->get(MockComms::class); + $mockComms->addResponse(GetMe::class, new GetMeResponse( + user: null + )); + $this->setComms($mockComms); + $this->assertNull($this->getAuth()->me($this->requestWithCookie('test'))); } public function test_auth_url(): void diff --git a/tests/Unit/Auth/Oidc/OidcAuthTest.php b/tests/Unit/Auth/Oidc/OidcAuthTest.php index 5dbf571..ed8e9e6 100644 --- a/tests/Unit/Auth/Oidc/OidcAuthTest.php +++ b/tests/Unit/Auth/Oidc/OidcAuthTest.php @@ -34,7 +34,7 @@ public function test_check_not_logged_in(): void $oidc = $this->getOidcAuth(); $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($this->createMock(SessionInterface::class)); - $this->assertFalse($oidc->me($requestNotLoggedIn)); + $this->assertNull($oidc->me($requestNotLoggedIn)); } public function test_check_has_session_but_wrong_user_id(): void @@ -49,7 +49,7 @@ public function test_check_has_session_but_wrong_user_id(): void $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($session); - $this->assertFalse($oidc->me($requestNotLoggedIn)); + $this->assertNull($oidc->me($requestNotLoggedIn)); } public function test_check_logged_in(): void @@ -68,9 +68,10 @@ public function test_check_logged_in(): void $requestNotLoggedIn = Request::create('/'); $requestNotLoggedIn->setSession($session); - $user = $oidc->me($requestNotLoggedIn); - $this->assertInstanceOf(AuthUser::class, $user); + $me = $oidc->me($requestNotLoggedIn); + $this->assertNotNull($me); + $user = $me->getUser(); $this->assertSame($oidcUser->getId(), $user->id); $this->assertSame($oidcUser->getEmail(), $user->email); $this->assertSame($oidcUser->getName(), $user->name); diff --git a/tests/Unit/Billing/BillingFakeLaravelTest.php b/tests/Unit/Billing/BillingFakeLaravelTest.php index d3a3e6e..4818723 100644 --- a/tests/Unit/Billing/BillingFakeLaravelTest.php +++ b/tests/Unit/Billing/BillingFakeLaravelTest.php @@ -3,7 +3,6 @@ namespace Hyvor\Internal\Tests\Unit\Billing; use Hyvor\Internal\Billing\BillingFake; -use Hyvor\Internal\Billing\License\BlogsLicense; use Hyvor\Internal\Tests\LaravelTestCase; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +12,9 @@ class BillingFakeLaravelTest extends LaravelTestCase use BillingFakeTestTrait; - protected function enable(?BlogsLicense $license = null, array|callable|null $licenses = null): void + protected function enable(array|callable $licenses = []): void { - BillingFake::enable(license: $license, licenses: $licenses); + BillingFake::enable(licenses: $licenses); } } diff --git a/tests/Unit/Billing/BillingFakeSymfonyTest.php b/tests/Unit/Billing/BillingFakeSymfonyTest.php index 04a1162..ef2804d 100644 --- a/tests/Unit/Billing/BillingFakeSymfonyTest.php +++ b/tests/Unit/Billing/BillingFakeSymfonyTest.php @@ -11,7 +11,7 @@ class BillingFakeSymfonyTest extends SymfonyTestCase use BillingFakeTestTrait; - protected function enable(?BlogsLicense $license = null, array|callable|null $licenses = null): void + protected function enable(array|callable|null $licenses = null): void { BillingFake::enableForSymfony($this->container, $license, $licenses); } diff --git a/tests/Unit/Billing/BillingFakeTestTrait.php b/tests/Unit/Billing/BillingFakeTestTrait.php index ea613e0..7b5fc34 100644 --- a/tests/Unit/Billing/BillingFakeTestTrait.php +++ b/tests/Unit/Billing/BillingFakeTestTrait.php @@ -7,36 +7,34 @@ use Hyvor\Internal\Billing\License\BlogsLicense; use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; -use Hyvor\Internal\Component\Component; use PHPUnit\Framework\Attributes\TestWith; trait BillingFakeTestTrait { /** - * @param array|callable|null $licenses + * @param array|callable $licenses */ - protected abstract function enable( - ?BlogsLicense $license = null, - array|callable|null $licenses = null - ): void; + protected abstract function enable(array|callable $licenses = []): void; public function testEnableAndLicense(): void { - $this->enable(license: BlogsLicense::trial()); + $this->enable(licenses: [1 => new ResolvedLicense(ResolvedLicenseType::TRIAL, BlogsLicense::trial())]); $fake = $this->getContainer()->get(BillingInterface::class); $this->assertInstanceOf(BillingFake::class, $fake); - $this->assertInstanceOf(BlogsLicense::class, $fake->license(1)); + + $license = $fake->license(1); + $this->assertInstanceOf(BlogsLicense::class, $license->license); } public function testEnableAndLicenseNull(): void { - $this->enable(null); + $this->enable(licenses: [1 => new ResolvedLicense(ResolvedLicenseType::NONE)]); $fake = $this->getContainer()->get(BillingInterface::class); $this->assertInstanceOf(BillingFake::class, $fake); $license = $fake->license(1); - // TODO: + $this->assertNull($license->license); } #[TestWith([true])] @@ -62,15 +60,15 @@ public function test_enable_and_licenses(bool $callback): void $this->assertCount(3, $allLicenses); $license1 = $allLicenses[1]; - $this->assertInstanceOf(BlogsLicense::class, $license1); - $this->assertEquals(2, $license1->users); + $this->assertInstanceOf(BlogsLicense::class, $license1->license); + $this->assertEquals(2, $license1->license->users); $license2 = $allLicenses[2]; - $this->assertInstanceOf(BlogsLicense::class, $license2); - $this->assertEquals(5, $license2->users); + $this->assertInstanceOf(BlogsLicense::class, $license2->license); + $this->assertEquals(5, $license2->license->users); $license3 = $allLicenses[3]; - // TODO: + $this->assertNull($license3->license); } } From 34594967549b46a09149c6b0bf817625edae194f Mon Sep 17 00:00:00 2001 From: Supun Wimalasena Date: Sun, 1 Feb 2026 16:48:05 +0100 Subject: [PATCH 3/4] all tests fixed --- .../EventDispatcher/TestEventDispatcher.php | 8 ++ src/Billing/License/Plan/TalkPlan.php | 2 + src/Billing/License/TalkLicense.php | 2 + src/InternalFake.php | 9 +- src/InternalServiceProvider.php | 7 +- .../Testing/TestEventDispatcherTest.php | 7 +- tests/Feature/ServiceProvider/FakeTest.php | 10 +-- .../ServiceProvider/internalfakextended.php | 9 +- tests/Unit/Billing/BillingFakeSymfonyTest.php | 4 +- tests/Unit/Billing/BillingFakeTestTrait.php | 2 +- tests/Unit/Billing/BillingLaravelTest.php | 13 ++- tests/Unit/Billing/BillingSymfonyTest.php | 12 +-- tests/Unit/Billing/BillingTestTrait.php | 82 ++++++++----------- tests/Unit/Billing/LicenseTest.php | 4 +- 14 files changed, 86 insertions(+), 85 deletions(-) diff --git a/bundle/src/EventDispatcher/TestEventDispatcher.php b/bundle/src/EventDispatcher/TestEventDispatcher.php index a2b8c62..dc1d4cf 100644 --- a/bundle/src/EventDispatcher/TestEventDispatcher.php +++ b/bundle/src/EventDispatcher/TestEventDispatcher.php @@ -24,6 +24,14 @@ public function __construct( parent::__construct(); } + /** + * @param false|string[] $mockEvents + */ + public function setMockEvents(false|array $mockEvents): void + { + $this->mockEvents = $mockEvents; + } + public function dispatch(object $event, ?string $eventName = null): object { $eventName ??= $event::class; diff --git a/src/Billing/License/Plan/TalkPlan.php b/src/Billing/License/Plan/TalkPlan.php index 5b1c53d..2b1cb32 100644 --- a/src/Billing/License/Plan/TalkPlan.php +++ b/src/Billing/License/Plan/TalkPlan.php @@ -54,6 +54,7 @@ private function premiumPlan(int $credits, float $monthlyPrice): void { $license = new TalkLicense( credits: $credits, + comments: -1, storage: $this->getStorageBytesFromCredits($credits), sso: false, noBranding: false, @@ -78,6 +79,7 @@ private function businessPlan(int $credits, float $monthlyPrice): void { $license = new TalkLicense( credits: $credits, + comments: -1, storage: $this->getStorageBytesFromCredits($credits), sso: true, noBranding: true, diff --git a/src/Billing/License/TalkLicense.php b/src/Billing/License/TalkLicense.php index 278d502..b8f2a5c 100644 --- a/src/Billing/License/TalkLicense.php +++ b/src/Billing/License/TalkLicense.php @@ -9,6 +9,7 @@ final class TalkLicense extends License public function __construct( public int $credits, + public int $comments, public int $storage, // 100MB public bool $sso, public bool $noBranding, @@ -52,6 +53,7 @@ public static function trial(): static { return new self( credits: 1_000, + comments: -1, storage: 100_000_000, sso: true, noBranding: false, diff --git a/src/InternalFake.php b/src/InternalFake.php index 2e7e2b2..394839b 100644 --- a/src/InternalFake.php +++ b/src/InternalFake.php @@ -39,14 +39,14 @@ public function usersDatabase(): ?array /** * Returns a default (trial) license of the component */ - public function license(int $userId, Component $component): ?License + public function license(int $organizationId, Component $component): ?License { $licenseClass = $component->license(); return $licenseClass::trial(); // trial defaults } /** - * Returns a collection of licenses for the given LicenseOf objects. + * sets a trial license for all organizations * @param int[] $organizationIds * @return array */ @@ -55,7 +55,10 @@ public function licenses(array $organizationIds, Component $component): array $licenses = []; $licenseClass = $component->license(); foreach ($organizationIds as $organizationId) { - $licenses[$organizationId] = new ResolvedLicense(ResolvedLicenseType::TRIAL, $licenseClass::trial()); + $licenses[$organizationId] = new ResolvedLicense( + ResolvedLicenseType::TRIAL, + $licenseClass::trial() + ); } return $licenses; } diff --git a/src/InternalServiceProvider.php b/src/InternalServiceProvider.php index 9243b3b..0b7db42 100644 --- a/src/InternalServiceProvider.php +++ b/src/InternalServiceProvider.php @@ -124,12 +124,7 @@ private function fake(): void // fake billing BillingFake::enable( - license: fn(int $userId, ?int $resourceId, Component $component) => $fakeConfig->license( - $userId, - $resourceId, - $component - ), - licenses: fn($of, Component $component) => $fakeConfig->licenses($of, $component) + licenses: fn(array $organizationIds, Component $component) => $fakeConfig->licenses($organizationIds, $component) ); } diff --git a/tests/Bundle/Testing/TestEventDispatcherTest.php b/tests/Bundle/Testing/TestEventDispatcherTest.php index 7576037..8b041e6 100644 --- a/tests/Bundle/Testing/TestEventDispatcherTest.php +++ b/tests/Bundle/Testing/TestEventDispatcherTest.php @@ -10,7 +10,7 @@ class TestEventDispatcherTest extends SymfonyTestCase public function test_dispatcher(): void { - $testDispatcher = TestEventDispatcher::enable($this->container); + $testDispatcher = $this->getEd(); $testDispatcher->dispatch(new TestEvent('test', 10), 'TestEvent'); $dispatchedEvents = $testDispatcher->getDispatchedEvents(); @@ -27,7 +27,8 @@ public function test_dispatcher(): void public function test_mocks(): void { - $testDispatcher = TestEventDispatcher::enable($this->container, [TestDangerousEvent::class]); + $testDispatcher = $this->getEd(); + $testDispatcher->setMockEvents([TestDangerousEvent::class]); $testDispatcher->addListener(TestDangerousEvent::class, function (TestDangerousEvent $event) { // this is not called because TestDangerousEvent is mocked @@ -57,4 +58,4 @@ class TestDangerousEvent public function __construct() { } -} \ No newline at end of file +} diff --git a/tests/Feature/ServiceProvider/FakeTest.php b/tests/Feature/ServiceProvider/FakeTest.php index 18a0db3..260308f 100644 --- a/tests/Feature/ServiceProvider/FakeTest.php +++ b/tests/Feature/ServiceProvider/FakeTest.php @@ -48,8 +48,8 @@ public function testFakes(): void // billing $this->assertTrue($app->bound(BillingInterface::class)); $license = $app->get(BillingInterface::class)->license(1, Component::BLOGS); - $this->assertInstanceOf(BlogsLicense::class, $license); - $this->assertEquals(2, $license->users); + $this->assertInstanceOf(BlogsLicense::class, $license->license); + $this->assertEquals(2, $license->license->users); } public function testDoesNotFakeIfNotEnabled(): void @@ -81,7 +81,7 @@ public function testUsesExtendedClassIfThatIsAvailable(): void config(['internal.fake' => true]); // adds the extended class - include 'internalfakextended.php'; + include __DIR__ . '/internalfakextended.php'; $app = $this->app; assert($app !== null); @@ -96,8 +96,8 @@ public function testUsesExtendedClassIfThatIsAvailable(): void // billing $this->assertTrue($app->bound(Billing::class)); $license = $app->get(Billing::class)->license(1, Component::BLOGS); - $this->assertInstanceOf(BlogsLicense::class, $license); - $this->assertEquals(3, $license->users); + $this->assertInstanceOf(BlogsLicense::class, $license->license); + $this->assertEquals(3, $license->license->users); } } diff --git a/tests/Feature/ServiceProvider/internalfakextended.php b/tests/Feature/ServiceProvider/internalfakextended.php index 13de182..682aefb 100644 --- a/tests/Feature/ServiceProvider/internalfakextended.php +++ b/tests/Feature/ServiceProvider/internalfakextended.php @@ -4,7 +4,8 @@ use Hyvor\Internal\Auth\AuthUser; use Hyvor\Internal\Billing\License\BlogsLicense; -use Hyvor\Internal\Billing\License\License; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; use Hyvor\Internal\Component\Component; class InternalFakeExtended extends InternalFake @@ -15,11 +16,13 @@ public function user(): ?AuthUser return null; } - public function license(int $userId, Component $component): ?License + public function licenses(array $organizationIds, Component $component): array { $license = BlogsLicense::trial(); $license->users = 3; - return $license; + return [ + 1 => new ResolvedLicense(ResolvedLicenseType::TRIAL, $license) + ]; } } diff --git a/tests/Unit/Billing/BillingFakeSymfonyTest.php b/tests/Unit/Billing/BillingFakeSymfonyTest.php index ef2804d..3b874bd 100644 --- a/tests/Unit/Billing/BillingFakeSymfonyTest.php +++ b/tests/Unit/Billing/BillingFakeSymfonyTest.php @@ -11,9 +11,9 @@ class BillingFakeSymfonyTest extends SymfonyTestCase use BillingFakeTestTrait; - protected function enable(array|callable|null $licenses = null): void + protected function enable(array|callable $licenses): void { - BillingFake::enableForSymfony($this->container, $license, $licenses); + BillingFake::enableForSymfony($this->container, $licenses); } } diff --git a/tests/Unit/Billing/BillingFakeTestTrait.php b/tests/Unit/Billing/BillingFakeTestTrait.php index 7b5fc34..d387003 100644 --- a/tests/Unit/Billing/BillingFakeTestTrait.php +++ b/tests/Unit/Billing/BillingFakeTestTrait.php @@ -15,7 +15,7 @@ trait BillingFakeTestTrait /** * @param array|callable $licenses */ - protected abstract function enable(array|callable $licenses = []): void; + protected abstract function enable(array|callable $licenses): void; public function testEnableAndLicense(): void { diff --git a/tests/Unit/Billing/BillingLaravelTest.php b/tests/Unit/Billing/BillingLaravelTest.php index 5d6b0a6..6b1c9da 100644 --- a/tests/Unit/Billing/BillingLaravelTest.php +++ b/tests/Unit/Billing/BillingLaravelTest.php @@ -4,12 +4,11 @@ use Hyvor\Internal\Billing\Billing; use Hyvor\Internal\Billing\SubscriptionIntent; +use Hyvor\Internal\Bundle\Comms\CommsInterface; +use Hyvor\Internal\Bundle\Comms\MockComms; use Hyvor\Internal\InternalApi\InternalApi; use Hyvor\Internal\Tests\LaravelTestCase; use PHPUnit\Framework\Attributes\CoversClass; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Contracts\HttpClient\HttpClientInterface; #[CoversClass(Billing::class)] #[CoversClass(SubscriptionIntent::class)] @@ -18,14 +17,14 @@ class BillingLaravelTest extends LaravelTestCase use BillingTestTrait; - protected function getBilling(): Billing + public function setComms(MockComms $comms): void { - return app(Billing::class); + app()->singleton(CommsInterface::class, fn() => $comms); } - protected function setHttpResponse(MockResponse $response): void + protected function getBilling(): Billing { - app()->singleton(HttpClientInterface::class, fn() => new MockHttpClient($response)); + return app(Billing::class); } protected function getInternalApi(): InternalApi diff --git a/tests/Unit/Billing/BillingSymfonyTest.php b/tests/Unit/Billing/BillingSymfonyTest.php index 993f84f..74a2c15 100644 --- a/tests/Unit/Billing/BillingSymfonyTest.php +++ b/tests/Unit/Billing/BillingSymfonyTest.php @@ -4,10 +4,10 @@ use Hyvor\Internal\Billing\Billing; use Hyvor\Internal\Billing\SubscriptionIntent; +use Hyvor\Internal\Bundle\Comms\MockComms; use Hyvor\Internal\InternalApi\InternalApi; use Hyvor\Internal\Tests\SymfonyTestCase; use PHPUnit\Framework\Attributes\CoversClass; -use Symfony\Component\HttpClient\Response\MockResponse; #[CoversClass(Billing::class)] #[CoversClass(SubscriptionIntent::class)] @@ -16,6 +16,11 @@ class BillingSymfonyTest extends SymfonyTestCase use BillingTestTrait; + function setComms(MockComms $comms): void + { + return; // already set + } + protected function getBilling(): Billing { $billing = $this->container->get(Billing::class); @@ -23,11 +28,6 @@ protected function getBilling(): Billing return $billing; } - protected function setHttpResponse(MockResponse $response): void - { - $this->setHttpClientResponse($response); - } - protected function getInternalApi(): InternalApi { $internalApi = $this->container->get(InternalApi::class); diff --git a/tests/Unit/Billing/BillingTestTrait.php b/tests/Unit/Billing/BillingTestTrait.php index f870603..fd5920a 100644 --- a/tests/Unit/Billing/BillingTestTrait.php +++ b/tests/Unit/Billing/BillingTestTrait.php @@ -4,6 +4,11 @@ use Hyvor\Internal\Billing\Billing; use Hyvor\Internal\Billing\License\BlogsLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicense; +use Hyvor\Internal\Billing\License\Resolved\ResolvedLicenseType; +use Hyvor\Internal\Bundle\Comms\Event\ToCore\License\GetLicenses; +use Hyvor\Internal\Bundle\Comms\Event\ToCore\License\GetLicensesResponse; +use Hyvor\Internal\Bundle\Comms\MockComms; use Hyvor\Internal\Component\Component; use Hyvor\Internal\InternalApi\InternalApi; use Symfony\Component\HttpClient\Response\JsonMockResponse; @@ -14,8 +19,6 @@ trait BillingTestTrait abstract protected function getBilling(): Billing; - abstract protected function setHttpResponse(MockResponse $response): void; - abstract protected function getInternalApi(): InternalApi; public function testSubscriptionIntent(): void @@ -37,74 +40,59 @@ public function testSubscriptionIntent(): void ); } + abstract function setComms(MockComms $comms): void; + public function testGetLicense(): void { - $mockResponse = new JsonMockResponse([ + /** @var MockComms $mockComms */ + $mockComms = $this->getContainer()->get(MockComms::class); + $mockComms->addResponse(GetLicenses::class, new GetLicensesResponse( [ - 'user_id' => 1, - 'resource_id' => 10, - 'license' => BlogsLicense::trial()->serialize() + 1 => new ResolvedLicense(ResolvedLicenseType::TRIAL, BlogsLicense::trial()) ] - ]); - $this->setHttpResponse($mockResponse); + )); + $this->setComms($mockComms); $billing = $this->getBilling(); $license = $billing->license(1, Component::BLOGS); - $this->assertInstanceOf(BlogsLicense::class, $license); - $this->assertEquals(2, $license->users); - - // HTTP Request - $data = $this->getInternalApi()->dataFromMockResponse($mockResponse); - - $this->assertCount(1, $data['of']); - $this->assertEquals(1, $data['of'][0]['user_id']); - $this->assertEquals(10, $data['of'][0]['resource_id']); + $this->assertInstanceOf(BlogsLicense::class, $license->license); + $this->assertEquals(2, $license->license->users); - $headers = $mockResponse->getRequestOptions()['headers']; - $this->assertContains('X-Internal-Api-To: core', $headers); - $this->assertContains('X-Internal-Api-From: blogs', $headers); + $mockComms->assertSent(GetLicenses::class, Component::CORE, eventValidator: function ($event) { + $this->assertEquals([1], $event->getOrganizationIds()); + $this->assertEquals(Component::BLOGS, $event->getComponent()); + }); } public function test_get_licenses(): void { - $mockResponse = new JsonMockResponse([ - [ - 'user_id' => 1, - 'resource_id' => null, - 'license' => BlogsLicense::trial()->serialize() - ], + + /** @var MockComms $mockComms */ + $mockComms = $this->getContainer()->get(MockComms::class); + $mockComms->addResponse(GetLicenses::class, new GetLicensesResponse( [ - 'user_id' => 2, - 'resource_id' => null, - 'license' => null + 1 => new ResolvedLicense(ResolvedLicenseType::TRIAL, BlogsLicense::trial()), + 2 => new ResolvedLicense(ResolvedLicenseType::NONE) ] - ]); - $this->setHttpResponse($mockResponse); + )); + $this->setComms($mockComms); $billing = $this->getBilling(); $licenses = $billing->licenses([1, 2], Component::BLOGS); $this->assertCount(2, $licenses); - $user1License = $licenses[1]; - $this->assertInstanceOf(BlogsLicense::class, $user1License); - - $user2License = $licenses[2]; - - // HTTP Request - $data = $this->getInternalApi()->dataFromMockResponse($mockResponse); - $this->assertIsArray($data['of']); - $this->assertCount(2, $data['of']); + $org1License = $licenses[1]; + $this->assertInstanceOf(BlogsLicense::class, $org1License->license); - $this->assertEquals(1, $data['of'][0]['user_id']); - $this->assertEquals(null, $data['of'][0]['resource_id']); - $this->assertEquals(2, $data['of'][1]['user_id']); - $this->assertEquals(null, $data['of'][1]['resource_id']); + $org2License = $licenses[2]; + $this->assertNull($org2License->license); - $headers = $mockResponse->getRequestOptions()['headers']; - $this->assertContains('X-Internal-Api-To: core', $headers); - $this->assertContains('X-Internal-Api-From: blogs', $headers); + $mockComms->assertSent(GetLicenses::class, Component::CORE, eventValidator: function ($event) { + $this->assertEquals([1, 2], $event->getOrganizationIds()); + $this->assertEquals(Component::BLOGS, $event->getComponent()); + }); } diff --git a/tests/Unit/Billing/LicenseTest.php b/tests/Unit/Billing/LicenseTest.php index 9ed7935..f5e8c62 100644 --- a/tests/Unit/Billing/LicenseTest.php +++ b/tests/Unit/Billing/LicenseTest.php @@ -4,7 +4,6 @@ use Hyvor\Internal\Billing\License\BlogsLicense; use Hyvor\Internal\Billing\License\CoreLicense; -use Hyvor\Internal\Billing\License\DerivedFrom; use Hyvor\Internal\Billing\License\License; use Hyvor\Internal\Billing\License\PostLicense; use Hyvor\Internal\Billing\License\Property\LicensePropertyType; @@ -73,7 +72,8 @@ public function test_license_properties(string $licenseClass): void $this->assertSame( count($declaredProperties), - count($propertyReflections) + count($propertyReflections), + 'all declared properties must exist in class: ' . $licenseClass ); } From f867ef6a829afe8af0d5b8757bd3491f361e5454 Mon Sep 17 00:00:00 2001 From: Supun Wimalasena Date: Sun, 1 Feb 2026 16:55:34 +0100 Subject: [PATCH 4/4] phpstan fixed --- CHANGELOG.md | 1 + bundle/src/Testing/ApiTestingTrait.php | 27 ++++++++++++++++---- src/Billing/BillingFactory.php | 3 +-- tests/Bundle/Testing/ApiTestingTraitTest.php | 6 ++++- tests/Bundle/Testing/TestBrowser.php | 5 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b08e969..a4cf917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - UsageAbstract removed - AuthMiddleware removed in Laravel - Laravel built-in auth routes removed (/api/auth/check, /api/auth/login, etc.) +- assertFailed() on ApiTestingTrait is deprecated ## 3.1.8 - 2025-11-03 diff --git a/bundle/src/Testing/ApiTestingTrait.php b/bundle/src/Testing/ApiTestingTrait.php index 5863142..68dd162 100644 --- a/bundle/src/Testing/ApiTestingTrait.php +++ b/bundle/src/Testing/ApiTestingTrait.php @@ -2,6 +2,7 @@ namespace Hyvor\Internal\Bundle\Testing; +use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\HttpFoundation\Response; trait ApiTestingTrait @@ -14,7 +15,9 @@ trait ApiTestingTrait */ public function getJson(): array { - $response = self::getClient()->getResponse(); + /** @var AbstractBrowser $client */ + $client = self::getClient(); + $response = $client->getResponse(); $content = $response->getContent(); $this->assertNotFalse($content); $this->assertJson($content); @@ -23,9 +26,19 @@ public function getJson(): array return $json; } + /** + * @deprecated use assertResponseFailed + */ public function assertFailed(int $code, ?string $message = null): void { - $response = self::getClient()->getResponse(); + $this->assertResponseFailed($code, $message); + } + + public function assertResponseFailed(int $code, ?string $message = null): void + { + /** @var AbstractBrowser $client */ + $client = self::getClient(); + $response = $client->getResponse(); $this->assertSame($code, $response->getStatusCode()); if ($message !== null) { @@ -36,7 +49,9 @@ public function assertFailed(int $code, ?string $message = null): void public function assertViolationCount(int $count): void { - $response = self::getClient()->getResponse(); + /** @var AbstractBrowser $client */ + $client = self::getClient(); + $response = $client->getResponse(); $this->assertSame(Response::HTTP_UNPROCESSABLE_ENTITY, $response->getStatusCode()); $response = $this->getJson(); @@ -48,7 +63,9 @@ public function assertViolationCount(int $count): void public function assertHasViolation(string $property, string $message = ''): void { - $response = self::getClient()->getResponse(); + /** @var AbstractBrowser $client */ + $client = self::getClient(); + $response = $client->getResponse(); $this->assertSame(Response::HTTP_UNPROCESSABLE_ENTITY, $response->getStatusCode()); $response = $this->getJson(); @@ -70,4 +87,4 @@ public function assertHasViolation(string $property, string $message = ''): void $this->assertTrue($found, 'Violation not found'); } -} \ No newline at end of file +} diff --git a/src/Billing/BillingFactory.php b/src/Billing/BillingFactory.php index f4c3442..e5e0413 100644 --- a/src/Billing/BillingFactory.php +++ b/src/Billing/BillingFactory.php @@ -22,11 +22,10 @@ public function create(): BillingInterface $fakeLicenseProvider = new BillingFakeLicenseProvider(get_class($fake)); return new BillingFake( $this->internalConfig, - [$fakeLicenseProvider, 'license'], [$fakeLicenseProvider, 'licenses'] ); } return $this->billing; } -} \ No newline at end of file +} diff --git a/tests/Bundle/Testing/ApiTestingTraitTest.php b/tests/Bundle/Testing/ApiTestingTraitTest.php index 76424ce..d32196f 100644 --- a/tests/Bundle/Testing/ApiTestingTraitTest.php +++ b/tests/Bundle/Testing/ApiTestingTraitTest.php @@ -4,6 +4,7 @@ use Hyvor\Internal\Bundle\Testing\ApiTestingTrait; use PHPUnit\Framework\TestCase; +use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\DependencyInjection\Container; class ApiTestingTraitTest extends TestCase @@ -24,7 +25,10 @@ private function setJson(array $json, int $status = 200): void self::$status = $status; } - public static function getClient(): TestBrowser + /** + * @return AbstractBrowser + */ + public static function getClient(): AbstractBrowser { $browser = new TestBrowser(); $browser->setJson(self::$json, self::$status); diff --git a/tests/Bundle/Testing/TestBrowser.php b/tests/Bundle/Testing/TestBrowser.php index 45a22da..f68c629 100644 --- a/tests/Bundle/Testing/TestBrowser.php +++ b/tests/Bundle/Testing/TestBrowser.php @@ -4,10 +4,9 @@ use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\BrowserKit\Response; -use Symfony\Component\HttpFoundation\Request; /** - * @extends AbstractBrowser + * @extends AbstractBrowser */ class TestBrowser extends AbstractBrowser { @@ -27,4 +26,4 @@ protected function doRequest(object $request): Response 'Content-Type' => 'application/json', ]); } -} \ No newline at end of file +}