Skip to content

Commit 344eabd

Browse files
authored
Add test fixture for #51 + fix adding setUp() when needed (#52)
* add test fixture for #51 * misc * add setUp method adding
1 parent 2641a25 commit 344eabd

File tree

13 files changed

+189
-66
lines changed

13 files changed

+189
-66
lines changed

composer.json

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@
1616
"symfony/console": "^7.1"
1717
},
1818
"require-dev": {
19-
"rector/rector": "dev-main",
20-
"nikic/php-parser": "^5.3.1",
21-
"phpunit/phpunit": "^10.5",
22-
"phpstan/phpstan": "^2.0",
23-
"symplify/easy-coding-standard": "^12.1",
19+
"rector/rector": "^2.0",
20+
"nikic/php-parser": "^5.4",
21+
"phpunit/phpunit": "^11.5",
22+
"phpstan/phpstan": "^2.1",
23+
"phpecs/phpecs": "^2.0",
2424
"phpstan/extension-installer": "^1.3",
25-
"symplify/rule-doc-generator": "^12.1",
26-
"tomasvotruba/class-leak": "^0.2.5",
25+
"tomasvotruba/class-leak": "^2.0",
2726
"tracy/tracy": "^2.10"
2827
},
2928
"autoload": {
@@ -47,7 +46,7 @@
4746
"phpstan": "vendor/bin/phpstan analyse --ansi",
4847
"check-cs": "vendor/bin/ecs check --ansi",
4948
"fix-cs": "vendor/bin/ecs check --fix --ansi",
50-
"docs": "vendor/bin/rule-doc-generator generate src rules --output-file docs/rector_rules_overview.md --ansi"
49+
"phpunit": "vendor/bin/phpunit --colors=always"
5150
},
5251
"minimum-stability": "dev",
5352
"prefer-stable": true,

rector.php

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,18 @@
44

55
use Rector\Config\RectorConfig;
66
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
7-
use Rector\Set\ValueObject\SetList;
8-
9-
return static function (RectorConfig $rectorConfig): void {
10-
$rectorConfig->importNames();
11-
12-
$rectorConfig->paths([__DIR__ . '/config', __DIR__ . '/src', __DIR__ . '/rules', __DIR__ . '/rules-tests']);
13-
14-
$rectorConfig->skip([
15-
// for tests
16-
'*/Source/*',
177

8+
return RectorConfig::configure()
9+
->withImportNames()
10+
->withPaths([__DIR__ . '/config', __DIR__ . '/src', __DIR__ . '/rules', __DIR__ . '/rules-tests'])
11+
->withSkip([
1812
StringClassNameToClassConstantRector::class => [__DIR__ . '/src/DocFactory.php'],
19-
]);
20-
21-
$rectorConfig->sets([
22-
SetList::INSTANCEOF,
23-
SetList::NAMING,
24-
SetList::TYPE_DECLARATION,
25-
SetList::DEAD_CODE,
26-
SetList::CODE_QUALITY,
27-
SetList::CODING_STYLE,
28-
]);
29-
};
13+
])
14+
->withPreparedSets(
15+
instanceOf: true,
16+
naming: true,
17+
typeDeclarations: true,
18+
deadCode: true,
19+
codeQuality: true,
20+
codingStyle: true,
21+
);

rules-tests/Rector/Class_/PromisesToAssertsRector/Fixture/phpspec_promises.php.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ use PhpSpec\ObjectBehavior;
2222

