/
githubmirror
/
gutenberg
Обзор
Документация
Войти
/
githubmirror
/
gutenberg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
trunk
phpunit/media/media-processing-test.php
353 строки
12 KB
Adam Silverstein
Media: Stop forcing crossorigin on IMG tags in media templates (#80532)
23 июл 2026, 05:24
Не верифицирован
23 июл 2026, 05:24
cb53341
Код
Авторство
О чём код?
<?php /** * Tests for client-side media processing. * * Client-side media processing is a core feature that uses the browser's * capabilities to handle tasks like image resizing and compression before * uploading to the server. It can be disabled via the * 'wp_client_side_media_processing_enabled' filter or checked using * the gutenberg_is_client_side_media_processing_enabled() helper function. */ class Media_Processing_Test extends WP_UnitTestCase { /** * @var int Administrator ID. */ protected static $admin_id; /** * @var string Image file path. */ private static $image_file; public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { self::$admin_id = $factory->user->create( array( 'role' => 'administrator', ) ); } public function set_up() { parent::set_up(); self::$image_file = get_temp_dir() . 'canola.jpg'; if ( ! file_exists( self::$image_file ) ) { copy( DIR_TESTDATA . '/images/canola.jpg', self::$image_file ); } } public function tear_down() { $this->remove_added_uploads(); parent::tear_down(); } /** * @covers gutenberg_get_all_image_sizes */ public function test_get_all_image_sizes() { $sizes = gutenberg_get_all_image_sizes(); $this->assertNotEmpty( $sizes ); foreach ( $sizes as $size ) { $this->assertIsInt( $size['width'] ); $this->assertIsInt( $size['height'] ); $this->assertIsString( $size['name'] ); } } /** * @covers gutenberg_filter_attachment_post_type_args */ public function test_filter_attachment_post_type_args() { $post_type_object = get_post_type_object( 'attachment' ); $this->assertInstanceOf( Gutenberg_REST_Attachments_Controller::class, $post_type_object->get_rest_controller() ); $this->assertSame( array( 'rest_controller_class' => Gutenberg_REST_Attachments_Controller::class ), gutenberg_filter_attachment_post_type_args( array(), 'attachment' ) ); $this->assertSame( array(), gutenberg_filter_attachment_post_type_args( array(), 'post' ) ); } /** * @covers ::gutenberg_rest_get_attachment_filesize */ public function test_rest_get_attachment_filesize() { $attachment_id = self::factory()->attachment->create_object( self::$image_file, 0, array( 'post_mime_type' => 'image/jpeg', 'post_excerpt' => 'A sample caption', ) ); $this->assertSame( wp_filesize( self::$image_file ), gutenberg_rest_get_attachment_filesize( array( 'id' => $attachment_id ) ) ); } /** * @covers ::gutenberg_rest_get_attachment_filename */ public function test_rest_get_attachment_filename() { $attachment_id = self::factory()->attachment->create_object( self::$image_file, 0, array( 'post_mime_type' => 'image/jpeg', 'post_excerpt' => 'A sample caption', ) ); $this->assertSame( 'canola.jpg', gutenberg_rest_get_attachment_filename( array( 'id' => $attachment_id ) ) ); } /** * @covers ::gutenberg_media_processing_filter_rest_index */ public function test_get_rest_index_should_return_additional_settings() { $server = new WP_REST_Server(); $request = new WP_REST_Request( 'GET', '/' ); $index = $server->dispatch( $request ); $data = $index->get_data(); $this->assertArrayNotHasKey( 'image_size_threshold', $data ); $this->assertArrayNotHasKey( 'image_output_formats', $data ); $this->assertArrayNotHasKey( 'jpeg_interlaced', $data ); $this->assertArrayNotHasKey( 'png_interlaced', $data ); $this->assertArrayNotHasKey( 'gif_interlaced', $data ); $this->assertArrayNotHasKey( 'image_sizes', $data ); $this->assertArrayNotHasKey( 'image_strip_meta', $data ); $this->assertArrayNotHasKey( 'image_max_bit_depth', $data ); } /** * @covers ::gutenberg_media_processing_filter_rest_index */ public function test_get_rest_index_should_return_additional_settings_can_upload_files() { wp_set_current_user( self::$admin_id ); $server = new WP_REST_Server(); $request = new WP_REST_Request( 'GET', '/' ); $index = $server->dispatch( $request ); $data = $index->get_data(); $this->assertArrayHasKey( 'image_size_threshold', $data ); /* * TODO: Reactivate these assertions once the Core PR below merges into trunk: * https://github.com/WordPress/wordpress-develop/pull/12007 * * Core's re-introduced client-side media processing still exposes these * file-less output-format settings on the REST API root index. PR #12007 * removes them in favor of the per-attachment `image_output_format` and * `image_save_progressive` response fields (completing the migration from * Gutenberg #75793). Until that lands in Core, these keys are present when * running against Core trunk, so the assertions are temporarily disabled. */ // $this->assertArrayNotHasKey( 'image_output_formats', $data ); // $this->assertArrayNotHasKey( 'jpeg_interlaced', $data ); // $this->assertArrayNotHasKey( 'png_interlaced', $data ); // $this->assertArrayNotHasKey( 'gif_interlaced', $data ); $this->assertArrayHasKey( 'image_sizes', $data ); $this->assertArrayHasKey( 'image_strip_meta', $data ); $this->assertTrue( $data['image_strip_meta'] ); $this->assertArrayHasKey( 'image_max_bit_depth', $data ); $this->assertSame( 16, $data['image_max_bit_depth'] ); } /** * @covers ::gutenberg_media_processing_filter_rest_index */ public function test_get_rest_index_honors_image_strip_meta_filter() { wp_set_current_user( self::$admin_id ); add_filter( 'image_strip_meta', '__return_false' ); $server = new WP_REST_Server(); $request = new WP_REST_Request( 'GET', '/' ); $index = $server->dispatch( $request ); $data = $index->get_data(); $this->assertFalse( $data['image_strip_meta'] ); } /** * @covers ::gutenberg_media_processing_filter_rest_index */ public function test_get_rest_index_honors_image_max_bit_depth_filter() { wp_set_current_user( self::$admin_id ); add_filter( 'image_max_bit_depth', static function ( $max_depth ) { return min( 8, $max_depth ); } ); $server = new WP_REST_Server(); $request = new WP_REST_Request( 'GET', '/' ); $index = $server->dispatch( $request ); $data = $index->get_data(); $this->assertSame( 8, $data['image_max_bit_depth'] ); } /** * @covers ::gutenberg_add_crossorigin_attributes */ public function test_add_crossorigin_attributes() { $html = <<<HTML <img src="https://www.someothersite.com/test1.jpg" /> <img src="test2.jpg" /> <audio><source src="https://www.someothersite.com/test1.mp3"></audio> <audio src="https://www.someothersite.com/test1.mp3"></audio> <audio src="/test2.mp3"></audio> <video><source src="https://www.someothersite.com/test1.mp4"></video> <video src="https://www.someothersite.com/test1.mp4"></video> <video src="/test2.mp4"></video> <script src="https://www.someothersite.com/test1.js"></script> <script src="/test2.js"></script> <link href="https://www.someothersite.com/test1.css"></link> <link href="/test2.css"></link> HTML; $expected = <<<HTML <img src="https://www.someothersite.com/test1.jpg" /> <img src="test2.jpg" /> <audio crossorigin="anonymous"><source src="https://www.someothersite.com/test1.mp3"></audio> <audio crossorigin="anonymous" src="https://www.someothersite.com/test1.mp3"></audio> <audio src="/test2.mp3"></audio> <video crossorigin="anonymous"><source src="https://www.someothersite.com/test1.mp4"></video> <video crossorigin="anonymous" src="https://www.someothersite.com/test1.mp4"></video> <video src="/test2.mp4"></video> <script crossorigin="anonymous" src="https://www.someothersite.com/test1.js"></script> <script src="/test2.js"></script> <link crossorigin="anonymous" href="https://www.someothersite.com/test1.css"></link> <link href="/test2.css"></link> HTML; $actual = gutenberg_add_crossorigin_attributes( $html ); $this->assertSame( $expected, $actual ); } /** * @covers ::gutenberg_override_media_templates */ public function test_gutenberg_override_media_templates(): void { if ( ! function_exists( '\wp_print_media_templates' ) ) { require_once ABSPATH . WPINC . '/media-template.php'; } gutenberg_override_media_templates(); ob_start(); do_action( 'admin_footer' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound $output = ob_get_clean(); $this->assertStringContainsString( '<audio crossorigin="anonymous"', $output ); $this->assertStringContainsString( '<video crossorigin="anonymous"', $output ); $this->assertStringNotContainsString( 'crossorigin="anonymous" crossorigin=', $output, 'Tags must not receive a duplicate crossorigin attribute when WordPress Core has already added one.' ); } /** * Tests that the media template processing adds crossorigin to AUDIO and * VIDEO tags, skips tags that already have it, and leaves IMG tags * untouched (adding it breaks previews of media served without CORS * headers). * * @covers ::gutenberg_update_media_template_crossorigin_attributes */ public function test_gutenberg_update_media_template_crossorigin_attributes(): void { $html = <<<HTML <script type="text/html" id="tmpl-test-media"> <img src="{{ data.url }}" draggable="false" alt="" /> <audio controls src="{{ data.url }}"></audio> <audio crossorigin="anonymous" controls src="{{ data.url }}"></audio> <video controls src="{{ data.url }}"></video> </script> <script type="text/javascript">var notATemplate = '<img src="test.jpg" />';</script> HTML; $actual = gutenberg_update_media_template_crossorigin_attributes( $html ); $this->assertStringContainsString( '<audio crossorigin="anonymous" controls src="{{ data.url }}"></audio>', $actual ); $this->assertStringContainsString( '<video crossorigin="anonymous" controls src="{{ data.url }}"></video>', $actual ); $this->assertSame( 3, substr_count( $actual, 'crossorigin' ), 'Only the two AUDIO tags and one VIDEO tag should carry a crossorigin attribute, with no duplicates.' ); $this->assertDoesNotMatchRegularExpression( '/<img\b[^>]*\bcrossorigin/i', $actual, 'IMG tags must not receive a crossorigin attribute.' ); $this->assertStringContainsString( "var notATemplate = '<img src=\"test.jpg\" />';", $actual, 'Script tags that are not text/html templates must not be modified.' ); } /** * Tests that client-side media processing is enabled by default in the Gutenberg plugin. * * @covers ::gutenberg_is_client_side_media_processing_enabled */ public function test_client_side_media_processing_enabled_by_default_in_plugin() { $this->assertTrue( gutenberg_is_client_side_media_processing_enabled() ); } /** * Tests that client-side media processing can be disabled via filter. * * @covers ::gutenberg_is_client_side_media_processing_enabled */ public function test_client_side_media_processing_can_be_disabled_via_filter() { add_filter( 'wp_client_side_media_processing_enabled', '__return_false' ); $this->assertFalse( gutenberg_is_client_side_media_processing_enabled() ); remove_filter( 'wp_client_side_media_processing_enabled', '__return_false' ); } /** * Tests that the 7.1 compat REST controller is used when filter disables client-side media. * * @covers ::gutenberg_override_attachments_rest_controller */ public function test_compat_rest_controller_used_when_filter_disabled() { add_filter( 'wp_client_side_media_processing_enabled', '__return_false' ); $result = gutenberg_override_attachments_rest_controller( array(), 'attachment' ); remove_filter( 'wp_client_side_media_processing_enabled', '__return_false' ); $this->assertSame( array( 'rest_controller_class' => 'Gutenberg_REST_Attachments_Controller_7_1' ), $result ); } /** * Tests that the 7.1 compat REST controller is not used when filter is enabled. * * @covers ::gutenberg_override_attachments_rest_controller */ public function test_compat_rest_controller_not_used_when_filter_enabled() { // Feature is enabled by default (core compat layer). $result = gutenberg_override_attachments_rest_controller( array(), 'attachment' ); $this->assertSame( array(), $result ); } }