-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathwp-tests-phpunit-run.js
More file actions
183 lines (164 loc) · 8.18 KB
/
Copy pathwp-tests-phpunit-run.js
File metadata and controls
183 lines (164 loc) · 8.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* Wrap the "composer run wp-tests-php" command to process tests
* that are expected to error and fail at the moment.
*
* Unexpected errors/failures still fail the workflow. Expected failures that
* stop happening are reported so this allowlist can be reduced over time.
*/
const { execSync } = require( 'child_process' );
const fs = require( 'fs' );
const path = require( 'path' );
const requiresNativeParserExtension = process.env.WP_SQLITE_REQUIRE_NATIVE_PARSER_EXTENSION === '1';
const expectedErrors = [
'Tests_DB_Charset::test_invalid_characters_in_query',
'Tests_DB_Charset::test_set_charset_changes_the_connection_collation',
];
const expectedFailures = [
'Tests_Admin_wpSiteHealth::test_object_cache_thresholds with data set #3',
'Tests_Comment::test_wp_update_comment',
'Tests_Comment_CheckComment::test_should_return_false_when_comment_previously_approved_is_enabled_and_author_does_not_have_approved_comment',
'Tests_Comment_CheckComment::test_should_return_true_when_comment_previously_approved_is_enabled_and_author_has_approved_comment',
'Tests_Comment_CheckComment::test_should_return_false_when_comment_previously_approved_is_enabled_and_user_does_not_have_a_previously_approved_comment_with_any_email',
'Tests_DB_Charset::test_get_column_charset with data set #5',
'Tests_DB_Charset::test_get_column_charset with data set #6',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #1',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #2',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #3',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #4',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #5',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #6',
'Tests_DB_Charset::test_get_column_charset_is_mysql_undefined with data set #7',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #1',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #2',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #3',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #4',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #5',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #6',
'Tests_DB_Charset::test_get_column_charset_non_mysql with data set #7',
'Tests_DB_Charset::test_strip_invalid_text with data set #21',
'Tests_DB_Charset::test_strip_invalid_text with data set #22',
'Tests_DB_Charset::test_strip_invalid_text with data set #23',
'Tests_DB_Charset::test_strip_invalid_text with data set #24',
'Tests_DB_Charset::test_strip_invalid_text with data set #25',
'Tests_DB_Charset::test_strip_invalid_text with data set #26',
'Tests_DB_Charset::test_strip_invalid_text with data set #27',
'Tests_DB_Charset::test_strip_invalid_text with data set #28',
'Tests_DB_Charset::test_strip_invalid_text with data set #30',
'Tests_DB_Charset::test_strip_invalid_text with data set #31',
'Tests_DB_Charset::test_strip_invalid_text with data set #32',
'Tests_DB_Charset::test_strip_invalid_text with data set #33',
'Tests_DB_Charset::test_strip_invalid_text with data set #34',
'Tests_DB_Charset::test_strip_invalid_text with data set #39',
'Tests_DB_Charset::test_strip_invalid_text with data set #40',
'Tests_DB_Charset::test_strip_invalid_text with data set #41',
'Tests_DB_dbDelta::test_column_type_change',
'Tests_DB::test_mysqli_flush_sync',
'Tests_DB::test_query_value_contains_invalid_chars',
'Tests_DB::test_replace',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #1',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #2',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #3',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #4',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #5',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #6',
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #7',
'Tests_Menu_wpNavMenu::test_wp_nav_menu_should_not_have_has_children_class_with_custom_depth',
];
console.log( 'Running WordPress PHPUnit tests with expected failures tracking...' );
if ( requiresNativeParserExtension ) {
console.log( 'Native parser extension is required for this PHPUnit run.' );
}
console.log( 'Expected errors:', expectedErrors );
console.log( 'Expected failures:', expectedFailures );
function verifyNativeParserExtension() {
const verifier = path.join( __dirname, '..', '..', 'wordpress', 'native-verify-extension.php' );
if ( ! fs.existsSync( verifier ) ) {
console.error( `Error: Native parser verifier not found at ${ verifier }.` );
process.exit( 1 );
}
execSync( 'composer run wp-test-ensure-env', { stdio: 'inherit' } );
execSync(
'cd wordpress && node tools/local-env/scripts/docker.js run --rm php php /var/www/native-verify-extension.php',
{ stdio: 'inherit' }
);
}
try {
if ( requiresNativeParserExtension ) {
verifyNativeParserExtension();
}
try {
execSync(
`composer run wp-test-php -- --log-junit=phpunit-results.xml --verbose`,
{ stdio: 'inherit' }
);
console.log( '\n⚠️ All tests passed, checking if expected errors/failures occurred...' );
} catch ( error ) {
console.log( '\n⚠️ Some tests errored/failed (expected). Analyzing results...' );
}
// Read the JUnit XML test output:
const junitOutputFile = path.join( __dirname, '..', '..', 'wordpress', 'phpunit-results.xml' );
if ( ! fs.existsSync( junitOutputFile ) ) {
console.error( 'Error: JUnit output file not found!' );
process.exit( 1 );
}
const junitXml = fs.readFileSync( junitOutputFile, 'utf8' );
// Extract test info from the XML:
const actualErrors = [];
const actualFailures = [];
for ( const testcase of junitXml.matchAll( /<testcase([^>]*)\/>|<testcase([^>]*)>([\s\S]*?)<\/testcase>/g ) ) {
const attributes = {};
const attributesString = testcase[2] ?? testcase[1];
for ( const attribute of attributesString.matchAll( /(\w+)="([^"]*)"/g ) ) {
attributes[attribute[1]] = attribute[2];
}
const content = testcase[3] ?? '';
const fqn = attributes.class ? `${attributes.class}::${attributes.name}` : attributes.name;
const hasError = content.includes( '<error' );
const hasFailure = content.includes( '<failure' );
if ( hasError ) {
actualErrors.push( fqn );
}
if ( hasFailure ) {
actualFailures.push( fqn );
}
}
let isSuccess = true;
// Check if all expected errors actually errored
const unexpectedNonErrors = expectedErrors.filter( test => ! actualErrors.includes( test ) );
if ( unexpectedNonErrors.length > 0 ) {
console.error( '\n❌ The following tests were expected to error but did not:' );
unexpectedNonErrors.forEach( test => console.error( ` - ${test}` ) );
isSuccess = false;
}
// Check if all expected failures actually failed
const unexpectedPasses = expectedFailures.filter( test => ! actualFailures.includes( test ) );
if ( unexpectedPasses.length > 0 ) {
console.error( '\n❌ The following tests were expected to fail but passed:' );
unexpectedPasses.forEach( test => console.error( ` - ${test}` ) );
isSuccess = false;
}
// Check for unexpected errors
const unexpectedErrors = actualErrors.filter( test => ! expectedErrors.includes( test ) );
if ( unexpectedErrors.length > 0 ) {
console.error( '\n❌ The following tests errored unexpectedly:' );
unexpectedErrors.forEach( test => console.error( ` - ${test}` ) );
isSuccess = false;
}
// Check for unexpected failures
const unexpectedFailures = actualFailures.filter( test => ! expectedFailures.includes( test ) );
if ( unexpectedFailures.length > 0 ) {
console.error( '\n❌ The following tests failed unexpectedly:' );
unexpectedFailures.forEach( test => console.error( ` - ${test}` ) );
isSuccess = false;
}
if ( isSuccess ) {
console.log( '\n✅ All tests behaved as expected!' );
process.exit( 0 );
} else {
console.log( '\n❌ Some tests did not behave as expected!' );
process.exit( 1 );
}
} catch ( error ) {
console.error( '\n❌ Script execution error:', error.message );
process.exit( 1 );
}