Skip to content

Commit 83b3879

Browse files
committed
Only chek if error starts with a text to avoid issues when the last part change based on cakephp version.
1 parent 54c2a17 commit 83b3879

File tree

3 files changed

+136
-16
lines changed

3 files changed

+136
-16
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace CakeDC\PHPStan\Constraint;
5+
6+
use PHPUnit\Framework\Constraint\Constraint;
7+
8+
class ArrayOfStringStartsWith extends Constraint
9+
{
10+
/**
11+
* @var array<string>
12+
*/
13+
private readonly array $actual;
14+
/**
15+
* @var array<array{expected: string, type: string, actual: string|null}>
16+
*/
17+
private array $result = [];
18+
/**
19+
* @var array<string>
20+
*/
21+
private array $notExpected = [];
22+
23+
/**
24+
* @param array<string> $actual
25+
*/
26+
public function __construct(array $actual)
27+
{
28+
$this->actual = $actual;
29+
}
30+
31+
/**
32+
* @return string
33+
*/
34+
public function toString(): string
35+
{
36+
return 'a list of errors';
37+
}
38+
39+
/**
40+
* @param mixed $other
41+
* @return bool
42+
*/
43+
protected function matches(mixed $other): bool
44+
{
45+
$result = true;
46+
$this->notExpected = $this->actual;
47+
assert(is_array($other));
48+
foreach ($other as $key => $error) {
49+
if (!isset($this->actual[$key])) {
50+
$this->result[$key] = ['expected' => $error, 'type' => 'missing', 'actual' => null];
51+
$result = false;
52+
continue;
53+
}
54+
unset($this->notExpected[$key]);
55+
if (!str_starts_with($this->actual[$key], $error)) {
56+
$this->result[$key] = ['expected' => $error, 'type' => 'not-equal', 'actual' => $this->actual[$key]];
57+
$result = false;
58+
}
59+
}
60+
61+
return $result && empty($this->notExpected);
62+
}
63+
64+
/**
65+
* @param mixed $other
66+
* @return string
67+
*/
68+
protected function failureDescription(mixed $other): string
69+
{
70+
$text = "\n";
71+
foreach ($this->result as $item) {
72+
if ($item['type'] === 'not-equal') {
73+
$text .= sprintf(" -%s \n +%s \n", $item['expected'], $item['actual']);
74+
}
75+
if ($item['type'] === 'missing') {
76+
$text .= sprintf(" -%s \n", $item['expected']);
77+
}
78+
}
79+
80+
foreach ($this->notExpected as $item) {
81+
$text .= sprintf(" \n +%s", $item);
82+
}
83+
84+
return $text;
85+
}
86+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace CakeDC\PHPStan\Rule\Traits;
5+
6+
use CakeDC\PHPStan\Constraint\ArrayOfStringStartsWith;
7+
use PHPStan\Analyser\Error;
8+
9+
/**
10+
* @mixin \PHPStan\Testing\RuleTestCase;
11+
*/
12+
trait AnalyseCheckLineStartsWithTrait
13+
{
14+
/**
15+
* @param array $files
16+
* @param array $expected
17+
* @return void
18+
*/
19+
public function analyseCheckLineStartsWith(array $files, array $expected): void
20+
{
21+
$actualErrors = $this->gatherAnalyserErrors($files);
22+
$messageText = static function (int $line, string $message): string {
23+
return sprintf('%02d: %s', $line, $message);
24+
};
25+
$actualErrors = array_map(static function (Error $error) use ($messageText): string {
26+
$line = $error->getLine();
27+
if ($line === null) {
28+
return $messageText(-1, $error->getMessage());
29+
}
30+
31+
return $messageText($line, $error->getMessage());
32+
}, $actualErrors);
33+
34+
$expected = array_map(static function (array $item) use ($messageText): string {
35+
return $messageText($item[1], $item[0]);
36+
}, $expected);
37+
$this->assertThat($expected, new ArrayOfStringStartsWith($actualErrors));
38+
}
39+
}

tests/TestCase/Rule/Model/AddAssociationMatchOptionsTypesRuleTest.php

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33

44
namespace CakeDC\PHPStan\Test\TestCase\Rule\Model;
55

6-
use Cake\Core\Configure;
76
use CakeDC\PHPStan\Rule\Model\AddAssociationMatchOptionsTypesRule;
7+
use CakeDC\PHPStan\Rule\Traits\AnalyseCheckLineStartsWithTrait;
88
use PHPStan\Rules\Properties\PropertyReflectionFinder;
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleLevelHelper;
1111
use PHPStan\Testing\RuleTestCase;
1212

1313
class AddAssociationMatchOptionsTypesRuleTest extends RuleTestCase
1414
{
15+
use AnalyseCheckLineStartsWithTrait;
16+
1517
/**
1618
* @return \PHPStan\Rules\Rule
1719
*/
@@ -38,14 +40,7 @@ protected function getRule(): Rule
3840
*/
3941
public function testRule(): void
4042
{
41-
$messageThrough = 'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through" (Cake\ORM\Table|string|null) does not accept stdClass.';
42-
if (version_compare(Configure::version(), '5.0.5', '<')) {
43-
$messageThrough = 'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through" (Cake\ORM\Table|string) does not accept stdClass.';
44-
}
45-
// first argument: path to the example file that contains some errors that should be reported by MyRule
46-
// second argument: an array of expected errors,
47-
// each error consists of the asserted error message, and the asserted error file line
48-
$this->analyse([__DIR__ . '/Fake/FailingRuleItemsTable.php'], [
43+
$this->analyseCheckLineStartsWith([__DIR__ . '/Fake/FailingRuleItemsTable.php'], [
4944
[
5045
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "className" (string) does not accept false.',
5146
66,
@@ -67,12 +62,12 @@ public function testRule(): void
6762
66,
6863
],
6964
[
70-
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "bindingKey" (list<string>|string) does not accept 10.',
65+
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "bindingKey" ',
7166
66,
7267
'Type #1 from the union: 10 is not a list.',
7368
],
7469
[
75-
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "foreignKey" (list<string>|string|false) does not accept 11.',
70+
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "foreignKey" ',
7671
66,
7772
'Type #1 from the union: 11 is not a list.',
7873
],
@@ -114,7 +109,7 @@ public function testRule(): void
114109
'Type #1 from the union: Closure(): 10 is not a list.',
115110
],
116111
[
117-
$messageThrough,
112+
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through"',
118113
98,
119114
],
120115
[
@@ -150,12 +145,12 @@ public function testRule(): void
150145
120,
151146
],
152147
[
153-
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "bindingKey" (list<string>|string) does not accept 10.',
148+
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "bindingKey" ',
154149
120,
155150
'Type #1 from the union: 10 is not a list.',
156151
],
157152
[
158-
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "foreignKey" (list<string>|string|false) does not accept 11.',
153+
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "foreignKey" ',
159154
120,
160155
'Type #1 from the union: 11 is not a list.',
161156
],
@@ -220,12 +215,12 @@ public function testRule(): void
220215
148,
221216
],
222217
[
223-
'Call to Cake\ORM\AssociationCollection::load with option "bindingKey" (list<string>|string) does not accept 10.',
218+
'Call to Cake\ORM\AssociationCollection::load with option "bindingKey" ',
224219
148,
225220
'Type #1 from the union: 10 is not a list.',
226221
],
227222
[
228-
'Call to Cake\ORM\AssociationCollection::load with option "foreignKey" (list<string>|string|false) does not accept 11.',
223+
'Call to Cake\ORM\AssociationCollection::load with option "foreignKey" ',
229224
148,
230225
'Type #1 from the union: 11 is not a list.',
231226
],

0 commit comments

Comments
 (0)