2323
final class PhpSpecPromises extends ObjectBehavior
2424
{
25+
private \Rector\PhpSpecToPHPUnit\Tests\Rector\Class_\PromisesToAssertsRector\Fixture\PhpSpecPromises $phpSpecPromises;
26+
protected function setUp(): void
27+
{
28+
$this->phpSpecPromises = new \Rector\PhpSpecToPHPUnit\Tests\Rector\Class_\PromisesToAssertsRector\Fixture\PhpSpecPromises();
29+
}
2530
public function it_returns_id()
2631
{
2732
$this->assertSame(5, $this->phpSpecPromises->id());

rules-tests/Rector/Class_/PromisesToAssertsRector/Fixture/should_be_instance_of.php.inc

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace spec\Rector\PhpSpecToPHPUnit;
44

55
use PhpSpec\ObjectBehavior;
66

7-
class TestClassMethod extends ObjectBehavior
7+
class ShouldBeInstanceofMethod extends ObjectBehavior
88
{
99
public function let_1()
1010
{
@@ -35,26 +35,31 @@ namespace spec\Rector\PhpSpecToPHPUnit;
3535

3636
use PhpSpec\ObjectBehavior;
3737

38-
class TestClassMethod extends ObjectBehavior
38+
class ShouldBeInstanceofMethod extends ObjectBehavior
3939
{
40+
private \Rector\PhpSpecToPHPUnit\ShouldBeInstanceofMethod $shouldBeInstanceofMethod;
41+
protected function setUp(): void
42+
{
43+
$this->shouldBeInstanceofMethod = new \Rector\PhpSpecToPHPUnit\ShouldBeInstanceofMethod();
44+
}
4045
public function let_1()
4146
{
42-
$this->assertInstanceOf(\stdClass::class, $this->testClassMethod);
47+
$this->assertInstanceOf(\stdClass::class, $this->shouldBeInstanceofMethod);
4348
}
4449

4550
public function let_2()
4651
{
47-
$this->assertInstanceOf(\stdClass::class, $this->testClassMethod);
52+
$this->assertInstanceOf(\stdClass::class, $this->shouldBeInstanceofMethod);
4853
}
4954

5055
public function let_3()
5156
{
52-
$this->assertInstanceOf(\stdClass::class, $this->testClassMethod);
57+
$this->assertInstanceOf(\stdClass::class, $this->shouldBeInstanceofMethod);
5358
}
5459

5560
public function let_4()
5661
{
57-
$this->assertInstanceOf(\stdClass::class, $this->testClassMethod);
62+
$this->assertInstanceOf(\stdClass::class, $this->shouldBeInstanceofMethod);
5863
}
5964
}
6065

rules/Rector/Class_/ImplicitLetInitializationRector.php

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,18 @@
44

55
namespace Rector\PhpSpecToPHPUnit\Rector\Class_;
66

7-
use PhpParser\Modifiers;
87
use PhpParser\Node;
9-
use PhpParser\Node\Expr\Assign;
10-
use PhpParser\Node\Expr\New_;
11-
use PhpParser\Node\Expr\PropertyFetch;
12-
use PhpParser\Node\Expr\Variable;
13-
use PhpParser\Node\Identifier;
14-
use PhpParser\Node\Name\FullyQualified;
158
use PhpParser\Node\Param;
169
use PhpParser\Node\Stmt\Class_;
1710
use PhpParser\Node\Stmt\ClassMethod;
18-
use PhpParser\Node\Stmt\Expression;
1911
use PhpParser\Node\Stmt\Property;
2012
use Rector\NodeTypeResolver\Node\AttributeKey;
2113
use Rector\PhpSpecToPHPUnit\Enum\PhpSpecMethodName;
2214
use Rector\PhpSpecToPHPUnit\Naming\PhpSpecRenaming;
15+
use Rector\PhpSpecToPHPUnit\NodeFactory\SetUpInstanceFactory;
2316
use Rector\PhpSpecToPHPUnit\NodeFinder\MethodCallFinder;
2417
use Rector\PhpSpecToPHPUnit\ValueObject\TestedObject;
2518
use Rector\Rector\AbstractRector;
26-
use Rector\ValueObject\MethodName;
2719
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2820
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2921

@@ -34,6 +26,7 @@ final class ImplicitLetInitializationRector extends AbstractRector
3426
{
3527
public function __construct(
3628
private readonly PhpSpecRenaming $phpSpecRenaming,
29+
private readonly SetUpInstanceFactory $setUpInstanceFactory,
3730
) {
3831
}
3932

@@ -108,26 +101,12 @@ public function refactor(Node $node): ?Node
108101

109102
$testedObjectProperty = $this->createTestedObjectProperty($testedObject);
110103

111-
$setUpClassMethod = $this->createSetUpClassMethod($testedObject);
104+
$setUpClassMethod = $this->setUpInstanceFactory->createSetUpClassMethod($testedObject);
112105
$node->stmts = [$testedObjectProperty, $setUpClassMethod, ...(array) $node->stmts];
113106

114107
return $node;
115108
}
116109

117-
private function createSetUpClassMethod(TestedObject $testedObject): ClassMethod
118-
{
119-
$classMethod = new ClassMethod(MethodName::SET_UP);
120-
$classMethod->returnType = new Identifier('void');
121-
$classMethod->flags |= Modifiers::PROTECTED;
122-
123-
$propertyFetch = new PropertyFetch(new Variable('this'), $testedObject->getPropertyName());
124-
$new = new New_(new FullyQualified($testedObject->getClassName()));
125-
126-
$classMethod->stmts = [new Expression(new Assign($propertyFetch, $new))];
127-
128-
return $classMethod;
129-
}
130-
131110
private function createTestedObjectProperty(TestedObject $testedObject): Property
132111
{
133112
return $this->nodeFactory->createPrivatePropertyFromNameAndType(

rules/Rector/Class_/PromisesToAssertsRector.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Rector\PhpSpecToPHPUnit\Rector\Class_;
66

7+
use PhpParser\Node\Stmt\ClassMethod;
8+
use PhpParser\Node\Identifier;
79
use PhpParser\Node;
810
use PhpParser\Node\Expr;
911
use PhpParser\Node\Expr\Assign;
@@ -12,15 +14,19 @@
1214
use PhpParser\Node\Expr\PropertyFetch;
1315
use PhpParser\Node\Expr\Variable;
1416
use PhpParser\Node\Stmt\Class_;
15-
use PHPStan\Node\ClassMethod;
17+
use PhpParser\Node\Stmt\Property;
18+
use PhpParser\NodeFinder;
1619
use Rector\PhpSpecToPHPUnit\Enum\PhpSpecMethodName;
1720
use Rector\PhpSpecToPHPUnit\Enum\PHPUnitMethodName;
1821
use Rector\PhpSpecToPHPUnit\Enum\ProphecyPromisesToPHPUnitAssertMap;
1922
use Rector\PhpSpecToPHPUnit\Naming\PhpSpecRenaming;
2023
use Rector\PhpSpecToPHPUnit\Naming\SystemMethodDetector;
2124
use Rector\PhpSpecToPHPUnit\NodeFactory\AssertMethodCallFactory;
2225
use Rector\PhpSpecToPHPUnit\NodeFactory\BeConstructedWithAssignFactory;
26+
use Rector\PhpSpecToPHPUnit\NodeFactory\SetUpInstanceFactory;
27+
use Rector\PhpSpecToPHPUnit\ValueObject\TestedObject;
2328
use Rector\Rector\AbstractRector;
29+
use Rector\ValueObject\MethodName;
2430
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2531
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2632

@@ -29,11 +35,15 @@
2935
*/
3036
final class PromisesToAssertsRector extends AbstractRector
3137
{
38+
private NodeFinder $nodeFinder;
39+
3240
public function __construct(
3341
private readonly PhpSpecRenaming $phpSpecRenaming,
3442
private readonly AssertMethodCallFactory $assertMethodCallFactory,
3543
private readonly BeConstructedWithAssignFactory $beConstructedWithAssignFactory,
44+
private readonly SetUpInstanceFactory $setUpInstanceFactory,
3645
) {
46+
$this->nodeFinder = new NodeFinder();
3747
}
3848

3949
/**
@@ -58,6 +68,8 @@ public function refactor(Node $node): Node|null
5868

5969
$localMethodNames = $this->getLocalMethodNames($node);
6070

71+
$needsSetUp = true;
72+
6173
foreach ($node->getMethods() as $classMethod) {
6274
if (! $classMethod->isPublic()) {
6375
continue;
@@ -68,9 +80,15 @@ public function refactor(Node $node): Node|null
6880
$classMethod,
6981
[PhpSpecMethodName::LET, PhpSpecMethodName::LET_GO, PhpSpecMethodName::GET_MATCHERS]
7082
)) {
83+
$needsSetUp = false;
7184
continue;
7285
}
7386

87+
// if all methods have this call, no need to add setUp()
88+
if ($this->hasBeConstructedMethodCall($classMethod)) {
89+
$needsSetUp = false;
90+
}
91+
7492
$this->traverseNodesWithCallable($classMethod, function (Node $node) use (
7593
$class,
7694
$testedObjectPropertyFetch,
@@ -179,6 +197,16 @@ public function refactor(Node $node): Node|null
179197
return null;
180198
}
181199

200+
// add setUp() method with the property
201+
if ($needsSetUp && ! $class->getMethod(MethodName::SET_UP)) {
202+
$testedObject = $this->phpSpecRenaming->resolveTestedObject($node);
203+
$setUpClassMethod = $this->setUpInstanceFactory->createSetUpClassMethod($testedObject);
204+
205+
$testedObjectProperty = $this->createTestedObjectProperty($testedObject);
206+
207+
$class->stmts = array_merge([$testedObjectProperty, $setUpClassMethod], $class->stmts);
208+
}
209+
182210
return $node;
183211
}
184212

@@ -248,4 +276,29 @@ private function getLocalMethodNames(Class_ $class): array
248276
/** @var string[] $localMethodNames */
249277
return $localMethodNames;
250278
}
279+
280+
private function createTestedObjectProperty(TestedObject $testedObject): Property
281+
{
282+
return $this->nodeFactory->createPrivatePropertyFromNameAndType(
283+
$testedObject->getPropertyName(),
284+
$testedObject->getTestedObjectType()
285+
);
286+
}
287+
288+
private function hasBeConstructedMethodCall(ClassMethod $classMethod): bool
289+
{
290+
$methodCall = $this->nodeFinder->findFirst((array) $classMethod->stmts, function (Node $node): bool {
291+
if (! $node instanceof MethodCall) {
292+
return false;
293+
}
294+
295+
if (! $node->name instanceof Identifier) {
296+
return false;
297+
}
298+
299+
return $node->name->toString() === 'beConstructedWith';
300+
});
301+
302+
return $methodCall instanceof MethodCall;
303+
}
251304
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PhpSpecToPHPUnit\NodeFactory;
6+
7+
use PhpParser\Modifiers;
8+
use PhpParser\Node\Expr\Assign;
9+
use PhpParser\Node\Expr\New_;
10+
use PhpParser\Node\Expr\PropertyFetch;
11+
use PhpParser\Node\Expr\Variable;
12+
use PhpParser\Node\Identifier;
13+
use PhpParser\Node\Name\FullyQualified;
14+
use PhpParser\Node\Stmt\ClassMethod;
15+
use PhpParser\Node\Stmt\Expression;
16+
use Rector\PhpSpecToPHPUnit\ValueObject\TestedObject;
17+
use Rector\ValueObject\MethodName;
18+
19+
final class SetUpInstanceFactory
20+
{
21+
public function createSetUpClassMethod(TestedObject $testedObject): ClassMethod
22+
{
23+
$classMethod = new ClassMethod(MethodName::SET_UP);
24+
$classMethod->returnType = new Identifier('void');
25+
$classMethod->flags |= Modifiers::PROTECTED;
26+
27+
$propertyFetch = new PropertyFetch(new Variable('this'), $testedObject->getPropertyName());
28+
$new = new New_(new FullyQualified($testedObject->getClassName()));
29+
30+
$classMethod->stmts = [new Expression(new Assign($propertyFetch, $new))];
31+
32+
return $classMethod;
33+
}
34+
}

src/NodeFactory/WillReturnMapMethodCallFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ private function createConsecutiveItemsArray(
9393
PhpSpecMethodName::SHOULD_RETURN
9494
);
9595

96-
if (empty($returnArgs)) {
96+
if ($returnArgs === []) {
9797
$returnArgs = $this->resolveInputArgs(
9898
$consecutiveMethodCall->getMethodCall(),
9999
PhpSpecMethodName::WILL_RETURN
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace spec\Set\Sylius;
4+
5+
use PhpSpec\ObjectBehavior;
6+
7+
final class SomeTestedClassSpec extends ObjectBehavior
8+
{
9+
public function it_is_initializable(): void
10+
{
11+
$this->shouldHaveType(SomeTestedClass::class);
12+
}
13+
14+
public function it_implements(): void
15+
{
16+
$this->shouldImplement(RandomInterface::class);
17+
}
18+
}
19+
20+
?>
21+
-----
22+
<?php
23+
24+
namespace Tests\Set\Sylius;
25+
26+
use PhpSpec\ObjectBehavior;
27+
28+
final class SomeTestedClassTest extends \PHPUnit\Framework\TestCase
29+
{
30+
private \Set\Sylius\SomeTestedClass $someTestedClass;
31+
protected function setUp(): void
32+
{
33+
$this->someTestedClass = new \Set\Sylius\SomeTestedClass();
34+
}
35+
public function testImplements(): void
36+
{
37+
$this->assertInstanceOf(RandomInterface::class, $this->someTestedClass);
38+
}
39+
}
40+
41+
?>

0 commit comments

Comments
 (0)