Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PHPUnit] Add AddProphecyTraitRector #3117

Merged
merged 1 commit into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/set/phpunit/phpunit91.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
services:
Rector\PHPUnit\Rector\Class_\AddProphecyTraitRector: null
33 changes: 29 additions & 4 deletions docs/AllRectorsOverview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# All 481 Rectors Overview
# All 482 Rectors Overview

- [Projects](#projects)
- [General](#general)
Expand Down Expand Up @@ -3612,9 +3612,10 @@ Remove temporary *Uuid relation properties
Change array to ArrayCollection in setParameters method of query builder

```diff

-use Doctrine\ORM\EntityRepository;
+use Doctrine\Common\Collections\ArrayCollection;use Doctrine\ORM\EntityRepository;use Doctrine\ORM\Query\Parameter;
-
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityRepository;
+use Doctrine\ORM\Query\Parameter;

class SomeRepository extends EntityRepository
{
Expand Down Expand Up @@ -5131,6 +5132,30 @@ Tests without assertion will have @doesNotPerformAssertion

<br>

### `AddProphecyTraitRector`

- class: [`Rector\PHPUnit\Rector\Class_\AddProphecyTraitRector`](/../master/rules/phpunit/src/Rector/Class_/AddProphecyTraitRector.php)
- [test fixtures](/../master/rules/phpunit/tests/Rector/Class_/AddProphecyTraitRector/Fixture)

Add Prophecy trait for method using $this->prophesize()

```diff
use PHPUnit\Framework\TestCase;
+use Prophecy\PhpUnit\ProphecyTrait;

final class ExampleTest extends TestCase
{
+ use ProphecyTrait;
+
public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}
```

<br>

### `AddSeeTestAnnotationRector`

- class: [`Rector\PHPUnit\Rector\Class_\AddSeeTestAnnotationRector`](/../master/rules/phpunit/src/Rector/Class_/AddSeeTestAnnotationRector.php)
Expand Down
7 changes: 4 additions & 3 deletions packages/post-rector/src/Application/PostFileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class PostFileProcessor
*/
public function __construct(array $postRectors)
{
$this->sortByPriorityAndSetCommanders($postRectors);
$this->postRectors = $this->sortByPriority($postRectors);
}

/**
Expand All @@ -41,8 +41,9 @@ public function traverse(array $nodes): array

/**
* @param PostRectorInterface[] $postRectors
* @return PostRectorInterface[]
*/
private function sortByPriorityAndSetCommanders(array $postRectors): void
private function sortByPriority(array $postRectors): array
{
$postRectorsByPriority = [];

Expand All @@ -56,6 +57,6 @@ private function sortByPriorityAndSetCommanders(array $postRectors): void

krsort($postRectorsByPriority);

$this->postRectors = $postRectorsByPriority;
return $postRectorsByPriority;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ protected function configure(): void
{
$this->setName(CommandNaming::classToName(self::class));
$this->setAliases(['c']);
$this->setDescription('[Dev] Create a new Rector, in a proper location, with new tests');
$this->setDescription('[DEV] Create a new Rector, in a proper location, with new tests');
}

protected function execute(InputInterface $input, OutputInterface $output): int
Expand Down
3 changes: 1 addition & 2 deletions packages/rector-generator/src/TemplateVariablesFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Name\FullyQualified;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\Core\Util\RectorStrings;
use Rector\RectorGenerator\ValueObject\Configuration;

final class TemplateVariablesFactory
Expand All @@ -32,7 +31,7 @@ public function createFromConfiguration(Configuration $configuration): array
{
$data = [
'_Package_' => $configuration->getPackage(),
'_package_' => RectorStrings::camelCaseToDashes($configuration->getPackage()),
'_package_' => $configuration->getPackageDirectory(),
'_Category_' => $configuration->getCategory(),
'_Description_' => $configuration->getDescription(),
'_Name_' => $configuration->getName(),
Expand Down
5 changes: 5 additions & 0 deletions packages/rector-generator/src/ValueObject/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ public function getPackage(): string

public function getPackageDirectory(): string
{
// special cases
if ($this->package === 'PHPUnit') {
return 'phpunit';
}

return RectorStrings::camelCaseToDashes($this->package);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,9 @@ private function removeAssignsFromConstructor(ClassMethod $classMethod): void

private function removeUnusedProperties(Class_ $class): void
{
foreach (array_keys($this->propertyFetchToParamsToRemoveFromConstructor) as $propertyFetchName) {
$propertyFetchNames = array_keys($this->propertyFetchToParamsToRemoveFromConstructor);

foreach ($propertyFetchNames as $propertyFetchName) {
/** @var string $propertyFetchName */
$this->classManipulator->removeProperty($class, $propertyFetchName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ public function getSomething()
PHP
,
<<<'PHP'

use Doctrine\Common\Collections\ArrayCollection;use Doctrine\ORM\EntityRepository;use Doctrine\ORM\Query\Parameter;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Parameter;

class SomeRepository extends EntityRepository
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function getNodeTypes(): array
*/
public function refactor(Node $node): ?Node
{
if (! $this->classManipulator->hasClassTrait($node, 'Gedmo\Timestampable\Traits\TimestampableEntity')) {
if (! $this->classManipulator->hasTrait($node, 'Gedmo\Timestampable\Traits\TimestampableEntity')) {
return null;
}

Expand Down
122 changes: 122 additions & 0 deletions rules/phpunit/src/Rector/Class_/AddProphecyTraitRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

declare(strict_types=1);

namespace Rector\PHPUnit\Rector\Class_;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\PhpParser\Node\Manipulator\ClassInsertManipulator;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\Rector\AbstractPHPUnitRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;

/**
* @see https://github.com/sebastianbergmann/phpunit/issues/4142
* @see https://github.com/sebastianbergmann/phpunit/issues/4141
* @see https://github.com/sebastianbergmann/phpunit/issues/4149
*
* @see \Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector\AddProphecyTraitRectorTest
*/
final class AddProphecyTraitRector extends AbstractPHPUnitRector
{
/**
* @var string
*/
private const PROPHECY_TRAIT = 'Prophecy\PhpUnit\ProphecyTrait';

/**
* @var ClassInsertManipulator
*/
private $classInsertManipulator;

/**
* @var ClassManipulator
*/
private $classManipulator;

public function __construct(ClassManipulator $classManipulator, ClassInsertManipulator $classInsertManipulator)
{
$this->classInsertManipulator = $classInsertManipulator;
$this->classManipulator = $classManipulator;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add Prophecy trait for method using $this->prophesize()', [
new CodeSample(
<<<'PHP'
use PHPUnit\Framework\TestCase;

final class ExampleTest extends TestCase
{
public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}
PHP
,
<<<'PHP'
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;

final class ExampleTest extends TestCase
{
use ProphecyTrait;

public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}
PHP

),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if ($this->shouldSkipClass($node)) {
return null;
}

$this->classInsertManipulator->addAsFirstTrait($node, self::PROPHECY_TRAIT);

return $node;
}

private function hasProphesizeMethodCall(Class_ $node): bool
{
return (bool) $this->betterNodeFinder->findFirst($node, function (Node $node) {
return $this->isMethodCall($node, 'this', 'prophesize');
});
}

private function shouldSkipClass(Class_ $class): bool
{
if (! $this->isInTestClass($class)) {
return true;
}

$hasProphesizeMethodCall = $this->hasProphesizeMethodCall($class);
if (! $hasProphesizeMethodCall) {
return true;
}

return $this->classManipulator->hasTrait($class, self::PROPHECY_TRAIT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector;

use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\PHPUnit\Rector\Class_\AddProphecyTraitRector;

final class AddProphecyTraitRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}

public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

protected function getRectorClass(): string
{
return AddProphecyTraitRector::class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector\Fixture;

use PHPUnit\Framework\TestCase;

final class ExampleTest extends TestCase
{
public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector\Fixture;

use PHPUnit\Framework\TestCase;

final class ExampleTest extends TestCase
{
use \Prophecy\PhpUnit\ProphecyTrait;
public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector\Fixture;

use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;

final class SkipIfAlreadyAdded extends TestCase
{
use ProphecyTrait;

public function testOne(): void
{
$prophecy = $this->prophesize(\AnInterface::class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\AddProphecyTraitRector\Fixture;

use PHPUnit\Framework\TestCase;
use stdClass;

final class SkipNonProphesizeTest extends TestCase
{
public function testOne(): void
{
$that = new stdClass();
$prophecy = $that->prophesize(\AnInterface::class);
}
}
2 changes: 1 addition & 1 deletion src/Console/Command/ScreenFileCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public function __construct(
protected function configure(): void
{
$this->setName(CommandNaming::classToName(self::class));
$this->setDescription('[Dev] Load file and print nodes meta data - super helpful to learn to build rules');
$this->setDescription('[DEV] Load file and print nodes meta data - super helpful to learn to build rules');

$this->addArgument(self::FILE_ARGUMENT, InputArgument::REQUIRED, 'Path to file to be screened');
}
Expand Down
2 changes: 1 addition & 1 deletion src/PhpParser/Node/Manipulator/ClassInsertManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function addAsFirstTrait(Class_ $class, string $traitName): void
{
$trait = new TraitUse([new FullyQualified($traitName)]);

$this->addStatementToClassBeforeTypes($class, $trait, TraitUse::class, Property::class);
$this->addStatementToClassBeforeTypes($class, $trait, TraitUse::class, Property::class, ClassMethod::class);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/PhpParser/Node/Manipulator/ClassManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public function hasPropertyName(Class_ $node, string $name): bool
return false;
}

public function hasClassTrait(Class_ $class, string $desiredTrait): bool
public function hasTrait(Class_ $class, string $desiredTrait): bool
{
foreach ($class->getTraitUses() as $traitUse) {
if (! $this->nodeNameResolver->haveName($traitUse->traits, $desiredTrait)) {
Expand Down
Loading