-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathEnqueueFrontendTest.php
More file actions
278 lines (213 loc) · 9.7 KB
/
Copy pathEnqueueFrontendTest.php
File metadata and controls
278 lines (213 loc) · 9.7 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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<?php
/**
* Test cases for the Enqueue_Frontend class.
*
* @package accessibility-checker
*/
use EDAC\Inc\Enqueue_Frontend;
/**
* Tests for Enqueue_Frontend behavior.
*/
class EnqueueFrontendTest extends WP_UnitTestCase {
/**
* Stored filter callbacks to be removed in tearDown.
*
* @var array<string, callable>
*/
private array $added_filters = [];
/**
* Set up test state.
*/
protected function setUp(): void {
parent::setUp();
update_option( 'edac_post_types', [ 'post' ] );
global $wp_scripts, $wp_styles;
$wp_scripts = new \WP_Scripts();
$wp_styles = new \WP_Styles();
}
/**
* Clean up test state.
*/
protected function tearDown(): void {
foreach ( $this->added_filters as $hook => $callback ) {
remove_filter( $hook, $callback );
}
$this->added_filters = [];
delete_option( 'edac_post_types' );
global $wp_scripts, $wp_styles, $post;
unset( $wp_scripts, $wp_styles, $post );
wp_set_current_user( 0 );
parent::tearDown();
}
/**
* Ensure the localized scannerBundleUrl includes the plugin version as a query string parameter.
*/
public function testScannerBundleUrlIncludesVersionQueryString(): void {
$admin_id = $this->factory()->user->create( [ 'role' => 'administrator' ] );
wp_set_current_user( $admin_id );
$created_post = $this->factory()->post->create_and_get( [ 'post_type' => 'post' ] );
global $post;
$post = $created_post;
Enqueue_Frontend::maybe_enqueue_frontend_highlighter();
global $wp_scripts;
$localized_data = $wp_scripts->get_data( 'edac-frontend-highlighter-app', 'data' );
$this->assertNotEmpty( $localized_data );
$this->assertStringContainsString( 'scannerBundleUrl', $localized_data );
$this->assertStringContainsString( 'ver=' . EDAC_VERSION, $localized_data );
}
/**
* Highlighter must NOT load on the "latest posts" homepage when no filter overrides the ID.
*
* When show_on_front=posts, the global $post is the first blog post from the main query, not
* the homepage itself. The fix passes null to the filter so the free plugin bails gracefully.
*/
public function testFrontendHighlighterDoesNotLoadOnLatestPostsHomepage(): void {
$admin_id = $this->factory()->user->create( [ 'role' => 'administrator' ] );
wp_set_current_user( $admin_id );
// Create a post so the main query has results.
$this->factory()->post->create_and_get( [ 'post_type' => 'post' ] );
update_option( 'show_on_front', 'posts' );
// Simulate visiting the homepage so is_home() / is_front_page() return true.
$this->go_to( '/' );
Enqueue_Frontend::maybe_enqueue_frontend_highlighter();
$this->assertFalse( wp_script_is( 'edac-frontend-highlighter-app', 'enqueued' ) );
delete_option( 'show_on_front' );
}
/**
* A filter on edac_filter_frontend_highlight_post_id can enable the highlighter on the
* "latest posts" homepage by supplying a valid post ID (e.g. a Pro virtual-page ID).
*/
public function testFrontendHighlighterLoadsOnLatestPostsHomepageWhenFilterProvidesId(): void {
$admin_id = $this->factory()->user->create( [ 'role' => 'administrator' ] );
wp_set_current_user( $admin_id );
$post = $this->factory()->post->create_and_get( [ 'post_type' => 'post' ] );
update_option( 'show_on_front', 'posts' );
$this->go_to( '/' );
$filter_callback = static function () use ( $post ) {
return $post->ID;
};
$this->added_filters['edac_filter_frontend_highlight_post_id'] = $filter_callback;
add_filter( 'edac_filter_frontend_highlight_post_id', $filter_callback );
Enqueue_Frontend::maybe_enqueue_frontend_highlighter();
$this->assertTrue( wp_script_is( 'edac-frontend-highlighter-app', 'enqueued' ) );
delete_option( 'show_on_front' );
}
/**
* Helper: enqueue the frontend highlighter as an admin and return the localized data string.
*
* @return string The raw JS localized-data string for edac-frontend-highlighter-app.
*/
private function enqueueAndGetLocalizedData(): string {
$admin_id = $this->factory()->user->create( [ 'role' => 'administrator' ] );
wp_set_current_user( $admin_id );
global $post;
$post = $this->factory()->post->create_and_get( [ 'post_type' => 'post' ] );
Enqueue_Frontend::maybe_enqueue_frontend_highlighter();
global $wp_scripts;
return (string) $wp_scripts->get_data( 'edac-frontend-highlighter-app', 'data' );
}
/**
* RestUrl is present in the localized data passed to the frontend highlighter script.
*/
public function testLocalizedDataIncludesRestUrl(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
$this->assertNotEmpty( $localized_data );
$this->assertStringContainsString( 'restUrl', $localized_data );
}
/**
* RestUrl uses the accessibility-checker/v1 namespace and matches rest_url().
*/
public function testRestUrlMatchesRestUrlFunction(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
$expected = rest_url( 'accessibility-checker/v1' );
$this->assertStringContainsString( 'accessibility-checker', $localized_data );
$this->assertStringContainsString( 'v1', $localized_data );
// The URL must be derived from rest_url(), not hardcoded — verify the host is present.
$this->assertStringContainsString( (string) wp_parse_url( $expected, PHP_URL_HOST ), $localized_data );
}
/**
* RestUrl must be an absolute URL, not a root-relative path like /wp-json/...
* A root-relative URL on a subdomain multisite would resolve to the main site.
*/
public function testRestUrlIsAbsolute(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
// The value following "restUrl" must not be a bare /wp-json path.
$this->assertDoesNotMatchRegularExpression( '/"restUrl"\s*:\s*"\\\\?\/wp-json/', $localized_data );
// And the scheme must be present.
$this->assertMatchesRegularExpression( '/"restUrl"\s*:\s*"https?/', $localized_data );
}
/**
* FixesRestUrl is present in the localized data passed to the frontend highlighter script.
*/
public function testLocalizedDataIncludesFixesRestUrl(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
$this->assertStringContainsString( 'fixesRestUrl', $localized_data );
}
/**
* FixesRestUrl uses the accessibility-checker/v1 namespace and matches rest_url().
*/
public function testFixesRestUrlUsesAccessibilityCheckerV1Namespace(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
$expected = esc_url_raw( rest_url( 'accessibility-checker/v1' ) );
$this->assertStringContainsString( '"fixesRestUrl":"' . $expected . '"', str_replace( '\/', '/', $localized_data ) );
}
/**
* FixesRestUrl must be an absolute URL, not a root-relative path.
*/
public function testFixesRestUrlIsAbsolute(): void {
$localized_data = $this->enqueueAndGetLocalizedData();
$this->assertDoesNotMatchRegularExpression( '/"fixesRestUrl"\s*:\s*"\\\\?\/wp-json/', $localized_data );
$this->assertMatchesRegularExpression( '/"fixesRestUrl"\s*:\s*"https?/', $localized_data );
}
/**
* RestUrl must follow a custom REST base prefix set via the rest_url_prefix filter.
* Verifies the URL is built with rest_url() rather than a hardcoded /wp-json/ string.
* Pretty permalinks are required for the prefix filter to be applied.
*/
public function testRestUrlRespectsCustomRestPrefix(): void {
update_option( 'permalink_structure', '/%postname%/' );
flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
$prefix_callback = static fn() => 'custom-api';
add_filter( 'rest_url_prefix', $prefix_callback );
$this->added_filters['rest_url_prefix'] = $prefix_callback;
$localized_data = $this->enqueueAndGetLocalizedData();
remove_filter( 'rest_url_prefix', $prefix_callback );
delete_option( 'permalink_structure' );
$this->assertStringContainsString( 'custom-api', $localized_data );
$this->assertStringNotContainsString( 'wp-json', $localized_data );
}
/**
* FixesRestUrl must follow a custom REST base prefix set via the rest_url_prefix filter.
*/
public function testFixesRestUrlRespectsCustomRestPrefix(): void {
update_option( 'permalink_structure', '/%postname%/' );
flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
$prefix_callback = static fn() => 'custom-api';
add_filter( 'rest_url_prefix', $prefix_callback );
$this->added_filters['rest_url_prefix'] = $prefix_callback;
$localized_data = $this->enqueueAndGetLocalizedData();
$expected = esc_url_raw( rest_url( 'accessibility-checker/v1' ) );
remove_filter( 'rest_url_prefix', $prefix_callback );
delete_option( 'permalink_structure' );
$this->assertStringContainsString( '"fixesRestUrl":"' . $expected . '"', str_replace( '\/', '/', $localized_data ) );
$this->assertStringNotContainsString( 'wp-json', $localized_data );
}
/**
* Ensure the highlighter uses the filtered post ID when determining scannable post types.
*/
public function testFrontendHighlighterUsesFilteredPostIdForScannableType(): void {
$admin_id = $this->factory()->user->create( [ 'role' => 'administrator' ] );
wp_set_current_user( $admin_id );
$scannable_post = $this->factory()->post->create_and_get( [ 'post_type' => 'post' ] );
$global_post = $this->factory()->post->create_and_get( [ 'post_type' => 'page' ] );
global $post;
$post = $global_post;
$filter_callback = static function () use ( $scannable_post ) {
return $scannable_post->ID;
};
$this->added_filters['edac_filter_frontend_highlight_post_id'] = $filter_callback;
add_filter( 'edac_filter_frontend_highlight_post_id', $filter_callback );
Enqueue_Frontend::maybe_enqueue_frontend_highlighter();
$this->assertTrue( wp_script_is( 'edac-frontend-highlighter-app', 'enqueued' ) );
}
}