From ad5765344d3921bda8c53124f4916993171bf9ef Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 7 Jul 2026 21:31:38 +1000 Subject: [PATCH 1/3] Refactor tests and test runner, add BOM sniff, add bom specific ruleset to prevent changing the superfluous space check --- WordPress-VIP-Go/ruleset-test-bom.inc | 3 +++ WordPress-VIP-Go/ruleset-test.php | 18 ++++++++++++++++-- WordPressVIPMinimum/ruleset-test-bom.inc | 3 +++ WordPressVIPMinimum/ruleset-test.php | 18 ++++++++++++++++-- WordPressVIPMinimum/ruleset.xml | 1 + tests/RulesetTest.php | 18 ++++++++++++++---- 6 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 WordPress-VIP-Go/ruleset-test-bom.inc create mode 100644 WordPressVIPMinimum/ruleset-test-bom.inc diff --git a/WordPress-VIP-Go/ruleset-test-bom.inc b/WordPress-VIP-Go/ruleset-test-bom.inc new file mode 100644 index 00000000..7ecb784f --- /dev/null +++ b/WordPress-VIP-Go/ruleset-test-bom.inc @@ -0,0 +1,3 @@ + [ + 1 => 1, + ], + 'warnings' => [], + 'messages' => [ + 1 => [ + 'File contains UTF-8 byte order mark, which may corrupt your application', + ], + ], +]; + require __DIR__ . '/../tests/RulesetTest.php'; // Run the tests! -$test = new RulesetTest( 'WordPress-VIP-Go', $expected ); -if ( $test->passes() ) { +$test = new RulesetTest( 'WordPress-VIP-Go', $expected ); +$bom_test = new RulesetTest( 'WordPress-VIP-Go', $bom_expected, 'ruleset-test-bom.inc' ); +if ( $test->passes() && $bom_test->passes() ) { printf( 'All WordPress-VIP-Go tests passed!' . PHP_EOL ); exit( 0 ); } diff --git a/WordPressVIPMinimum/ruleset-test-bom.inc b/WordPressVIPMinimum/ruleset-test-bom.inc new file mode 100644 index 00000000..7ecb784f --- /dev/null +++ b/WordPressVIPMinimum/ruleset-test-bom.inc @@ -0,0 +1,3 @@ + [ + 1 => 1, + ], + 'warnings' => [], + 'messages' => [ + 1 => [ + 'File contains UTF-8 byte order mark, which may corrupt your application', + ], + ], +]; + require __DIR__ . '/../tests/RulesetTest.php'; // Run the tests! -$test = new RulesetTest( 'WordPressVIPMinimum', $expected ); -if ( $test->passes() ) { +$test = new RulesetTest( 'WordPressVIPMinimum', $expected ); +$bom_test = new RulesetTest( 'WordPressVIPMinimum', $bom_expected, 'ruleset-test-bom.inc' ); +if ( $test->passes() && $bom_test->passes() ) { printf( 'All WordPressVIPMinimum tests passed!' . PHP_EOL ); exit( 0 ); } diff --git a/WordPressVIPMinimum/ruleset.xml b/WordPressVIPMinimum/ruleset.xml index c735a3b9..c0f66990 100644 --- a/WordPressVIPMinimum/ruleset.xml +++ b/WordPressVIPMinimum/ruleset.xml @@ -60,6 +60,7 @@ + diff --git a/tests/RulesetTest.php b/tests/RulesetTest.php index 3fb863f4..dc03e3ef 100644 --- a/tests/RulesetTest.php +++ b/tests/RulesetTest.php @@ -74,6 +74,13 @@ class RulesetTest { */ private $phpcs_bin = 'phpcs'; + /** + * Name of the fixture file (relative to the ruleset directory) to check. + * + * @var string + */ + private $fixture = 'ruleset-test.inc'; + /** * String returned by PHP_CodeSniffer report for an Error. */ @@ -84,10 +91,12 @@ class RulesetTest { * * @param string $ruleset Name of the ruleset e.g. WordPressVIPMinimum or WordPress-VIP-Go. * @param array>> $expected The array of expected errors, warnings and messages. + * @param string $fixture Name of the fixture file within the ruleset directory to check. Defaults to `ruleset-test.inc`. */ - public function __construct( $ruleset, $expected = [] ) { + public function __construct( $ruleset, $expected = [], $fixture = 'ruleset-test.inc' ) { $this->ruleset = $ruleset; $this->expected = $expected; + $this->fixture = $fixture; // Travis and Windows support. $phpcs_bin = getenv( 'PHPCS_BIN' ); @@ -99,7 +108,7 @@ public function __construct( $ruleset, $expected = [] ) { } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - printf( 'Testing the ' . $this->ruleset . ' ruleset.' . PHP_EOL ); + printf( 'Testing the ' . $this->ruleset . ' ruleset against ' . $this->fixture . '.' . PHP_EOL ); $output = $this->collect_phpcs_result(); @@ -149,11 +158,12 @@ private function collect_phpcs_result() { $report_file = dirname( __DIR__ ) . '/ruleset-tests-report.json'; $shell = sprintf( - '%1$s%2$s --severity=1 --standard=%3$s --report-json=%4$s ./%3$s/ruleset-test.inc', + '%1$s%2$s --severity=1 --standard=%3$s --report-json=%4$s ./%3$s/%5$s', $php, // Current PHP executable if available. $this->phpcs_bin, $this->ruleset, - $report_file + $report_file, + $this->fixture ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_shell_exec -- This is test code, not production. From 06c89838ac8127312301c8c0fd5b30fc28a213be Mon Sep 17 00:00:00 2001 From: Gary Jones Date: Tue, 7 Jul 2026 14:38:54 +0100 Subject: [PATCH 2/3] test: preserve BOM in ruleset test fixtures via EditorConfig The BOM sniff test relies on `ruleset-test-bom.inc` beginning with a UTF-8 byte order mark. The global `[*]` section sets `charset = utf-8`, which prompts EditorConfig-aware editors to strip that mark on save, silently invalidating the Generic.Files.ByteOrderMark ruleset test. A scoped `[*-bom.inc]` override with `charset = utf-8-bom` instructs those editors to keep the mark, protecting the fixture from accidental damage. --- .editorconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.editorconfig b/.editorconfig index 30288000..69ef6731 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,3 +12,9 @@ [*.md] trim_trailing_whitespace = false + + # Preserve the UTF-8 byte order mark in the BOM ruleset test fixtures, so that + # editors honouring EditorConfig do not silently strip it (which would + # invalidate the Generic.Files.ByteOrderMark ruleset test). + [*-bom.inc] + charset = utf-8-bom From 759204488580f360666227084071f8fdae316330 Mon Sep 17 00:00:00 2001 From: Gary Jones Date: Tue, 7 Jul 2026 14:39:02 +0100 Subject: [PATCH 3/3] test: report discrepancies from both ruleset tests Guarding the success path with `$test->passes() && $bom_test->passes()` short-circuits: when the primary ruleset test fails, the BOM test's `passes()` never runs, so its discrepancy report is never printed. That hides half the picture from anyone debugging a failure. Evaluating both results into variables before the check lets each test report its own discrepancies independently. --- WordPress-VIP-Go/ruleset-test.php | 6 +++++- WordPressVIPMinimum/ruleset-test.php | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/WordPress-VIP-Go/ruleset-test.php b/WordPress-VIP-Go/ruleset-test.php index 6af4b359..6f929fbb 100644 --- a/WordPress-VIP-Go/ruleset-test.php +++ b/WordPress-VIP-Go/ruleset-test.php @@ -342,7 +342,11 @@ // Run the tests! $test = new RulesetTest( 'WordPress-VIP-Go', $expected ); $bom_test = new RulesetTest( 'WordPress-VIP-Go', $bom_expected, 'ruleset-test-bom.inc' ); -if ( $test->passes() && $bom_test->passes() ) { + +// Evaluate both tests before the check so each reports its own discrepancies rather than being short-circuited away. +$test_passes = $test->passes(); +$bom_test_passes = $bom_test->passes(); +if ( $test_passes && $bom_test_passes ) { printf( 'All WordPress-VIP-Go tests passed!' . PHP_EOL ); exit( 0 ); } diff --git a/WordPressVIPMinimum/ruleset-test.php b/WordPressVIPMinimum/ruleset-test.php index 19dd17ef..8fd42f54 100644 --- a/WordPressVIPMinimum/ruleset-test.php +++ b/WordPressVIPMinimum/ruleset-test.php @@ -327,7 +327,11 @@ // Run the tests! $test = new RulesetTest( 'WordPressVIPMinimum', $expected ); $bom_test = new RulesetTest( 'WordPressVIPMinimum', $bom_expected, 'ruleset-test-bom.inc' ); -if ( $test->passes() && $bom_test->passes() ) { + +// Evaluate both tests before the check so each reports its own discrepancies rather than being short-circuited away. +$test_passes = $test->passes(); +$bom_test_passes = $bom_test->passes(); +if ( $test_passes && $bom_test_passes ) { printf( 'All WordPressVIPMinimum tests passed!' . PHP_EOL ); exit( 0 ); }