- Timestamp:
- 07/16/2024 09:42:38 AM (10 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php
r58594 r58729 185 185 186 186 /** 187 * Invokes the private `print_client_interactivity` method of188 * WP_Interactivity_API class.189 *190 * @return array|null The content of the JSON object printed on the client-side or null if nothings was printed.191 */192 private function print_client_interactivity_data() {193 $interactivity_data_markup = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) );194 preg_match( '/<script type="application\/json" id="wp-interactivity-data">.*?(\{.*\}).*?<\/script>/s', $interactivity_data_markup, $interactivity_data_string );195 return isset( $interactivity_data_string[1] ) ? json_decode( $interactivity_data_string[1], true ) : null;196 }197 198 /**199 * Tests that the initial state and config are correctly printed on the200 * client-side.201 *202 * @ticket 60356203 *204 * @covers ::state205 * @covers ::config206 * @covers ::print_client_interactivity_data207 */208 public function test_state_and_config_is_correctly_printed() {209 $this->interactivity->state( 'myPlugin', array( 'a' => 1 ) );210 $this->interactivity->state( 'otherPlugin', array( 'b' => 2 ) );211 $this->interactivity->config( 'myPlugin', array( 'a' => 1 ) );212 $this->interactivity->config( 'otherPlugin', array( 'b' => 2 ) );213 214 $result = $this->print_client_interactivity_data();215 216 $data = array(217 'myPlugin' => array( 'a' => 1 ),218 'otherPlugin' => array( 'b' => 2 ),219 );220 221 $this->assertSame(222 array(223 'config' => $data,224 'state' => $data,225 ),226 $result227 );228 }229 230 /**231 187 * Tests that the wp-interactivity-data script is not printed if both state 232 188 * and config are empty. 233 189 * 234 190 * @ticket 60356 191 * @ticket 61512 192 */ 193 public function test_state_and_config_dont_print_when_empty() { 194 $filter = $this->get_script_data_filter_result(); 195 196 $this->assertSame( array(), $filter->get_args()[0][0] ); 197 } 198 199 /** 200 * Test that the print_client_interactivity_data is deprecated and produces no output. 201 * 202 * @ticket 60356 203 * @ticket 61512 235 204 * 236 205 * @covers ::print_client_interactivity_data 237 */ 238 public function test_state_and_config_dont_print_when_empty() { 239 $result = $this->print_client_interactivity_data(); 240 $this->assertNull( $result ); 241 } 242 243 /** 244 * Tests that the config is not printed if it's empty. 245 * 246 * @ticket 60356 247 * 248 * @covers ::state 249 * @covers ::print_client_interactivity_data 206 * 207 * @expectedDeprecated WP_Interactivity_API::print_client_interactivity_data 250 208 */ 251 209 public function test_config_not_printed_when_empty() { 252 $this->interactivity->state( 'myPlugin', array( 'a' => 1 ) ); 253 $result = $this->print_client_interactivity_data(); 254 $this->assertSame( array( 'state' => array( 'myPlugin' => array( 'a' => 1 ) ) ), $result ); 255 } 256 257 /** 258 * Tests that the state is not printed if it's empty. 259 * 260 * @ticket 60356 261 * 262 * @covers ::config 263 * @covers ::print_client_interactivity_data 210 $this->interactivity->print_client_interactivity_data(); 211 $this->expectOutputString( '' ); 212 } 213 214 /** 215 * Sets up an activity, runs an optional callback, and returns a MockAction for inspection. 216 * 217 * @since 6.7.0 218 * 219 * @param ?Closure $callback Optional. Callback to run to set up interactivity state and config. 220 * @return MockAction 221 */ 222 private function get_script_data_filter_result( ?Closure $callback = null ): MockAction { 223 $this->interactivity->add_hooks(); 224 $this->interactivity->register_script_modules(); 225 wp_enqueue_script_module( '@wordpress/interactivity' ); 226 $filter = new MockAction(); 227 add_filter( 'script_module_data_@wordpress/interactivity', array( $filter, 'filter' ) ); 228 229 if ( $callback ) { 230 $callback(); 231 } 232 233 ob_start(); 234 wp_script_modules()->print_script_module_data(); 235 ob_end_clean(); 236 237 return $filter; 238 } 239 240 /** 241 * Tests that the state is not included in client data if it's empty. 242 * 243 * @ticket 60356 244 * @ticket 61512 264 245 */ 265 246 public function test_state_not_printed_when_empty() { 266 $this->interactivity->config( 'myPlugin', array( 'a' => 1 ) ); 267 $result = $this->print_client_interactivity_data(); 268 $this->assertSame( array( 'config' => array( 'myPlugin' => array( 'a' => 1 ) ) ), $result ); 247 $filter = $this->get_script_data_filter_result( 248 function () { 249 $this->interactivity->config( 'myPlugin', array( 'a' => 1 ) ); 250 } 251 ); 252 253 $this->assertSame( array( 'config' => array( 'myPlugin' => array( 'a' => 1 ) ) ), $filter->get_args()[0][0] ); 269 254 } 270 255 … … 273 258 * 274 259 * @ticket 60761 275 * 276 * @covers ::print_client_interactivity_data 260 * @ticket 61512 277 261 */ 278 262 public function test_state_not_printed_when_empty_array() { 279 $this->interactivity->state( 'pluginWithEmptyState_prune', array() ); 280 $this->interactivity->state( 'pluginWithState_include', array( 'value' => 'excellent' ) ); 281 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 282 $expected = <<<'SCRIPT_TAG' 283 <script type="application/json" id="wp-interactivity-data"> 284 {"state":{"pluginWithState_include":{"value":"excellent"}}} 285 </script> 286 287 SCRIPT_TAG; 288 289 $this->assertSameIgnoreEOL( $expected, $printed_script ); 263 $filter = $this->get_script_data_filter_result( 264 function () { 265 $this->interactivity->state( 'pluginWithEmptyState_prune', array() ); 266 $this->interactivity->state( 'pluginWithState_include', array( 'value' => 'excellent' ) ); 267 } 268 ); 269 270 $this->assertSame( array( 'state' => array( 'pluginWithState_include' => array( 'value' => 'excellent' ) ) ), $filter->get_args()[0][0] ); 290 271 } 291 272 … … 294 275 * 295 276 * @ticket 60761 296 * 297 * @covers ::print_client_interactivity_data 277 * @ticket 61512 298 278 */ 299 279 public function test_state_not_printed_when_only_empty_arrays() { 300 $this->interactivity->state( 'pluginWithEmptyState_prune', array() ); 301 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 302 $this->assertSame( '', $printed_script ); 280 $filter = $this->get_script_data_filter_result( 281 function () { 282 $this->interactivity->state( 'pluginWithEmptyState_prune', array() ); 283 } 284 ); 285 286 $this->assertSame( array(), $filter->get_args()[0][0] ); 303 287 } 304 288 … … 307 291 * 308 292 * @ticket 60761 309 * 310 * @covers ::print_client_interactivity_data 293 * @ticket 61512 311 294 */ 312 295 public function test_state_printed_correctly_with_nested_empty_array() { 313 $this->interactivity->state( 'myPlugin', array( 'emptyArray' => array() ) ); 314 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 315 $expected = <<<'SCRIPT_TAG' 316 <script type="application/json" id="wp-interactivity-data"> 317 {"state":{"myPlugin":{"emptyArray":[]}}} 318 </script> 319 320 SCRIPT_TAG; 321 322 $this->assertSameIgnoreEOL( $expected, $printed_script ); 296 $filter = $this->get_script_data_filter_result( 297 function () { 298 $this->interactivity->state( 'myPlugin', array( 'emptyArray' => array() ) ); 299 } 300 ); 301 302 $this->assertSame( array( 'state' => array( 'myPlugin' => array( 'emptyArray' => array() ) ) ), $filter->get_args()[0][0] ); 323 303 } 324 304 … … 327 307 * 328 308 * @ticket 60761 329 * 330 * @covers ::print_client_interactivity_data 309 * @ticket 61512 331 310 */ 332 311 public function test_config_not_printed_when_empty_array() { 333 $this->interactivity->config( 'pluginWithEmptyConfig_prune', array() ); 334 $this->interactivity->config( 'pluginWithConfig_include', array( 'value' => 'excellent' ) ); 335 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 336 $expected = <<<'SCRIPT_TAG' 337 <script type="application/json" id="wp-interactivity-data"> 338 {"config":{"pluginWithConfig_include":{"value":"excellent"}}} 339 </script> 340 341 SCRIPT_TAG; 342 343 $this->assertSameIgnoreEOL( $expected, $printed_script ); 312 $filter = $this->get_script_data_filter_result( 313 function () { 314 $this->interactivity->config( 'pluginWithEmptyConfig_prune', array() ); 315 $this->interactivity->config( 'pluginWithConfig_include', array( 'value' => 'excellent' ) ); 316 } 317 ); 318 319 $this->assertSame( array( 'config' => array( 'pluginWithConfig_include' => array( 'value' => 'excellent' ) ) ), $filter->get_args()[0][0] ); 344 320 } 345 321 … … 348 324 * 349 325 * @ticket 60761 350 * 351 * @covers ::print_client_interactivity_data 326 * @ticket 61512 352 327 */ 353 328 public function test_config_not_printed_when_only_empty_arrays() { 354 $this->interactivity->config( 'pluginWithEmptyConfig_prune', array() ); 355 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 356 $this->assertSame( '', $printed_script ); 329 $filter = $this->get_script_data_filter_result( 330 function () { 331 $this->interactivity->config( 'pluginWithEmptyConfig_prune', array() ); 332 } 333 ); 334 335 $this->assertSame( array(), $filter->get_args()[0][0] ); 357 336 } 358 337 … … 361 340 * 362 341 * @ticket 60761 363 * 364 * @covers ::print_client_interactivity_data 342 * @ticket 61512 365 343 */ 366 344 public function test_config_printed_correctly_with_nested_empty_array() { 367 $this->interactivity->config( 'myPlugin', array( 'emptyArray' => array() ) ); 368 $printed_script = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 369 $expected = <<<'SCRIPT_TAG' 370 <script type="application/json" id="wp-interactivity-data"> 371 {"config":{"myPlugin":{"emptyArray":[]}}} 372 </script> 373 374 SCRIPT_TAG; 375 376 $this->assertSameIgnoreEOL( $expected, $printed_script ); 377 } 378 379 /** 380 * Tests that special characters in the initial state and configuration are 381 * properly escaped. 382 * 383 * @ticket 60356 384 * @ticket 61170 385 * 386 * @covers ::state 387 * @covers ::config 388 * @covers ::print_client_interactivity_data 389 */ 390 public function test_state_and_config_escape_special_characters() { 391 $this->interactivity->state( 392 'myPlugin', 393 array( 394 'ampersand' => '&', 395 'less-than sign' => '<', 396 'greater-than sign' => '>', 397 'solidus' => '/', 398 'line separator' => "\u{2028}", 399 'paragraph separator' => "\u{2029}", 400 'flag of england' => "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", 401 'malicious script closer' => '</script>', 402 'entity-encoded malicious script closer' => '</script>', 403 ) 404 ); 405 $this->interactivity->config( 'myPlugin', array( 'chars' => '&<>/' ) ); 406 407 $interactivity_data_markup = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 408 preg_match( '~<script type="application/json" id="wp-interactivity-data">\s*(\{.*\})\s*</script>~s', $interactivity_data_markup, $interactivity_data_string ); 409 410 $expected = <<<"JSON" 411 {"config":{"myPlugin":{"chars":"&\\u003C\\u003E/"}},"state":{"myPlugin":{"ampersand":"&","less-than sign":"\\u003C","greater-than sign":"\\u003E","solidus":"/","line separator":"\u{2028}","paragraph separator":"\u{2029}","flag of england":"\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}","malicious script closer":"\\u003C/script\\u003E","entity-encoded malicious script closer":"</script>"}}} 412 JSON; 413 $this->assertSame( $expected, $interactivity_data_string[1] ); 414 } 415 416 /** 417 * Tests that special characters in the initial state and configuration are 418 * properly escaped when the blog_charset is not UTF-8 (unicode compatible). 419 * 420 * This this test, unicode and line terminators should be escaped to their 421 * JSON unicode sequences. 422 * 423 * @ticket 61170 424 * 425 * @covers ::state 426 * @covers ::config 427 * @covers ::print_client_interactivity_data 428 */ 429 public function test_state_and_config_escape_special_characters_non_utf8() { 430 add_filter( 'pre_option_blog_charset', array( $this, 'charset_iso_8859_1' ) ); 431 $this->interactivity->state( 432 'myPlugin', 433 array( 434 'ampersand' => '&', 435 'less-than sign' => '<', 436 'greater-than sign' => '>', 437 'solidus' => '/', 438 'line separator' => "\u{2028}", 439 'paragraph separator' => "\u{2029}", 440 'flag of england' => "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}", 441 'malicious script closer' => '</script>', 442 'entity-encoded malicious script closer' => '</script>', 443 ) 444 ); 445 $this->interactivity->config( 'myPlugin', array( 'chars' => '&<>/' ) ); 446 447 $interactivity_data_markup = get_echo( array( $this->interactivity, 'print_client_interactivity_data' ) ); 448 preg_match( '~<script type="application/json" id="wp-interactivity-data">\s*(\{.*\})\s*</script>~s', $interactivity_data_markup, $interactivity_data_string ); 449 450 $expected = <<<"JSON" 451 {"config":{"myPlugin":{"chars":"&\\u003C\\u003E/"}},"state":{"myPlugin":{"ampersand":"&","less-than sign":"\\u003C","greater-than sign":"\\u003E","solidus":"/","line separator":"\\u2028","paragraph separator":"\\u2029","flag of england":"\\ud83c\\udff4\\udb40\\udc67\\udb40\\udc62\\udb40\\udc65\\udb40\\udc6e\\udb40\\udc67\\udb40\\udc7f","malicious script closer":"\\u003C/script\\u003E","entity-encoded malicious script closer":"</script>"}}} 452 JSON; 453 $this->assertSame( $expected, $interactivity_data_string[1] ); 345 $filter = $this->get_script_data_filter_result( 346 function () { 347 $this->interactivity->config( 'myPlugin', array( 'emptyArray' => array() ) ); 348 } 349 ); 350 351 $this->assertSame( array( 'config' => array( 'myPlugin' => array( 'emptyArray' => array() ) ) ), $filter->get_args()[0][0] ); 454 352 } 455 353
Note: See TracChangeset
for help on using the changeset viewer.