@@ -28,6 +28,32 @@ public function setUp(): void {
28
28
add_filter ( 'pre_http_request ' , array ( $ this , 'mock_http_requests ' ), 10 , 3 );
29
29
}
30
30
31
+ /**
32
+ * Test that the far-future headers test is added to the site health tests.
33
+ *
34
+ * @covers ::perflab_ffh_add_test
35
+ */
36
+ public function test_perflab_ffh_add_test (): void {
37
+ $ tests = array (
38
+ 'direct ' => array (),
39
+ );
40
+
41
+ $ tests = perflab_ffh_add_test ( $ tests );
42
+
43
+ $ this ->assertArrayHasKey ( 'far_future_headers ' , $ tests ['direct ' ] );
44
+ $ this ->assertEquals ( 'Effective Caching Headers ' , $ tests ['direct ' ]['far_future_headers ' ]['label ' ] );
45
+ $ this ->assertEquals ( 'perflab_ffh_assets_test ' , $ tests ['direct ' ]['far_future_headers ' ]['test ' ] );
46
+ }
47
+
48
+ /**
49
+ * Test that the far-future headers test is attached to the site status tests.
50
+ *
51
+ * @covers ::perflab_ffh_add_test
52
+ */
53
+ public function test_perflab_ffh_add_test_is_attached_to_site_status_tests (): void {
54
+ $ this ->assertNotFalse ( has_filter ( 'site_status_tests ' , 'perflab_ffh_add_test ' ) );
55
+ }
56
+
31
57
/**
32
58
* Test that when all assets have valid far-future headers, the status is "good".
33
59
*
@@ -61,24 +87,85 @@ public function test_all_assets_valid_far_future_headers(): void {
61
87
public function test_assets_conditionally_cached (): void {
62
88
// For conditional caching scenario, setting etag/last-modified headers.
63
89
$ this ->mocked_responses = array (
64
- 'js/wp-embed.min.js ' => $ this ->build_response ( 200 , array ( 'cache-control ' => 'max-age= ' . ( YEAR_IN_SECONDS + 1000 ) ) ),
65
- 'css/buttons.min.css ' => $ this ->build_response ( 200 , array ( 'etag ' => '"123456789" ' ) ),
66
- 'fonts/dashicons.woff2 ' => $ this ->build_response ( 200 , array ( 'last-modified ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ) ),
67
- 'images/media/video.png ' => $ this ->build_response (
90
+ includes_url ( 'js/wp-embed.min.js ' ) => $ this ->build_response ( 200 , array ( 'cache-control ' => 'max-age= ' . ( YEAR_IN_SECONDS + 1000 ) ) ),
91
+ includes_url ( 'css/buttons.min.css ' ) => $ this ->build_response ( 200 , array ( 'etag ' => '"123456789" ' ) ),
92
+ includes_url ( 'fonts/dashicons.woff2 ' ) => $ this ->build_response ( 200 , array ( 'last-modified ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ) ),
93
+ includes_url ( 'images/media/video.png ' ) => $ this ->build_response (
68
94
200 ,
69
95
array (
70
96
'etag ' => '"123456789" ' ,
71
97
'last-modified ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ,
72
98
)
73
99
),
74
- 'conditional_304 ' => $ this ->build_response ( 304 ),
100
+ 'conditional_304 ' => $ this ->build_response ( 304 ),
75
101
);
76
102
77
103
$ result = perflab_ffh_assets_test ();
78
104
$ this ->assertEquals ( 'recommended ' , $ result ['status ' ] );
79
105
$ this ->assertNotEmpty ( $ result ['actions ' ] );
80
106
}
81
107
108
+ /**
109
+ * Test that ETag/Last-Modified is used for conditional requests.
110
+ *
111
+ * @dataProvider data_provider_conditional_headers
112
+ * @covers ::perflab_ffh_try_conditional_request
113
+ *
114
+ * @param string $url The URL to test.
115
+ * @param array<string, string> $headers The headers to send.
116
+ * @param array<string, mixed>|WP_Error $response The response to return.
117
+ * @param bool $expected The expected result.
118
+ */
119
+ public function test_try_conditional_request_function ( string $ url , array $ headers , $ response , bool $ expected ): void {
120
+ $ this ->mocked_responses = array (
121
+ $ url => $ response ,
122
+ );
123
+
124
+ $ result = perflab_ffh_try_conditional_request ( $ url , $ headers );
125
+
126
+ $ this ->assertEquals ( $ expected , $ result );
127
+ }
128
+
129
+ /**
130
+ * Data provider for test_try_conditional_request_function.
131
+ *
132
+ * @return array<array<mixed>> Data provider.
133
+ */
134
+ public function data_provider_conditional_headers (): array {
135
+ return array (
136
+ array (
137
+ includes_url ( 'js/wp-embed.min.js ' ),
138
+ array ( 'If-None-Match ' => '"123456789" ' ),
139
+ $ this ->build_response ( 304 ),
140
+ true ,
141
+ ),
142
+ array (
143
+ includes_url ( 'css/buttons.min.css ' ),
144
+ array ( 'If-Modified-Since ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ),
145
+ $ this ->build_response ( 304 ),
146
+ true ,
147
+ ),
148
+ array (
149
+ includes_url ( 'fonts/dashicons.woff2 ' ),
150
+ array ( 'If-None-Match ' => '"123456789" ' ),
151
+ $ this ->build_response ( 200 ),
152
+ false ,
153
+ ),
154
+ array (
155
+ includes_url ( 'images/media/video.png ' ),
156
+ array ( 'If-Modified-Since ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ),
157
+ $ this ->build_response ( 200 ),
158
+ false ,
159
+ ),
160
+ array (
161
+ includes_url ( 'images/media/video.png ' ),
162
+ array (),
163
+ new WP_Error ( 'http_request_failed ' , 'HTTP request failed ' ),
164
+ false ,
165
+ ),
166
+ );
167
+ }
168
+
82
169
/**
83
170
* Test that different status messages are returned based on the test results.
84
171
*
@@ -90,25 +177,40 @@ public function test_status_messages(): void {
90
177
$ this ->mocked_responses = array (
91
178
includes_url ( 'js/wp-embed.min.js ' ) => $ this ->build_response ( 200 , array ( 'cache-control ' => 'max-age= ' . ( YEAR_IN_SECONDS - 1000 ) ) ),
92
179
includes_url ( 'css/buttons.min.css ' ) => $ this ->build_response ( 200 , array ( 'expires ' => gmdate ( 'D, d M Y H:i:s ' , time () + YEAR_IN_SECONDS - 1000 ) . ' GMT ' ) ),
180
+ includes_url ( 'images/blank.gif ' ) => $ this ->build_response (
181
+ 200 ,
182
+ array (
183
+ 'cache-control ' => 'max-age= ' . ( YEAR_IN_SECONDS - 1000 ),
184
+ 'expires ' => gmdate ( 'D, d M Y H:i:s ' , time () - 1000 ) . ' GMT ' ,
185
+ )
186
+ ),
187
+ 'conditional_304 ' => $ this ->build_response ( 304 ),
93
188
includes_url ( 'fonts/dashicons.woff2 ' ) => $ this ->build_response ( 200 , array ( 'etag ' => '"123456789" ' ) ),
94
189
includes_url ( 'images/media/video.png ' ) => $ this ->build_response ( 200 , array () ),
95
- 'conditional_304 ' => $ this ->build_response ( 304 ),
190
+ includes_url ( 'images/media/video.svg ' ) => new WP_Error ( 'http_request_failed ' , 'HTTP request failed ' ),
191
+ includes_url ( 'images/media/code.png ' ) => array (),
96
192
);
97
193
98
194
$ result = perflab_ffh_check_assets (
99
195
array (
100
196
includes_url ( 'js/wp-embed.min.js ' ),
101
197
includes_url ( 'css/buttons.min.css ' ),
198
+ includes_url ( 'images/blank.gif ' ),
102
199
includes_url ( 'fonts/dashicons.woff2 ' ),
103
200
includes_url ( 'images/media/video.png ' ),
201
+ includes_url ( 'images/media/video.svg ' ),
202
+ includes_url ( 'images/media/code.png ' ),
104
203
)
105
204
);
106
205
107
206
$ this ->assertEquals ( 'recommended ' , $ result ['final_status ' ] );
108
207
$ this ->assertStringContainsString ( 'max-age below threshold (actual: ' , $ result ['details ' ][0 ]['reason ' ] );
109
208
$ this ->assertStringContainsString ( 'expires below threshold (actual: ' , $ result ['details ' ][1 ]['reason ' ] );
110
- $ this ->assertEquals ( 'No far-future headers but conditionally cached ' , $ result ['details ' ][2 ]['reason ' ] );
111
- $ this ->assertEquals ( 'No far-future headers and no conditional caching ' , $ result ['details ' ][3 ]['reason ' ] );
209
+ $ this ->assertStringContainsString ( 'max-age below threshold (actual: ' , $ result ['details ' ][2 ]['reason ' ] );
210
+ $ this ->assertEquals ( 'No far-future headers but conditionally cached ' , $ result ['details ' ][3 ]['reason ' ] );
211
+ $ this ->assertEquals ( 'No far-future headers and no conditional caching ' , $ result ['details ' ][4 ]['reason ' ] );
212
+ $ this ->assertEquals ( 'Could not retrieve headers ' , $ result ['details ' ][5 ]['reason ' ] );
213
+ $ this ->assertEquals ( 'No valid headers retrieved ' , $ result ['details ' ][6 ]['reason ' ] );
112
214
}
113
215
114
216
/**
@@ -177,9 +279,9 @@ public function test_when_no_assets(): void {
177
279
* @param bool $response A preemptive return value of an HTTP request. Default false.
178
280
* @param array<string, mixed> $args Request arguments.
179
281
* @param string $url The request URL.
180
- * @return array<string, mixed> Mocked response.
282
+ * @return array<string, mixed>|WP_Error Mocked response.
181
283
*/
182
- public function mock_http_requests ( bool $ response , array $ args , string $ url ): array {
284
+ public function mock_http_requests ( bool $ response , array $ args , string $ url ) {
183
285
// If conditional headers used in second request, simulate a 304 response.
184
286
if ( isset ( $ this ->mocked_responses ['conditional_304 ' ] ) && ( isset ( $ args ['headers ' ]['If-None-Match ' ] ) || isset ( $ args ['headers ' ]['If-Modified-Since ' ] ) ) ) {
185
287
return $ this ->mocked_responses ['conditional_304 ' ];
0 commit comments