Skip to content

Commit e2b5ff1

Browse files
committed
SpecificAssertContainsWithoutIdentityRector: add phpunit 9 compatibility rector
As of sebastianbergmann/phpunit#3426 assertContains() and assertNotContains() will perform strict comparisons starting with PHPUnit 9 where non-strict comparisons were performed in PHPUnit 8 and earlier; assertContainsEqual() and assertNotContainsEqual() should be used instead if needed non-strict comparison
1 parent 3b68551 commit e2b5ff1

File tree

8 files changed

+254
-1
lines changed

8 files changed

+254
-1
lines changed

config/set/phpunit/phpunit90.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
services:
22
Rector\PHPUnit\Rector\Class_\TestListenerToHooksRector: null
33
Rector\PHPUnit\Rector\MethodCall\ExplicitPhpErrorApiRector: null
4+
Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector: null

docs/AllRectorsOverview.md

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# All 464 Rectors Overview
1+
# All 465 Rectors Overview
22

33
- [Projects](#projects)
44
- [General](#general)
@@ -5677,6 +5677,32 @@ Change assertContains()/assertNotContains() method to new string and iterable al
56775677

56785678
<br>
56795679

5680+
### `SpecificAssertContainsWithoutIdentityRector`
5681+
5682+
- class: [`Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector`](/../master/rules/phpunit/src/Rector/MethodCall/SpecificAssertContainsWithoutIdentityRector.php)
5683+
- [test fixtures](/../master/rules/phpunit/tests/Rector/MethodCall/SpecificAssertContainsWithoutIdentityRector/Fixture)
5684+
5685+
Change assertContains()/assertNotContains() with non-strict comparison to new specific alternatives
5686+
5687+
```diff
5688+
<?php
5689+
5690+
-final class SomeTest extends \PHPUnit\Framework\TestCase
5691+
+final class SomeTest extends TestCase
5692+
{
5693+
public function test()
5694+
{
5695+
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
5696+
- $this->assertContains(new \stdClass(), $objects, 'message', false, false);
5697+
- $this->assertNotContains(new \stdClass(), $objects, 'message', false, false);
5698+
+ $this->assertContainsEquals(new \stdClass(), $objects, 'message');
5699+
+ $this->assertNotContainsEquals(new \stdClass(), $objects, 'message');
5700+
}
5701+
}
5702+
```
5703+
5704+
<br>
5705+
56805706
### `SpecificAssertInternalTypeRector`
56815707

56825708
- class: [`Rector\PHPUnit\Rector\MethodCall\SpecificAssertInternalTypeRector`](/../master/rules/phpunit/src/Rector/MethodCall/SpecificAssertInternalTypeRector.php)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PHPUnit\Rector\MethodCall;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\MethodCall;
9+
use PhpParser\Node\Expr\StaticCall;
10+
use PhpParser\Node\Identifier;
11+
use PHPStan\Type\StringType;
12+
use Rector\Core\Rector\AbstractPHPUnitRector;
13+
use Rector\Core\RectorDefinition\CodeSample;
14+
use Rector\Core\RectorDefinition\RectorDefinition;
15+
16+
/**
17+
* @see https://github.com/sebastianbergmann/phpunit/issues/3426
18+
* @see \Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\SpecificAssertContainsWithoutIdentityRectorTest
19+
*/
20+
final class SpecificAssertContainsWithoutIdentityRector extends AbstractPHPUnitRector
21+
{
22+
/**
23+
* @var string[][]
24+
*/
25+
private const OLD_METHODS_NAMES_TO_NEW_NAMES = [
26+
'string' => [
27+
'assertContains' => 'assertContainsEquals',
28+
'assertNotContains' => 'assertNotContainsEquals',
29+
],
30+
];
31+
32+
public function getDefinition(): RectorDefinition
33+
{
34+
return new RectorDefinition(
35+
'Change assertContains()/assertNotContains() with non-strict comparison to new specific alternatives',
36+
[
37+
new CodeSample(
38+
<<<'PHP'
39+
<?php
40+
41+
final class SomeTest extends \PHPUnit\Framework\TestCase
42+
{
43+
public function test()
44+
{
45+
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
46+
$this->assertContains(new \stdClass(), $objects, 'message', false, false);
47+
$this->assertNotContains(new \stdClass(), $objects, 'message', false, false);
48+
}
49+
}
50+
PHP
51+
,
52+
<<<'PHP'
53+
<?php
54+
55+
final class SomeTest extends TestCase
56+
{
57+
public function test()
58+
{
59+
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
60+
$this->assertContainsEquals(new \stdClass(), $objects, 'message');
61+
$this->assertNotContainsEquals(new \stdClass(), $objects, 'message');
62+
}
63+
}
64+
PHP
65+
),
66+
]
67+
);
68+
}
69+
70+
/**
71+
* @return string[]
72+
*/
73+
public function getNodeTypes(): array
74+
{
75+
return [MethodCall::class, StaticCall::class];
76+
}
77+
78+
/**
79+
* @param MethodCall|StaticCall $node
80+
*/
81+
public function refactor(Node $node): ?Node
82+
{
83+
if (! $this->isPHPUnitMethodNames($node, ['assertContains', 'assertNotContains'])) {
84+
return null;
85+
}
86+
87+
//when second argument is string: do nothing
88+
if ($this->isStaticType($node->args[1]->value, StringType::class)) {
89+
return null;
90+
}
91+
92+
//when less then 5 arguments given: do nothing
93+
if (! isset($node->args[4]) || $node->args[4]->value === null) {
94+
return null;
95+
}
96+
97+
//when 5th argument check identity is true: do nothing
98+
if ($this->isValue($node->args[4]->value, true)) {
99+
return null;
100+
}
101+
102+
/* here we search for element of array without identity check and we can replace functions */
103+
$methodName = $this->getName($node->name);
104+
105+
$node->name = new Identifier(self::OLD_METHODS_NAMES_TO_NEW_NAMES['string'][$methodName]);
106+
unset($node->args[3], $node->args[4]);
107+
108+
return $node;
109+
}
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use stdClass;
7+
8+
final class CheckIdentity extends TestCase
9+
{
10+
public function test()
11+
{
12+
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
13+
$this->assertContains(new stdClass(), $objects, 'message', false, true);
14+
$this->assertNotContains(new stdClass(), $objects, 'message', false, true);
15+
}
16+
}
17+
18+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use stdClass;
7+
8+
final class SomeTest extends TestCase
9+
{
10+
public function test()
11+
{
12+
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
13+
$this->assertContains(new stdClass(), $objects, 'message', false, false);
14+
$this->assertNotContains(new stdClass(), $objects, 'message', false, false);
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
23+
24+
use PHPUnit\Framework\TestCase;
25+
use stdClass;
26+
27+
final class SomeTest extends TestCase
28+
{
29+
public function test()
30+
{
31+
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
32+
$this->assertContainsEquals(new stdClass(), $objects, 'message');
33+
$this->assertNotContainsEquals(new stdClass(), $objects, 'message');
34+
}
35+
}
36+
37+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use stdClass;
7+
8+
final class PartialArguments extends TestCase
9+
{
10+
public function test()
11+
{
12+
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
13+
$this->assertContains(new stdClass(), $objects, 'message', false);
14+
$this->assertNotContains(new stdClass(), $objects, 'message', false);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class NoChangeOnStrings extends TestCase
8+
{
9+
public function test()
10+
{
11+
$this->assertContains('foo', 'foo bar', 'message', false, false);
12+
$this->assertNotContains('foo', 'foo bar', 'message', false, false);
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector;
6+
7+
use Iterator;
8+
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
9+
10+
use Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector;
11+
12+
final class SpecificAssertContainsWithoutIdentityRectorTest extends AbstractRectorTestCase
13+
{
14+
/**
15+
* @dataProvider provideData()
16+
*/
17+
public function test(string $file): void
18+
{
19+
$this->doTestFile($file);
20+
}
21+
22+
public function provideData(): Iterator
23+
{
24+
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
25+
}
26+
27+
protected function getRectorClass(): string
28+
{
29+
return SpecificAssertContainsWithoutIdentityRector::class;
30+
}
31+
}

0 commit comments

Comments
 (0)