From f3008aa11aef537a78672c7f5db94e58bbeb7d87 Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 7 Apr 2024 11:01:39 +0200 Subject: [PATCH 1/4] Update tests and GH workflow --- .github/workflows/tests.yml | 38 ++++++------- composer.json | 2 +- phpunit.xml | 26 +++++++++ phpunit.xml.dist | 14 ----- src/JwtHttpBearerAuth.php | 15 ++---- src/JwtTools.php | 9 ++-- tests/ConsecutiveCalls.php | 44 ++++++++++----- tests/standard/BearerTest.php | 68 +++++++++++------------ tests/standard/ConstraintsConfigTest.php | 8 +-- tests/standard/JwtTest.php | 41 +++++--------- tests/standard/SignerTest.php | 13 +++-- tests/stubs/TestAuthController.php | 3 +- tests/toolset/BearerTest.php | 69 ++++++++++++------------ tests/toolset/ConstraintsConfigTest.php | 9 ++-- tests/toolset/JwtToolsTest.php | 45 ++++++---------- tests/toolset/SignerTest.php | 12 ++--- 16 files changed, 202 insertions(+), 214 deletions(-) create mode 100644 phpunit.xml delete mode 100644 phpunit.xml.dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5fb1db3..b372ecd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,8 +9,6 @@ on: jobs: PHPStan: runs-on: ubuntu-latest - strategy: - fail-fast: false steps: - name: Checkout @@ -19,26 +17,23 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.3' extensions: mbstring, intl coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} update: true - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies + - name: Cache vendor uses: actions/cache@v4 + id: cache-vendor with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- + path: ./vendor + key: ${{ runner.os }}-8.3-vendor-${{ hashFiles('./composer.json') }} - name: Install dependencies - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader + if: steps.cache-vendor.outputs.cache-hit != 'true' + run: composer i --prefer-dist --no-interaction --no-progress --optimize-autoloader - name: PHPStan tests run: vendor/bin/phpstan analyze -l 9 -a vendor/yiisoft/yii2/Yii.php --no-progress src @@ -49,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.1', '8.2'] + php: ['8.1', '8.2', '8.3', '8.4'] steps: - name: Checkout @@ -65,26 +60,23 @@ jobs: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} update: true - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies + - name: Cache vendor uses: actions/cache@v4 + id: cache-vendor with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- + path: ./vendor + key: ${{ runner.os }}-${{ matrix.php }}-vendor-${{ hashFiles('./composer.json') }} - name: Install dependencies + if: steps.cache-vendor.outputs.cache-hit != 'true' run: composer update --no-interaction --no-progress --optimize-autoloader - name: Run PHPUnit - if: matrix.php != '8.1' + if: matrix.php != '8.3' run: vendor/bin/phpunit - name: Run Infection with PHPUnit - if: matrix.php == '8.1' + if: matrix.php == '8.3' run: | mkdir -p build/logs vendor/bin/phpunit --coverage-xml=build/logs/coverage-xml --log-junit=build/logs/junit.xml diff --git a/composer.json b/composer.json index ab1f8df..689f33c 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "authors": [ { "name": "Paweł Bizley Brzozowski", - "email": "pawel@positive.codes" + "email": "pawel.bizley@gmail.com" }, { "name": "Dmitriy Demin", diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..806ab1e --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ + + + + + tests + + + + + + src + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 75401ae..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - ./tests - - - - - - ./src - - - diff --git a/src/JwtHttpBearerAuth.php b/src/JwtHttpBearerAuth.php index 2517d59..0d9523f 100644 --- a/src/JwtHttpBearerAuth.php +++ b/src/JwtHttpBearerAuth.php @@ -7,8 +7,6 @@ use Lcobucci\JWT\Encoding\CannotDecodeContent; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation; -use Throwable; -use Yii; use yii\base\InvalidConfigException; use yii\di\Instance; use yii\filters\auth\HttpBearerAuth; @@ -18,9 +16,6 @@ use yii\web\UnauthorizedHttpException; use yii\web\User; -use function call_user_func; -use function get_class; - /** * JwtHttpBearerAuth is an action filter that supports the authentication method based on HTTP Bearer JSON Web Token. * @@ -126,8 +121,8 @@ public function authenticate($user, $request, $response): ?IdentityInterface // if (!empty($data)) { $token = $this->processToken($data); } - } catch (Throwable $exception) { - Yii::warning($exception->getMessage(), 'JwtHttpBearerAuth'); + } catch (\Throwable $exception) { + \Yii::warning($exception->getMessage(), 'JwtHttpBearerAuth'); if (!$this->throwException) { return null; } @@ -135,10 +130,10 @@ public function authenticate($user, $request, $response): ?IdentityInterface // } if ($token !== null) { - if (is_callable($this->auth, true)) { - $identity = call_user_func($this->auth, $token); + if (\is_callable($this->auth, true)) { + $identity = \call_user_func($this->auth, $token); } else { - $identity = $user->loginByAccessToken($token->toString(), get_class($this)); + $identity = $user->loginByAccessToken($token->toString(), \get_class($this)); } } diff --git a/src/JwtTools.php b/src/JwtTools.php index 200dd3b..7af2194 100644 --- a/src/JwtTools.php +++ b/src/JwtTools.php @@ -16,7 +16,6 @@ use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation; use Lcobucci\JWT\Validator; -use Yii; use yii\base\Component; use yii\base\InvalidConfigException; use yii\di\Instance; @@ -86,10 +85,10 @@ private function buildObjectFromArray(array $config): object $keys = \array_keys($config); if (\is_string(\reset($keys))) { // most probably Yii-style config - return Yii::createObject($config); + return \Yii::createObject($config); } - return Yii::createObject(...$config); + return \Yii::createObject(...$config); } /** @@ -176,7 +175,7 @@ public function buildKey($key): Signer\Key } if (\str_starts_with($key, '@')) { $keyConfig = [ - Jwt::KEY => Yii::getAlias($key), + Jwt::KEY => \Yii::getAlias($key), Jwt::METHOD => Jwt::METHOD_FILE, ]; } elseif (\str_starts_with($key, 'file://')) { @@ -236,7 +235,7 @@ public function buildSigner($signer): Signer } if (\in_array($signer, [Jwt::ES256, Jwt::ES384, Jwt::ES512], true)) { - Yii::$container->set(Signer\Ecdsa\SignatureConverter::class, Signer\Ecdsa\MultibyteStringConverter::class); + \Yii::$container->set(Signer\Ecdsa\SignatureConverter::class, Signer\Ecdsa\MultibyteStringConverter::class); } /** @var Signer $signerInstance */ diff --git a/tests/ConsecutiveCalls.php b/tests/ConsecutiveCalls.php index d95eb69..bf5fbb6 100644 --- a/tests/ConsecutiveCalls.php +++ b/tests/ConsecutiveCalls.php @@ -5,35 +5,51 @@ namespace bizley\tests; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Constraint\Constraint; class ConsecutiveCalls extends Assert { - public const NEVER = 'never'; - public const RETURN = 'return'; + /** + * @var array + */ + private array $data = []; + private int $internalCounter = -1; /** - * @param array $data + * @param mixed[] ...$args */ - public function __construct(private array $data, private readonly string $mode = self::RETURN) + private function __construct(array ...$args) { + foreach ($args as $arg) { + if (!\is_array($arg)) { + throw new \InvalidArgumentException('All arguments must be arrays'); + } + $this->data[] = $arg; + } } /** - * @param mixed ...$args - * @return mixed|void|null + * @param mixed[] ...$arguments */ - public function __invoke(...$args) + public static function withArgs(array ...$arguments): self { - $testData = \array_shift($this->data); + return new self(...$arguments); + } - if ($this->mode === self::NEVER) { - self::assertSame($testData, $args); - } else { - $returned = $testData ? \array_pop($testData) : null; - self::assertSame($testData, $args); + public function __invoke(mixed ...$args): void + { + $testData = $this->data[++$this->internalCounter] ?? null; + if ($testData === null) { + $testData = $this->data[$this->internalCounter % \count($this->data)]; + } - return $returned; + foreach ($testData as $key => $value) { + if ($value instanceof Constraint) { + $value->evaluate($args[$key]); + } else { + self::assertEquals($value, $args[$key]); + } } } } diff --git a/tests/standard/BearerTest.php b/tests/standard/BearerTest.php index 44143a0..cdba47d 100644 --- a/tests/standard/BearerTest.php +++ b/tests/standard/BearerTest.php @@ -12,15 +12,13 @@ use bizley\tests\stubs\TestStub2Controller; use bizley\tests\stubs\TestStubController; use bizley\tests\stubs\UserIdentity; -use DateTimeImmutable; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\Constraint\IssuedBy; use Lcobucci\JWT\Validation\Constraint\LooseValidAt; use Lcobucci\JWT\Validation\NoConstraintsGiven; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use stdClass; -use Yii; use yii\base\InvalidConfigException; use yii\log\Logger; use yii\rest\Controller; @@ -28,6 +26,8 @@ use yii\web\Response; use yii\web\UnauthorizedHttpException; +#[CoversClass(JwtHttpBearerAuth::class)] +#[CoversClass(Jwt::class)] class BearerTest extends TestCase { protected function setUp(): void @@ -64,13 +64,13 @@ protected function setUp(): void protected function getJwt(): Jwt { - return Yii::$app->jwt; + return \Yii::$app->jwt; } public function testEmptyPattern(): void { $this->expectException(InvalidConfigException::class); - $controller = Yii::$app->createController('test-stub')[0]; + $controller = \Yii::$app->createController('test-stub')[0]; $controller->run('test'); } @@ -80,7 +80,7 @@ public function testHttpBearerAuthNoHeader(): void $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -89,10 +89,10 @@ public function testHttpBearerAuthInvalidToken(): void $this->expectException(Token\InvalidTokenStructure::class); $this->expectExceptionMessage('The JWT string must have two dots'); - Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); + \Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -101,10 +101,10 @@ public function testHttpBearerAuthInvalidHeader(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - Yii::$app->request->headers->set('Authorization', 'InvalidHeaderValue'); + \Yii::$app->request->headers->set('Authorization', 'InvalidHeaderValue'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -113,7 +113,7 @@ public function testHttpBearerAuthExpiredToken(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->getConfiguration()->setValidationConstraints( new LooseValidAt(SystemClock::fromSystemTimezone()) @@ -125,16 +125,16 @@ public function testHttpBearerAuthExpiredToken(): void ->getToken($this->getJwt()->getConfiguration()->signer(), $this->getJwt()->getConfiguration()->signingKey()) ->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } public function testHttpBearerAuth(): void { - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->getConfiguration()->setValidationConstraints( new LooseValidAt(SystemClock::fromSystemTimezone()), @@ -150,17 +150,17 @@ public function testHttpBearerAuth(): void UserIdentity::$token = $token; - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /** @var Controller $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; self::assertEquals('test', $controller->run('filtered')); } public function testHttpBearerAuthCustom(): void { - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->getConfiguration()->setValidationConstraints( new LooseValidAt(SystemClock::fromSystemTimezone()) @@ -174,13 +174,13 @@ public function testHttpBearerAuthCustom(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { $identity = UserIdentity::findIdentity($token->claims()->get('sub')); - Yii::$app->user->switchIdentity($identity); + \Yii::$app->user->switchIdentity($identity); return $identity; }; @@ -192,7 +192,7 @@ public function testHttpBearerAuthCustomNoIdentity(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->getConfiguration()->setValidationConstraints(new LooseValidAt(SystemClock::fromSystemTimezone())); @@ -204,10 +204,10 @@ public function testHttpBearerAuthCustomNoIdentity(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { return null; }; @@ -219,7 +219,7 @@ public function testHttpBearerAuthCustomNotIdentityInterface(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->getConfiguration()->setValidationConstraints(new LooseValidAt(SystemClock::fromSystemTimezone())); @@ -231,12 +231,12 @@ public function testHttpBearerAuthCustomNotIdentityInterface(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { - return new stdClass(); + return new \stdClass(); }; $controller->run('filtered'); } @@ -269,21 +269,21 @@ public function testFailedToken(): void $logger = $this->createMock(Logger::class); $logger->expects(self::exactly(2))->method('log')->willReturnCallback( - new ConsecutiveCalls([ + ConsecutiveCalls::withArgs( ['Route to run: test-stub2/test', 8, 'yii\base\Controller::runAction'], ['No constraint given.', 2, 'JwtHttpBearerAuth'], - ], ConsecutiveCalls::NEVER) + ) ); - Yii::setLogger($logger); + \Yii::setLogger($logger); $token = $this->getJwt()->getBuilder() ->getToken($this->getJwt()->getConfiguration()->signer(), $this->getJwt()->getConfiguration()->signingKey()) ->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-stub2')[0]; + $controller = \Yii::$app->createController('test-stub2')[0]; $controller->run('test'); self::assertSame(14, $controller->flag); } @@ -294,10 +294,10 @@ public function testSilentException(): void $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); // instead of 'The JWT string must have two dots' - Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); + \Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['throwException'] = false; $controller->run('filtered'); } diff --git a/tests/standard/ConstraintsConfigTest.php b/tests/standard/ConstraintsConfigTest.php index 741770c..6df0915 100644 --- a/tests/standard/ConstraintsConfigTest.php +++ b/tests/standard/ConstraintsConfigTest.php @@ -6,25 +6,25 @@ use bizley\jwt\Jwt; use bizley\tests\stubs\YiiConstraint; -use Closure; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\Constraint; use Lcobucci\JWT\Validation\Constraint\IdentifiedBy; use Lcobucci\JWT\Validation\Constraint\RelatedTo; use Lcobucci\JWT\Validation\NoConstraintsGiven; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Yii; use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] class ConstraintsConfigTest extends TestCase { /** - * @param array|Closure|null $validationConstraints + * @param array|\Closure|null $validationConstraints * @throws InvalidConfigException */ private function getJwt($validationConstraints): Jwt { - return Yii::createObject( + return \Yii::createObject( [ 'class' => Jwt::class, 'signer' => Jwt::HS256, diff --git a/tests/standard/JwtTest.php b/tests/standard/JwtTest.php index 5147d96..68d9df9 100644 --- a/tests/standard/JwtTest.php +++ b/tests/standard/JwtTest.php @@ -11,11 +11,13 @@ use Lcobucci\JWT\Signer; use Lcobucci\JWT\Validation\Constraint\IdentifiedBy; use Lcobucci\JWT\Validation\RequiredConstraintsViolated; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; -use stdClass; -use Yii; use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] class JwtTest extends TestCase { private function getJwt(): Jwt @@ -89,9 +91,7 @@ public function testValidateFail(): void self::assertFalse($jwt->validate($token)); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testAssertSuccess(): void { $jwt = $this->getJwt(); @@ -101,9 +101,7 @@ public function testAssertSuccess(): void $jwt->assert($token); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testAssertSuccessWithStringToken(): void { $jwt = $this->getJwt(); @@ -128,20 +126,17 @@ public function testAssertFail(): void public static function providerForInvalidKey(): iterable { - yield 'object' => [new stdClass(), 'Invalid key configuration!']; + yield 'object' => [new \stdClass(), 'Invalid key configuration!']; yield 'int value' => [[Jwt::KEY => 1], 'Invalid key value!']; yield 'array value' => [[Jwt::KEY => []], 'Invalid key value!']; - yield 'object value' => [[Jwt::KEY => new stdClass()], 'Invalid key value!']; + yield 'object value' => [[Jwt::KEY => new \stdClass()], 'Invalid key value!']; yield 'method' => [[Jwt::KEY => 'k', Jwt::METHOD => ''], 'Invalid key method!']; yield 'int pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => 1], 'Invalid key passphrase!']; yield 'array pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => []], 'Invalid key passphrase!']; - yield 'object pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => new stdClass()], 'Invalid key passphrase!']; + yield 'object pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => new \stdClass()], 'Invalid key passphrase!']; } - /** - * @dataProvider providerForInvalidKey - * @param mixed $key - */ + #[DataProvider('providerForInvalidKey')] public function testInvalidKey($key, string $message): void { $this->expectExceptionMessage($message); @@ -203,10 +198,7 @@ public static function providerForWrongKeyNames(): iterable yield 'file://' => ['_file://' . __DIR__ . '/data/rs256.key']; } - /** - * @dataProvider providerForWrongKeyNames - * @throws InvalidConfigException - */ + #[DataProvider('providerForWrongKeyNames')] public function testWrongFileKeyNameStartingCharacters(string $key): void { $jwt = new Jwt( @@ -225,10 +217,7 @@ public static function providerForRightKeyNames(): iterable yield 'file://' => ['file://' . __DIR__ . '/../data/rs256.key']; } - /** - * @dataProvider providerForRightKeyNames - * @throws InvalidConfigException - */ + #[DataProvider('providerForRightKeyNames')] public function testRightFileKeyNameStartingCharacters(string $key): void { $jwt = new Jwt( @@ -302,15 +291,13 @@ public static function providerForSignerSignatureConverter(): iterable yield Jwt::ES512 => [Jwt::ES512]; } - /** - * @dataProvider providerForSignerSignatureConverter - */ + #[DataProvider('providerForSignerSignatureConverter')] public function testPrepareSignatureConverter(string $signerId): void { new Jwt(['signer' => $signerId, 'signingKey' => ' ', 'verifyingKey' => ' ']); $this->assertInstanceOf( Signer\Ecdsa\MultibyteStringConverter::class, - Yii::$container->get(Signer\Ecdsa\SignatureConverter::class) + \Yii::$container->get(Signer\Ecdsa\SignatureConverter::class) ); } } diff --git a/tests/standard/SignerTest.php b/tests/standard/SignerTest.php index ed3398e..b1d4b2a 100644 --- a/tests/standard/SignerTest.php +++ b/tests/standard/SignerTest.php @@ -9,10 +9,12 @@ use Lcobucci\JWT\Signer\InvalidKeyProvided; use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Validation\Constraint\SignedWith; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use Yii; use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] class SignerTest extends TestCase { /** @@ -21,8 +23,8 @@ class SignerTest extends TestCase public function getJwt(array $config = []): Jwt { /** @var Jwt $jwt */ - $jwt = Yii::createObject( - array_merge( + $jwt = \Yii::createObject( + \array_merge( ['class' => Jwt::class], $config ) @@ -177,10 +179,7 @@ public static function providerForSigners(): iterable ]; } - /** - * @dataProvider providerForSigners - * @throws InvalidConfigException - */ + #[DataProvider('providerForSigners')] public function testParseTokenWithSignature(array $config, string $algorithm): void { $jwt = $this->getJwt($config); diff --git a/tests/stubs/TestAuthController.php b/tests/stubs/TestAuthController.php index 926cddd..970b21a 100644 --- a/tests/stubs/TestAuthController.php +++ b/tests/stubs/TestAuthController.php @@ -5,7 +5,6 @@ namespace bizley\tests\stubs; use bizley\jwt\JwtHttpBearerAuth; -use Yii; use yii\rest\Controller; class TestAuthController extends Controller @@ -24,6 +23,6 @@ public function behaviors(): array public function actionFiltered(): ?string { - return Yii::$app->user->id; + return \Yii::$app->user->id; } } diff --git a/tests/toolset/BearerTest.php b/tests/toolset/BearerTest.php index f832f47..ba4ca12 100644 --- a/tests/toolset/BearerTest.php +++ b/tests/toolset/BearerTest.php @@ -13,15 +13,13 @@ use bizley\tests\stubs\TestStub2Controller; use bizley\tests\stubs\TestStubController; use bizley\tests\stubs\UserIdentity; -use DateTimeImmutable; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\Constraint\IssuedBy; use Lcobucci\JWT\Validation\Constraint\LooseValidAt; use Lcobucci\JWT\Validation\NoConstraintsGiven; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use stdClass; -use Yii; use yii\base\InvalidConfigException; use yii\log\Logger; use yii\rest\Controller; @@ -29,6 +27,9 @@ use yii\web\Response; use yii\web\UnauthorizedHttpException; +#[CoversClass(JwtHttpBearerAuth::class)] +#[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class BearerTest extends TestCase { protected function setUp(): void @@ -63,13 +64,13 @@ protected function setUp(): void protected function getJwt(): JwtTools { - return Yii::$app->jwt; + return \Yii::$app->jwt; } public function testEmptyPattern(): void { $this->expectException(InvalidConfigException::class); - $controller = Yii::$app->createController('test-stub')[0]; + $controller = \Yii::$app->createController('test-stub')[0]; $controller->run('test'); } @@ -79,7 +80,7 @@ public function testHttpBearerAuthNoHeader(): void $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -88,10 +89,10 @@ public function testHttpBearerAuthInvalidToken(): void $this->expectException(Token\InvalidTokenStructure::class); $this->expectExceptionMessage('The JWT string must have two dots'); - Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); + \Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -100,10 +101,10 @@ public function testHttpBearerAuthInvalidHeader(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - Yii::$app->request->headers->set('Authorization', 'InvalidHeaderValue'); + \Yii::$app->request->headers->set('Authorization', 'InvalidHeaderValue'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } @@ -112,7 +113,7 @@ public function testHttpBearerAuthExpiredToken(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->validationConstraints = [new LooseValidAt(SystemClock::fromSystemTimezone())]; @@ -125,16 +126,16 @@ public function testHttpBearerAuthExpiredToken(): void ) ->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->run('filtered'); } public function testHttpBearerAuth(): void { - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->validationConstraints = [ new LooseValidAt(SystemClock::fromSystemTimezone()), @@ -153,17 +154,17 @@ public function testHttpBearerAuth(): void UserIdentity::$token = $token; - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /** @var Controller $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; self::assertEquals('test', $controller->run('filtered')); } public function testHttpBearerAuthCustom(): void { - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->validationConstraints = [new LooseValidAt(SystemClock::fromSystemTimezone())]; @@ -178,13 +179,13 @@ public function testHttpBearerAuthCustom(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { $identity = UserIdentity::findIdentity($token->claims()->get('sub')); - Yii::$app->user->switchIdentity($identity); + \Yii::$app->user->switchIdentity($identity); return $identity; }; @@ -196,7 +197,7 @@ public function testHttpBearerAuthCustomNoIdentity(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->validationConstraints = [new LooseValidAt(SystemClock::fromSystemTimezone())]; @@ -211,10 +212,10 @@ public function testHttpBearerAuthCustomNoIdentity(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { return null; }; @@ -226,7 +227,7 @@ public function testHttpBearerAuthCustomNotIdentityInterface(): void $this->expectException(UnauthorizedHttpException::class); $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); - $now = new DateTimeImmutable(); + $now = new \DateTimeImmutable(); $this->getJwt()->validationConstraints = [new LooseValidAt(SystemClock::fromSystemTimezone())]; @@ -241,12 +242,12 @@ public function testHttpBearerAuthCustomNotIdentityInterface(): void $JWT = $token->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); + \Yii::$app->request->headers->set('Authorization', "Bearer $JWT"); /** @var TestAuthController $controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['auth'] = static function (Token $token) { - return new stdClass(); + return new \stdClass(); }; $controller->run('filtered'); } @@ -279,12 +280,12 @@ public function testFailedToken(): void $logger = $this->createMock(Logger::class); $logger->expects(self::exactly(2))->method('log')->willReturnCallback( - new ConsecutiveCalls([ + ConsecutiveCalls::withArgs( ['Route to run: test-stub2/test', 8, 'yii\base\Controller::runAction'], ['No constraint given.', 2, 'JwtHttpBearerAuth'], - ], ConsecutiveCalls::NEVER) + ) ); - Yii::setLogger($logger); + \Yii::setLogger($logger); $token = $this->getJwt()->getBuilder() ->getToken( @@ -293,10 +294,10 @@ public function testFailedToken(): void ) ->toString(); - Yii::$app->request->headers->set('Authorization', "Bearer $token"); + \Yii::$app->request->headers->set('Authorization', "Bearer $token"); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-stub2')[0]; + $controller = \Yii::$app->createController('test-stub2')[0]; $controller->run('test'); self::assertSame(14, $controller->flag); } @@ -307,10 +308,10 @@ public function testSilentException(): void $this->expectExceptionMessage('Your request was made with invalid or expired JSON Web Token.'); // instead of 'The JWT string must have two dots' - Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); + \Yii::$app->request->headers->set('Authorization', 'Bearer InvalidToken'); /* @var $controller Controller */ - $controller = Yii::$app->createController('test-auth')[0]; + $controller = \Yii::$app->createController('test-auth')[0]; $controller->filterConfig['throwException'] = false; $controller->run('filtered'); } diff --git a/tests/toolset/ConstraintsConfigTest.php b/tests/toolset/ConstraintsConfigTest.php index f68d0eb..1357f3e 100644 --- a/tests/toolset/ConstraintsConfigTest.php +++ b/tests/toolset/ConstraintsConfigTest.php @@ -7,25 +7,26 @@ use bizley\jwt\Jwt; use bizley\jwt\JwtTools; use bizley\tests\stubs\YiiConstraint; -use Closure; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\Constraint; use Lcobucci\JWT\Validation\Constraint\IdentifiedBy; use Lcobucci\JWT\Validation\Constraint\RelatedTo; use Lcobucci\JWT\Validation\NoConstraintsGiven; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Yii; use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class ConstraintsConfigTest extends TestCase { /** - * @param array|Closure|null $validationConstraints + * @param array|\Closure|null $validationConstraints * @throws InvalidConfigException */ private function getJwt($validationConstraints): JwtTools { - return Yii::createObject( + return \Yii::createObject( [ 'class' => JwtTools::class, 'validationConstraints' => $validationConstraints, diff --git a/tests/toolset/JwtToolsTest.php b/tests/toolset/JwtToolsTest.php index bae17d2..a11f144 100644 --- a/tests/toolset/JwtToolsTest.php +++ b/tests/toolset/JwtToolsTest.php @@ -12,11 +12,13 @@ use Lcobucci\JWT\Signer; use Lcobucci\JWT\Validation\Constraint\IdentifiedBy; use Lcobucci\JWT\Validation\RequiredConstraintsViolated; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; -use stdClass; -use Yii; -use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class JwtToolsTest extends TestCase { private function getJwt(): JwtTools @@ -77,9 +79,7 @@ public function testValidateFail(): void self::assertFalse($jwt->validate($token)); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testAssertSuccess(): void { $jwt = $this->getJwt(); @@ -91,9 +91,7 @@ public function testAssertSuccess(): void $jwt->assert($token); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testAssertSuccessWithStringToken(): void { $jwt = $this->getJwt(); @@ -119,20 +117,17 @@ public function testAssertFail(): void public static function providerForInvalidKey(): iterable { - yield 'object' => [new stdClass(), 'Invalid key configuration!']; + yield 'object' => [new \stdClass(), 'Invalid key configuration!']; yield 'int value' => [[Jwt::KEY => 1], 'Invalid key value!']; yield 'array value' => [[Jwt::KEY => []], 'Invalid key value!']; - yield 'object value' => [[Jwt::KEY => new stdClass()], 'Invalid key value!']; + yield 'object value' => [[Jwt::KEY => new \stdClass()], 'Invalid key value!']; yield 'method' => [[Jwt::KEY => 'k', Jwt::METHOD => ''], 'Invalid key method!']; yield 'int pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => 1], 'Invalid key passphrase!']; yield 'array pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => []], 'Invalid key passphrase!']; - yield 'object pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => new stdClass()], 'Invalid key passphrase!']; + yield 'object pass' => [[Jwt::KEY => 'k', Jwt::PASSPHRASE => new \stdClass()], 'Invalid key passphrase!']; } - /** - * @dataProvider providerForInvalidKey - * @param mixed $key - */ + #[DataProvider('providerForInvalidKey')] public function testInvalidKey($key, string $message): void { $this->expectExceptionMessage($message); @@ -185,10 +180,7 @@ public static function providerForWrongKeyNames(): iterable yield 'file://' => ['_file://' . __DIR__ . '/data/rs256.key']; } - /** - * @dataProvider providerForWrongKeyNames - * @throws InvalidConfigException - */ + #[DataProvider('providerForWrongKeyNames')] public function testWrongFileKeyNameStartingCharacters(string $key): void { $jwt = new Jwt( @@ -207,10 +199,7 @@ public static function providerForRightKeyNames(): iterable yield 'file://' => ['file://' . __DIR__ . '/../data/rs256.key']; } - /** - * @dataProvider providerForRightKeyNames - * @throws InvalidConfigException - */ + #[DataProvider('providerForRightKeyNames')] public function testRightFileKeyNameStartingCharacters(string $key): void { $jwt = new Jwt( @@ -284,16 +273,14 @@ public static function providerForSignerSignatureConverter(): iterable yield Jwt::ES512 => [Jwt::ES512]; } - /** - * @dataProvider providerForSignerSignatureConverter - */ + #[DataProvider('providerForSignerSignatureConverter')] public function testPrepareSignatureConverter(string $signerId): void { - Yii::$container->clear(Signer\Ecdsa\SignatureConverter::class); + \Yii::$container->clear(Signer\Ecdsa\SignatureConverter::class); new Jwt(['signer' => $signerId, 'signingKey' => ' ', 'verifyingKey' => ' ']); $this->assertInstanceOf( Signer\Ecdsa\MultibyteStringConverter::class, - Yii::$container->get(Signer\Ecdsa\SignatureConverter::class) + \Yii::$container->get(Signer\Ecdsa\SignatureConverter::class) ); } diff --git a/tests/toolset/SignerTest.php b/tests/toolset/SignerTest.php index 39bf8a3..459cef4 100644 --- a/tests/toolset/SignerTest.php +++ b/tests/toolset/SignerTest.php @@ -10,10 +10,13 @@ use Lcobucci\JWT\Signer\InvalidKeyProvided; use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Validation\Constraint\SignedWith; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use Yii; use yii\base\InvalidConfigException; +#[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class SignerTest extends TestCase { /** @@ -22,7 +25,7 @@ class SignerTest extends TestCase public function getJwt(array $config = []): JwtTools { /** @var JwtTools $jwt */ - $jwt = Yii::createObject( + $jwt = \Yii::createObject( array_merge( ['class' => JwtTools::class], $config @@ -153,10 +156,7 @@ public static function providerForSigners(): iterable ]; } - /** - * @dataProvider providerForSigners - * @throws InvalidConfigException - */ + #[DataProvider('providerForSigners')] public function testParseTokenWithSignature( string|object $signer, string|array|object $signingKey, From 08ff27dec2c006c0c8d69cce0cfb89817a7e027c Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 7 Apr 2024 11:07:03 +0200 Subject: [PATCH 2/4] Update tests and GH workflow --- .github/workflows/tests.yml | 2 +- tests/standard/BearerTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b372ecd..687f04e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.1', '8.2', '8.3', '8.4'] + php: ['8.1', '8.2', '8.3'] steps: - name: Checkout diff --git a/tests/standard/BearerTest.php b/tests/standard/BearerTest.php index cdba47d..fb292a9 100644 --- a/tests/standard/BearerTest.php +++ b/tests/standard/BearerTest.php @@ -6,6 +6,7 @@ use bizley\jwt\Jwt; use bizley\jwt\JwtHttpBearerAuth; +use bizley\jwt\JwtTools; use bizley\tests\ConsecutiveCalls; use bizley\tests\stubs\TestAuthController; use bizley\tests\stubs\TestJwtHttpBearerAuth; @@ -28,6 +29,7 @@ #[CoversClass(JwtHttpBearerAuth::class)] #[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class BearerTest extends TestCase { protected function setUp(): void From e5818585f0945475aab2ec2163a601dacb9e8e93 Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 7 Apr 2024 11:09:22 +0200 Subject: [PATCH 3/4] Update tests and GH workflow --- tests/standard/ConstraintsConfigTest.php | 2 ++ tests/standard/JwtTest.php | 2 ++ tests/standard/SignerTest.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/tests/standard/ConstraintsConfigTest.php b/tests/standard/ConstraintsConfigTest.php index 6df0915..4054bf4 100644 --- a/tests/standard/ConstraintsConfigTest.php +++ b/tests/standard/ConstraintsConfigTest.php @@ -5,6 +5,7 @@ namespace bizley\tests\standard; use bizley\jwt\Jwt; +use bizley\jwt\JwtTools; use bizley\tests\stubs\YiiConstraint; use Lcobucci\JWT\Token; use Lcobucci\JWT\Validation\Constraint; @@ -16,6 +17,7 @@ use yii\base\InvalidConfigException; #[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class ConstraintsConfigTest extends TestCase { /** diff --git a/tests/standard/JwtTest.php b/tests/standard/JwtTest.php index 68d9df9..1912570 100644 --- a/tests/standard/JwtTest.php +++ b/tests/standard/JwtTest.php @@ -5,6 +5,7 @@ namespace bizley\tests\standard; use bizley\jwt\Jwt; +use bizley\jwt\JwtTools; use bizley\tests\stubs\JwtStub; use Lcobucci\JWT\Decoder; use Lcobucci\JWT\Encoder; @@ -18,6 +19,7 @@ use yii\base\InvalidConfigException; #[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class JwtTest extends TestCase { private function getJwt(): Jwt diff --git a/tests/standard/SignerTest.php b/tests/standard/SignerTest.php index b1d4b2a..db22a77 100644 --- a/tests/standard/SignerTest.php +++ b/tests/standard/SignerTest.php @@ -5,6 +5,7 @@ namespace bizley\tests\standard; use bizley\jwt\Jwt; +use bizley\jwt\JwtTools; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\InvalidKeyProvided; use Lcobucci\JWT\Signer\Key\InMemory; @@ -15,6 +16,7 @@ use yii\base\InvalidConfigException; #[CoversClass(Jwt::class)] +#[CoversClass(JwtTools::class)] class SignerTest extends TestCase { /** From ece994dc753215328eb8cb4fe6f54578ce7764df Mon Sep 17 00:00:00 2001 From: Bizley Date: Sun, 7 Apr 2024 11:10:48 +0200 Subject: [PATCH 4/4] Update tests and GH workflow --- infection.json.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection.json.dist b/infection.json.dist index d7e8cb4..1c4b65f 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -15,7 +15,7 @@ "MethodCallRemoval": { "ignore": [ "bizley\\jwt\\Jwt::init::124", - "bizley\\jwt\\JwtHttpBearerAuth::init::77" + "bizley\\jwt\\JwtHttpBearerAuth::init::72" ] } },