123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714 |
- <?php
- declare(strict_types=1);
- /*
- * This file is part of PHP CS Fixer.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- * Dariusz Rumiński <dariusz.ruminski@gmail.com>
- *
- * This source file is subject to the MIT license that is bundled
- * with this source code in the file LICENSE.
- */
- namespace PhpCsFixer\Tests\Fixer\PhpUnit;
- use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
- /**
- * @internal
- *
- * @covers \PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer
- *
- * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer>
- *
- * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\PhpUnit\PhpUnitAttributesFixer
- */
- final class PhpUnitAttributesFixerTest extends AbstractFixerTestCase
- {
- /**
- * @requires PHP 8.0
- *
- * @dataProvider provideFixCases
- *
- * @param _AutogeneratedInputConfiguration $configuration
- */
- public function testFix(string $expected, ?string $input = null, array $configuration = []): void
- {
- $this->fixer->configure($configuration);
- $this->doTest($expected, $input);
- }
- /**
- * @return iterable<array{0: string, 1?: string}>
- */
- public static function provideFixCases(): iterable
- {
- yield 'do not fix with wrong values' => [<<<'PHP'
- <?php
- /**
- * @requires
- * @uses
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @backupGlobals
- * @backupStaticAttributes
- * @covers
- * @dataProvider
- * @depends
- * @group
- * @preserveGlobalState
- * @testDox
- * @testWith
- * @ticket
- */
- public function testFoo() { self::assertTrue(true); }
- }
- PHP];
- yield 'do not fix with wrong casing' => [<<<'PHP'
- <?php
- /**
- * @COVERS \Foo
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @dataPROVIDER provideFooCases
- * @requires php 8.3
- */
- public function testFoo() { self::assertTrue(true); }
- }
- PHP];
- yield 'do not fix when not supported by attributes' => [<<<'PHP'
- <?php
- /**
- * @covers FooClass::FooMethod
- * @uses ClassName::methodName
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- public function testFoo() { self::assertTrue(true); }
- }
- PHP];
- yield 'do not fix when there is already attribute of related class' => [<<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^8.2
- */
- #[\FirstAttributeToMakeSureMultipleAttributesWorks]
- #[\PHPUnit\Framework\Attributes\RequiresPhp('^7.1')]
- #[\ThirdAttributeToMakeSureMultipleAttributesWorks]
- public function testFoo() {}
- }
- PHP];
- yield 'do not duplicate attribute when used without leading slash' => [<<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^6.1
- */
- #[PHPUnit\Framework\Attributes\RequiresPhp('^6.1')]
- public function testFoo() {}
- }
- PHP];
- yield 'do not duplicate attribute when used with import' => [<<<'PHP'
- <?php
- use PHPUnit\Framework\Attributes\RequiresPhp;
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^6.2
- */
- #[RequiresPhp('^6.2')]
- public function testFoo() {}
- }
- PHP];
- yield 'do not duplicate attribute when used with partial import' => [<<<'PHP'
- <?php
- use PHPUnit\Framework\Attributes;
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^6.2
- */
- #[Attributes\RequiresPhp('^6.2')]
- public function testFoo() {}
- }
- PHP];
- yield 'do not duplicate attribute when used with alias' => [<<<'PHP'
- <?php
- use PHPUnit\Framework\Attributes\RequiresPhp as PHPUnitRequiresPhp;
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^6.0
- */
- #[PHPUnitRequiresPhp('^6.0')]
- public function testFoo() {}
- }
- PHP];
- yield 'do not duplicate attribute when used with partial alias' => [<<<'PHP'
- <?php
- use PHPUnit\Framework\Attributes as PHPUnitAttributes;
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^6.0
- */
- #[PHPUnitAttributes\RequiresPhp('^6.0')]
- public function testFoo() {}
- }
- PHP];
- yield 'fix multiple annotations' => [
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @copyright ACME Corporation
- */
- #[\PHPUnit\Framework\Attributes\DataProvider('provideFooCases')]
- #[\PHPUnit\Framework\Attributes\RequiresPhp('^8.2')]
- #[\PHPUnit\Framework\Attributes\RequiresOperatingSystem('Linux|Darwin')]
- public function testFoo($x) { self::assertTrue($x); }
- public static function provideFooCases() { yield [true]; yield [false]; }
- }
- PHP,
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @copyright ACME Corporation
- * @dataProvider provideFooCases
- * @requires PHP ^8.2
- * @requires OS Linux|Darwin
- */
- public function testFoo($x) { self::assertTrue($x); }
- public static function provideFooCases() { yield [true]; yield [false]; }
- }
- PHP,
- ];
- yield 'fix with multiple spaces' => [
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- */
- #[\PHPUnit\Framework\Attributes\RequiresPhp('^7.4|^8.1')]
- public function testFoo() { self::assertTrue(true); }
- }
- PHP,
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP ^7.4|^8.1
- */
- public function testFoo() { self::assertTrue(true); }
- }
- PHP,
- ];
- yield 'fix with > in operator' => [
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- */
- #[\PHPUnit\Framework\Attributes\RequiresPhp('>= 8.1')]
- public function testFoo() { self::assertTrue(true); }
- }
- PHP,
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @requires PHP >= 8.1
- */
- public function testFoo() { self::assertTrue(true); }
- }
- PHP,
- ];
- yield 'fix with trailing spaces' => self::createCase(
- ['class'],
- '#[CoversClass(Foo::class)]',
- '@covers Foo ',
- );
- $byte224 = \chr(224);
- yield 'fix with non-alphanumeric characters' => [
- <<<PHP
- <?php
- class FooTest extends \\PHPUnit\\Framework\\TestCase {
- /**
- */
- #[\\PHPUnit\\Framework\\Attributes\\TestDox('a\\'b"c')]
- public function testFoo() { self::assertTrue(true); }
- /**
- */
- #[\\PHPUnit\\Framework\\Attributes\\TestDox('龍')]
- public function testBar() { self::assertTrue(true); }
- /**
- */
- #[\\PHPUnit\\Framework\\Attributes\\TestDox('byte224: {$byte224}')]
- public function testBaz() { self::assertTrue(true); }
- }
- PHP,
- <<<PHP
- <?php
- class FooTest extends \\PHPUnit\\Framework\\TestCase {
- /**
- * @testDox a'b"c
- */
- public function testFoo() { self::assertTrue(true); }
- /**
- * @testDox 龍
- */
- public function testBar() { self::assertTrue(true); }
- /**
- * @testDox byte224: {$byte224}
- */
- public function testBaz() { self::assertTrue(true); }
- }
- PHP,
- ];
- yield 'handle After' => self::createCase(
- ['method'],
- '#[After]',
- '@after',
- );
- yield 'handle AfterClass' => self::createCase(
- ['method'],
- '#[AfterClass]',
- '@afterClass',
- );
- yield 'handle BackupGlobals enabled' => self::createCase(
- ['class', 'method'],
- '#[BackupGlobals(true)]',
- '@backupGlobals enabled',
- );
- yield 'handle BackupGlobals disabled' => self::createCase(
- ['class', 'method'],
- '#[BackupGlobals(false)]',
- '@backupGlobals disabled',
- );
- yield 'handle BackupGlobals no' => self::createCase(
- ['class', 'method'],
- '#[BackupGlobals(false)]',
- '@backupGlobals no',
- );
- yield 'handle BackupStaticProperties enabled' => self::createCase(
- ['class', 'method'],
- '#[BackupStaticProperties(true)]',
- '@backupStaticAttributes enabled',
- );
- yield 'handle BackupStaticProperties disabled' => self::createCase(
- ['class', 'method'],
- '#[BackupStaticProperties(false)]',
- '@backupStaticAttributes disabled',
- );
- yield 'handle Before' => self::createCase(
- ['method'],
- '#[Before]',
- '@before',
- );
- yield 'handle BeforeClass' => self::createCase(
- ['method'],
- '#[BeforeClass]',
- '@beforeClass',
- );
- yield 'handle CoversClass' => self::createCase(
- ['class'],
- '#[CoversClass(\VendorName\ClassName::class)]',
- '@covers \VendorName\ClassName',
- );
- yield 'handle CoversFunction' => self::createCase(
- ['class'],
- "#[CoversFunction('functionName')]",
- '@covers ::functionName',
- );
- yield 'handle CoversNothing' => self::createCase(
- ['class', 'method'],
- '#[CoversNothing]',
- '@coversNothing',
- );
- yield 'handle DataProvider' => self::createCase(
- ['method'],
- "#[DataProvider('provideFooCases')]",
- '@dataProvider provideFooCases',
- );
- yield 'handle DataProviderExternal' => self::createCase(
- ['method'],
- "#[DataProviderExternal(BarTest::class, 'provideFooCases')]",
- '@dataProvider BarTest::provideFooCases',
- );
- yield 'handle Depends' => self::createCase(
- ['method'],
- "#[Depends('methodName')]",
- '@depends methodName',
- );
- yield 'handle DependsExternal' => self::createCase(
- ['method'],
- "#[DependsExternal(ClassName::class, 'methodName')]",
- '@depends ClassName::methodName',
- );
- yield 'handle DependsExternalUsingDeepClone' => self::createCase(
- ['method'],
- "#[DependsExternalUsingDeepClone(ClassName::class, 'methodName')]",
- '@depends clone ClassName::methodName',
- );
- yield 'handle DependsExternalUsingShallowClone' => self::createCase(
- ['method'],
- "#[DependsExternalUsingShallowClone(ClassName::class, 'methodName')]",
- '@depends shallowClone ClassName::methodName',
- );
- yield 'handle DependsOnClass' => self::createCase(
- ['method'],
- '#[DependsOnClass(ClassName::class)]',
- '@depends ClassName::class',
- );
- yield 'handle DependsOnClassUsingDeepClone' => self::createCase(
- ['method'],
- '#[DependsOnClassUsingDeepClone(ClassName::class)]',
- '@depends clone ClassName::class',
- );
- yield 'handle DependsOnClassUsingShallowClone' => self::createCase(
- ['method'],
- '#[DependsOnClassUsingShallowClone(ClassName::class)]',
- '@depends shallowClone ClassName::class',
- );
- yield 'handle DependsUsingDeepClone' => self::createCase(
- ['method'],
- "#[DependsUsingDeepClone('methodName')]",
- '@depends clone methodName',
- );
- yield 'handle DependsUsingShallowClone' => self::createCase(
- ['method'],
- "#[DependsUsingShallowClone('methodName')]",
- '@depends shallowClone methodName',
- );
- yield 'handle DoesNotPerformAssertions' => self::createCase(
- ['class', 'method'],
- '#[DoesNotPerformAssertions]',
- '@doesNotPerformAssertions',
- );
- yield 'handle Group' => self::createCase(
- ['class', 'method'],
- "#[Group('groupName')]",
- '@group groupName',
- );
- yield 'handle Large' => self::createCase(
- ['class'],
- '#[Large]',
- '@large',
- );
- yield 'handle Medium' => self::createCase(
- ['class'],
- '#[Medium]',
- '@medium',
- );
- yield 'handle PostCondition' => self::createCase(
- ['method'],
- '#[PostCondition]',
- '@postCondition',
- );
- yield 'handle PreCondition' => self::createCase(
- ['method'],
- '#[PreCondition]',
- '@preCondition',
- );
- yield 'handle PreserveGlobalState enabled' => self::createCase(
- ['class', 'method'],
- '#[PreserveGlobalState(true)]',
- '@preserveGlobalState enabled',
- );
- yield 'handle PreserveGlobalState disabled' => self::createCase(
- ['class', 'method'],
- '#[PreserveGlobalState(false)]',
- '@preserveGlobalState disabled',
- );
- yield 'handle RequiresFunction' => self::createCase(
- ['class', 'method'],
- "#[RequiresFunction('imap_open')]",
- '@requires function imap_open',
- );
- yield 'handle RequiresMethod' => self::createCase(
- ['class', 'method'],
- "#[RequiresMethod(ReflectionMethod::class, 'setAccessible')]",
- '@requires function ReflectionMethod::setAccessible',
- );
- yield 'handle RequiresOperatingSystem' => self::createCase(
- ['class', 'method'],
- "#[RequiresOperatingSystem('Linux')]",
- '@requires OS Linux',
- );
- yield 'handle RequiresOperatingSystemFamily' => self::createCase(
- ['class', 'method'],
- "#[RequiresOperatingSystemFamily('Windows')]",
- '@requires OSFAMILY Windows',
- );
- yield 'handle RequiresPhp' => self::createCase(
- ['class', 'method'],
- "#[RequiresPhp('8.1.20')]",
- '@requires PHP 8.1.20',
- );
- yield 'handle RequiresPhpExtension' => self::createCase(
- ['class', 'method'],
- "#[RequiresPhpExtension('mysqli', '>= 8.3.0')]",
- '@requires extension mysqli >= 8.3.0',
- );
- yield 'handle RequiresPhpunit' => self::createCase(
- ['class', 'method'],
- "#[RequiresPhpunit('^10.1.0')]",
- '@requires PHPUnit ^10.1.0',
- );
- yield 'handle RequiresSetting' => self::createCase(
- ['class', 'method'],
- "#[RequiresSetting('date.timezone', 'Europe/London')]",
- '@requires setting date.timezone Europe/London',
- );
- yield 'handle RunInSeparateProcess' => self::createCase(
- ['method'],
- '#[RunInSeparateProcess]',
- '@runInSeparateProcess',
- );
- yield 'handle RunTestsInSeparateProcesses' => self::createCase(
- ['class'],
- '#[RunTestsInSeparateProcesses]',
- '@runTestsInSeparateProcesses',
- );
- yield 'handle Small' => self::createCase(
- ['class'],
- '#[Small]',
- '@small',
- );
- yield 'handle Test' => self::createCase(
- ['method'],
- '#[Test]',
- '@test',
- );
- yield 'handle TestDox' => self::createCase(
- ['class', 'method'],
- "#[TestDox('Hello world!')]",
- '@testDox Hello world!',
- );
- yield 'handle Ticket' => self::createCase(
- ['class', 'method'],
- "#[Ticket('ABC-123')]",
- '@ticket ABC-123',
- );
- yield 'handle UsesClass' => self::createCase(
- ['class'],
- '#[UsesClass(ClassName::class)]',
- '@uses ClassName',
- );
- yield 'handle UsesFunction' => self::createCase(
- ['class'],
- "#[UsesFunction('functionName')]",
- '@uses ::functionName',
- );
- yield 'handle TestWith' => [
- <<<'PHP'
- <?php
- /**
- * @testWith [true, false]
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- */
- #[\PHPUnit\Framework\Attributes\TestWithJson('[1, 2]')]
- public function testFoo($x) {}
- /**
- */
- #[\PHPUnit\Framework\Attributes\TestWithJson('[3, 4, 5]')]
- #[\PHPUnit\Framework\Attributes\TestWithJson('[6, 7, 8]')]
- #[\PHPUnit\Framework\Attributes\TestWithJson('["a", "b"]')]
- #[\PHPUnit\Framework\Attributes\TestWithJson('["c\'d"]')]
- public function testBar($x) {}
- }
- PHP,
- <<<'PHP'
- <?php
- /**
- * @testWith [true, false]
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @testWith [1, 2]
- */
- public function testFoo($x) {}
- /**
- * @testWith [3, 4, 5]
- * [6, 7, 8]
- * ["a", "b"]
- * ["c'd"]
- */
- public function testBar($x) {}
- }
- PHP,
- ];
- yield 'handle multiple annotations of the same name' => [
- <<<'PHP'
- <?php
- /**
- */
- #[\PHPUnit\Framework\Attributes\Group('foo')]
- #[\PHPUnit\Framework\Attributes\Group('bar')]
- class TheTest extends \PHPUnit\Framework\TestCase {}
- PHP,
- <<<'PHP'
- <?php
- /**
- * @group foo
- * @group bar
- */
- class TheTest extends \PHPUnit\Framework\TestCase {}
- PHP,
- ];
- yield 'keep annotations' => [
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @copyright ACME Corporation
- * @dataProvider provideFooCases
- * @requires PHP ^8.2
- * @requires OS Linux|Darwin
- */
- #[\PHPUnit\Framework\Attributes\DataProvider('provideFooCases')]
- #[\PHPUnit\Framework\Attributes\RequiresPhp('^8.2')]
- #[\PHPUnit\Framework\Attributes\RequiresOperatingSystem('Linux|Darwin')]
- public function testFoo($x) { self::assertTrue($x); }
- public static function provideFooCases() { yield [true]; yield [false]; }
- }
- PHP,
- <<<'PHP'
- <?php
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * @copyright ACME Corporation
- * @dataProvider provideFooCases
- * @requires PHP ^8.2
- * @requires OS Linux|Darwin
- */
- public function testFoo($x) { self::assertTrue($x); }
- public static function provideFooCases() { yield [true]; yield [false]; }
- }
- PHP,
- [
- 'keep_annotations' => true,
- ],
- ];
- }
- /**
- * @param non-empty-list<'class'|'method'> $scopes
- *
- * @return array{string, string}
- */
- private static function createCase(array $scopes, string $expectedAttribute, string $inputAnnotation): array
- {
- $expectedAttribute = str_replace('#[', '#[\PHPUnit\Framework\Attributes\\', $expectedAttribute);
- return [
- \sprintf(
- <<<'PHP'
- <?php
- %s
- class FooTest extends \PHPUnit\Framework\TestCase {
- %s
- public function testFoo($x) {}
- %s
- public function testBar($x) {}
- }
- PHP,
- \in_array('class', $scopes, true)
- ? \sprintf("/**\n */\n%s", $expectedAttribute)
- : \sprintf("/**\n * %s\n */", $inputAnnotation),
- \in_array('method', $scopes, true)
- ? \sprintf("/**\n */\n %s", $expectedAttribute)
- : \sprintf("/**\n * %s\n */", $inputAnnotation),
- \in_array('method', $scopes, true)
- ? \sprintf("\n %s", $expectedAttribute)
- : \sprintf('/** %s */', $inputAnnotation),
- ),
- \sprintf(
- <<<'PHP'
- <?php
- /**
- * %s
- */
- class FooTest extends \PHPUnit\Framework\TestCase {
- /**
- * %s
- */
- public function testFoo($x) {}
- /** %s */
- public function testBar($x) {}
- }
- PHP,
- $inputAnnotation,
- $inputAnnotation,
- $inputAnnotation,
- ),
- ];
- }
- }
|