Skip to content

Commit cb96819

Browse files
authored
Ruleset: add tests for handling of php[cs|cbf]-only attributes within a <ruleset> (#711)
Add tests specifically aimed at verifying `phpcs-only` and `phpcbf-only` attributes for elements within a `<ruleset>` are read and handled correctly.
1 parent daf63d9 commit cb96819

File tree

2 files changed

+442
-0
lines changed

2 files changed

+442
-0
lines changed
Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
<?php
2+
/**
3+
* Test handling of `phpc(cs|cbf)-only` instructions at ruleset level.
4+
*
5+
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
6+
* @copyright 2024 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\Core\Ruleset;
11+
12+
use PHP_CodeSniffer\Config;
13+
use PHP_CodeSniffer\Ruleset;
14+
use PHP_CodeSniffer\Tests\ConfigDouble;
15+
use PHPUnit\Framework\TestCase;
16+
17+
/**
18+
* Test handling of `phpc(cs|cbf)-only` instructions at ruleset level.
19+
*
20+
* @covers \PHP_CodeSniffer\Ruleset::processRuleset
21+
* @covers \PHP_CodeSniffer\Ruleset::shouldProcessElement
22+
*/
23+
final class ProcessRulesetShouldProcessElementTest extends TestCase
24+
{
25+
26+
/**
27+
* Cache to store the original ini values for ini settings being changed in these tests.
28+
*
29+
* @var array<string, string|null>
30+
*/
31+
private static $originalIniValues = [
32+
'bcmath.scale' => null,
33+
'docref_root' => null,
34+
'user_agent' => null,
35+
];
36+
37+
/**
38+
* The Config object.
39+
*
40+
* @var \PHP_CodeSniffer\Tests\ConfigDouble
41+
*/
42+
private static $config;
43+
44+
/**
45+
* The Ruleset object.
46+
*
47+
* @var \PHP_CodeSniffer\Ruleset
48+
*/
49+
private static $ruleset;
50+
51+
52+
/**
53+
* Store the original ini values to allow for restoring them after the tests.
54+
*
55+
* @beforeClass
56+
*
57+
* @return void
58+
*/
59+
public static function saveOriginalIniValues()
60+
{
61+
foreach (self::$originalIniValues as $name => $null) {
62+
$value = ini_get($name);
63+
if ($value !== false) {
64+
self::$originalIniValues[$name] = $value;
65+
}
66+
}
67+
68+
}//end saveOriginalIniValues()
69+
70+
71+
/**
72+
* Initialize the config and ruleset objects for this test only once (but do allow recording code coverage).
73+
*
74+
* @before
75+
*
76+
* @return void
77+
*/
78+
protected function initializeConfigAndRuleset()
79+
{
80+
if (isset(self::$ruleset) === false) {
81+
// Set up the ruleset.
82+
$standard = __DIR__.'/ProcessRulesetShouldProcessElementTest.xml';
83+
self::$config = new ConfigDouble(["--standard=$standard"]);
84+
self::$ruleset = new Ruleset(self::$config);
85+
}
86+
87+
}//end initializeConfigAndRuleset()
88+
89+
90+
/**
91+
* Destroy the Config object and restor the ini values after the tests.
92+
*
93+
* @afterClass
94+
*
95+
* @return void
96+
*/
97+
public static function restoreOriginalValues()
98+
{
99+
// Explicitly trigger __destruct() on the ConfigDouble to reset the Config statics.
100+
// The explicit method call prevents potential stray test-local references to the $config object
101+
// preventing the destructor from running the clean up (which without stray references would be
102+
// automagically triggered when this object is destroyed, but we can't definitively rely on that).
103+
if (isset(self::$config) === true) {
104+
self::$config->__destruct();
105+
}
106+
107+
foreach (self::$originalIniValues as $name => $value) {
108+
if ($value === null) {
109+
continue;
110+
}
111+
112+
ini_set($name, $value);
113+
}
114+
115+
}//end restoreOriginalValues()
116+
117+
118+
/**
119+
* Verify that in CS mode, phpcs-only <config> directives are respected and phpcbf-only <config>
120+
* directives are ignored.
121+
*
122+
* @return void
123+
*/
124+
public function testShouldProcessConfigCsonly()
125+
{
126+
if (PHP_CODESNIFFER_CBF === true) {
127+
$this->markTestSkipped('This test needs CS mode to run');
128+
}
129+
130+
$this->assertSame('true', Config::getConfigData('neither'), 'Non-selective config directive was not applied.');
131+
$this->assertSame('true', Config::getConfigData('csOnly'), 'CS-only config directive was not applied.');
132+
$this->assertSame(null, Config::getConfigData('cbfOnly'), 'CBF-only config directive was applied, while it shouldn\'t have been.');
133+
134+
}//end testShouldProcessConfigCsonly()
135+
136+
137+
/**
138+
* Verify that in CBF mode, phpcbf-only <config> directives are respected and phpcs-only <config>
139+
* directives are ignored.
140+
*
141+
* @group CBF
142+
*
143+
* @return void
144+
*/
145+
public function testShouldProcessConfigCbfonly()
146+
{
147+
if (PHP_CODESNIFFER_CBF === false) {
148+
$this->markTestSkipped('This test needs CBF mode to run');
149+
}
150+
151+
$this->assertSame('true', Config::getConfigData('neither'), 'Non-selective config directive was not applied.');
152+
$this->assertSame(null, Config::getConfigData('csOnly'), 'CS-only config directive was applied, while it shouldn\'t have been.');
153+
$this->assertSame('true', Config::getConfigData('cbfOnly'), 'CBF-only config directive was not applied.');
154+
155+
}//end testShouldProcessConfigCbfonly()
156+
157+
158+
/**
159+
* Verify that in CS mode, phpcs-only <arg> directives are respected and phpcbf-only <arg>
160+
* directives are ignored.
161+
*
162+
* @return void
163+
*/
164+
public function testShouldProcessArgCsonly()
165+
{
166+
if (PHP_CODESNIFFER_CBF === true) {
167+
$this->markTestSkipped('This test needs CS mode to run');
168+
}
169+
170+
$expectedExtensions = [
171+
'php' => 'PHP',
172+
'phpt' => 'PHP',
173+
];
174+
$expectedReports = ['full' => null];
175+
176+
$this->assertSame($expectedExtensions, self::$config->extensions, 'Non-selective arg directive was not applied.');
177+
$this->assertTrue(self::$config->showProgress, 'Non-selective short arg directive was not applied [1].');
178+
$this->assertTrue(self::$config->showSources, 'Non-selective short arg directive was not applied [2].');
179+
$this->assertTrue(self::$config->colors, 'CS-only arg directive was not applied.');
180+
$this->assertSame($expectedReports, self::$config->reports, 'CBF-only arg directive was applied, while it shouldn\'t have been.');
181+
182+
}//end testShouldProcessArgCsonly()
183+
184+
185+
/**
186+
* Verify that in CBF mode, phpcbf-only <arg> directives are respected and phpcs-only <arg>
187+
* directives are ignored.
188+
*
189+
* @group CBF
190+
*
191+
* @return void
192+
*/
193+
public function testShouldProcessArgCbfonly()
194+
{
195+
if (PHP_CODESNIFFER_CBF === false) {
196+
$this->markTestSkipped('This test needs CBF mode to run');
197+
}
198+
199+
$expectedExtensions = [
200+
'php' => 'PHP',
201+
'phpt' => 'PHP',
202+
];
203+
$expectedReports = ['summary' => null];
204+
205+
$this->assertSame($expectedExtensions, self::$config->extensions, 'Non-selective arg directive was not applied.');
206+
$this->assertTrue(self::$config->showProgress, 'Non-selective short arg directive was not applied [1].');
207+
$this->assertTrue(self::$config->showSources, 'Non-selective short arg directive was not applied [2].');
208+
$this->assertFalse(self::$config->colors, 'CS-only arg directive was applied, while it shouldn\'t have been.');
209+
$this->assertSame($expectedReports, self::$config->reports, 'CBF-only arg directive was not applied.');
210+
211+
}//end testShouldProcessArgCbfonly()
212+
213+
214+
/**
215+
* Verify that in CS mode, phpcs-only <ini> directives are respected and phpcbf-only <ini>
216+
* directives are ignored.
217+
*
218+
* @return void
219+
*/
220+
public function testShouldProcessIniCsonly()
221+
{
222+
if (PHP_CODESNIFFER_CBF === true) {
223+
$this->markTestSkipped('This test needs CS mode to run');
224+
}
225+
226+
$this->assertSame('2', ini_get('bcmath.scale'), 'Non-selective ini directive was not applied.');
227+
$this->assertSame('path/to/docs/', ini_get('docref_root'), 'CS-only ini directive was not applied.');
228+
$this->assertSame('', ini_get('user_agent'), 'CBF-only ini directive was applied, while it shouldn\'t have been.');
229+
230+
}//end testShouldProcessIniCsonly()
231+
232+
233+
/**
234+
* Verify that in CBF mode, phpcbf-only <ini> directives are respected and phpcs-only <ini>
235+
* directives are ignored.
236+
*
237+
* @group CBF
238+
*
239+
* @return void
240+
*/
241+
public function testShouldProcessIniCbfonly()
242+
{
243+
if (PHP_CODESNIFFER_CBF === false) {
244+
$this->markTestSkipped('This test needs CBF mode to run');
245+
}
246+
247+
$this->assertSame('2', ini_get('bcmath.scale'), 'Non-selective ini directive was not applied.');
248+
$this->assertSame('', ini_get('docref_root'), 'CS-only ini directive was applied, while it shouldn\'t have been..');
249+
$this->assertSame('Never mind', ini_get('user_agent'), 'CBF-only ini directive was not applied.');
250+
251+
}//end testShouldProcessIniCbfonly()
252+
253+
254+
/**
255+
* Verify that in CS mode, phpcs-only <exclude-pattern> directives are respected and phpcbf-only <exclude-pattern>
256+
* directives are ignored.
257+
*
258+
* @return void
259+
*/
260+
public function testShouldProcessExcludePatternCsonly()
261+
{
262+
if (PHP_CODESNIFFER_CBF === true) {
263+
$this->markTestSkipped('This test needs CS mode to run');
264+
}
265+
266+
$expected = [
267+
'./tests/' => 'absolute',
268+
'./vendor/' => 'absolute',
269+
];
270+
271+
$this->assertSame($expected, self::$ruleset->ignorePatterns);
272+
273+
}//end testShouldProcessExcludePatternCsonly()
274+
275+
276+
/**
277+
* Verify that in CBF mode, phpcbf-only <exclude-pattern> directives are respected and phpcs-only <exclude-pattern>
278+
* directives are ignored.
279+
*
280+
* @group CBF
281+
*
282+
* @return void
283+
*/
284+
public function testShouldProcessExcludePatternCbfonly()
285+
{
286+
if (PHP_CODESNIFFER_CBF === false) {
287+
$this->markTestSkipped('This test needs CBF mode to run');
288+
}
289+
290+
$expected = [
291+
'./tests/' => 'absolute',
292+
'./node-modules/' => 'absolute',
293+
];
294+
295+
$this->assertSame($expected, self::$ruleset->ignorePatterns);
296+
297+
}//end testShouldProcessExcludePatternCbfonly()
298+
299+
300+
/**
301+
* Verify that in CS mode, phpcs-only <rule> directives are respected and phpcbf-only <rule>
302+
* directives are ignored.
303+
*
304+
* @return void
305+
*/
306+
public function testShouldProcessRuleCsonly()
307+
{
308+
if (PHP_CODESNIFFER_CBF === true) {
309+
$this->markTestSkipped('This test needs CS mode to run');
310+
}
311+
312+
$this->assertArrayHasKey('PEAR.Formatting.MultiLineAssignment', self::$ruleset->sniffCodes);
313+
$this->assertArrayHasKey('Generic.Arrays.ArrayIndent', self::$ruleset->sniffCodes);
314+
$this->assertArrayNotHasKey('PSR2.Classes.ClassDeclaration', self::$ruleset->sniffCodes);
315+
316+
}//end testShouldProcessRuleCsonly()
317+
318+
319+
/**
320+
* Verify that in CBF mode, phpcbf-only <rule> directives are respected and phpcs-only <rule>
321+
* directives are ignored.
322+
*
323+
* @group CBF
324+
*
325+
* @return void
326+
*/
327+
public function testShouldProcessRuleCbfonly()
328+
{
329+
if (PHP_CODESNIFFER_CBF === false) {
330+
$this->markTestSkipped('This test needs CBF mode to run');
331+
}
332+
333+
$this->assertArrayHasKey('PEAR.Formatting.MultiLineAssignment', self::$ruleset->sniffCodes);
334+
$this->assertArrayNotHasKey('Generic.Arrays.ArrayIndent', self::$ruleset->sniffCodes);
335+
$this->assertArrayHasKey('PSR2.Classes.ClassDeclaration', self::$ruleset->sniffCodes);
336+
337+
}//end testShouldProcessRuleCbfonly()
338+
339+
340+
/**
341+
* Verify that in CS mode, phpcs-only <exclude> in <rule> directives are respected and phpcbf-only <exclude> in <rule>
342+
* directives are ignored.
343+
*
344+
* @return void
345+
*/
346+
public function testShouldProcessRuleExcludeCsonly()
347+
{
348+
if (PHP_CODESNIFFER_CBF === true) {
349+
$this->markTestSkipped('This test needs CS mode to run');
350+
}
351+
352+
$expected = [
353+
'PEAR.Formatting.MultiLineAssignment.Indent' => [
354+
'severity' => 0,
355+
],
356+
];
357+
358+
$this->assertSame($expected, self::$ruleset->ruleset);
359+
360+
}//end testShouldProcessRuleExcludeCsonly()
361+
362+
363+
/**
364+
* Verify that in CBF mode, phpcbf-only <exclude> in <rule> directives are respected and phpcs-only <exclude> in <rule>
365+
* directives are ignored.
366+
*
367+
* @group CBF
368+
*
369+
* @return void
370+
*/
371+
public function testShouldProcessRuleExcludeCbfonly()
372+
{
373+
if (PHP_CODESNIFFER_CBF === false) {
374+
$this->markTestSkipped('This test needs CBF mode to run');
375+
}
376+
377+
$expected = [
378+
'PEAR.Formatting.MultiLineAssignment.EqualSignLine' => [
379+
'severity' => 0,
380+
],
381+
];
382+
383+
$this->assertSame($expected, self::$ruleset->ruleset);
384+
385+
}//end testShouldProcessRuleExcludeCbfonly()
386+
387+
388+
}//end class

0 commit comments

Comments
 (0)