diff --git a/.env.test b/.env.test index 64bd1114..03fd82d4 100644 --- a/.env.test +++ b/.env.test @@ -1,3 +1,11 @@ # define your env variables for the test env here KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' + +# Test DB: doctrine's when@test config appends the `_test` suffix (see +# config/packages/doctrine.yaml), so this base name `db` becomes `db_test`. +# That database is created in ddev and granted to user `db`. +DATABASE_URL="mysql://db:db@db:3306/db?serverVersion=8.0&charset=utf8mb4" + +# JWT — generated keypair is shared with dev; passphrase from .env is fine. +# Redis cache/messenger use the same ddev redis; tests don't depend on it. diff --git a/tests/ApiTestCase.php b/tests/ApiTestCase.php new file mode 100644 index 00000000..d575135e --- /dev/null +++ b/tests/ApiTestCase.php @@ -0,0 +1,74 @@ +client = static::createClient(); + $this->em = static::getContainer()->get(EntityManagerInterface::class); + } + + /** + * Persist a user with the given roles. Mobile is randomised per test to + * avoid unique-constraint clashes across cases without a full DB reset. + */ + protected function createUser(array $roles = ['ROLE_USER'], ?string $mobile = null): User + { + $mobile ??= '0912' . str_pad((string) random_int(0, 9_999_999), 7, '0', STR_PAD_LEFT); + $user = new User($mobile); + $user->setRoles($roles); + $user->setStatus(1); + $this->em->persist($user); + $this->em->flush(); + + return $user; + } + + protected function jwtFor(User $user): string + { + return static::getContainer() + ->get(JWTTokenManagerInterface::class) + ->create($user); + } + + /** + * Issue an authenticated JSON request and return the decoded response body. + */ + protected function authJson(string $method, string $uri, User $user, array $body = []): array + { + $this->client->request( + $method, + $uri, + server: [ + 'HTTP_AUTHORIZATION' => 'Bearer ' . $this->jwtFor($user), + 'CONTENT_TYPE' => 'application/json', + ], + content: $body ? json_encode($body) : null, + ); + + return json_decode($this->client->getResponse()->getContent(), true) ?? []; + } + + protected function responseCode(): int + { + return $this->client->getResponse()->getStatusCode(); + } +} diff --git a/tests/Smoke/InfraSmokeTest.php b/tests/Smoke/InfraSmokeTest.php new file mode 100644 index 00000000..183fe5e6 --- /dev/null +++ b/tests/Smoke/InfraSmokeTest.php @@ -0,0 +1,34 @@ +client->request('GET', '/health'); + $this->assertSame(200, $this->responseCode()); + } + + public function testUnauthenticatedApiIs401(): void + { + $this->client->request('GET', '/oauth/userinfo'); + $this->assertSame(401, $this->responseCode()); + } + + public function testJwtAuthReachesUserInfo(): void + { + $user = $this->createUser(['ROLE_USER']); + $body = $this->authJson('GET', '/oauth/userinfo', $user); + + $this->assertSame(200, $this->responseCode()); + $this->assertTrue($body['success']); + $this->assertSame($user->getUuid(), $body['data']['uuid']); + } +}