<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[51493] trunk/tests/phpunit/tests/widgets: Tests: Rename classes in `phpunit/tests/widgets/` per the naming conventions.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/51493">51493</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/51493","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>SergeyBiryukov</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2021-07-26 19:25:09 +0000 (Mon, 26 Jul 2021)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Tests: Rename classes in `phpunit/tests/widgets/` per the naming conventions.
https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/#naming-and-organization
Follow-up to <a href="https://core.trac.wordpress.org/changeset/47780">[47780]</a>, <a href="https://core.trac.wordpress.org/changeset/48911">[48911]</a>, <a href="https://core.trac.wordpress.org/changeset/49327">[49327]</a>, <a href="https://core.trac.wordpress.org/changeset/50291">[50291]</a>, <a href="https://core.trac.wordpress.org/changeset/50292">[50292]</a>, <a href="https://core.trac.wordpress.org/changeset/50342">[50342]</a>, <a href="https://core.trac.wordpress.org/changeset/50452">[50452]</a>, <a href="https://core.trac.wordpress.org/changeset/50453">[50453]</a>, <a href="https://core.trac.wordpress.org/changeset/50456">[50456]</a>, <a href="https://core.trac.wordpress.org/changeset/50967">[50967]</a>, <a href="https://core.trac.wordpress.org/changeset/50968">[50968]</a>, <a href="https://core.trac.wordpress.org/changeset/50969">[50969]</a>, <a href="https://core.trac.wordpress.org/changeset/51491">[51491]</a>, <a href="https://core.trac.wordpress.org/changeset/51492">[514
92]</a>.
See <a href="https://core.trac.wordpress.org/ticket/53363">#53363</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestswidgetswpWidgetRssphp">trunk/tests/phpunit/tests/widgets/wpWidgetRss.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestswidgetswpWidgetCustomHtmlphp">trunk/tests/phpunit/tests/widgets/wpWidgetCustomHtml.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetMediaphp">trunk/tests/phpunit/tests/widgets/wpWidgetMedia.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetMediaAudiophp">trunk/tests/phpunit/tests/widgets/wpWidgetMediaAudio.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetMediaGalleryphp">trunk/tests/phpunit/tests/widgets/wpWidgetMediaGallery.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetMediaImagephp">trunk/tests/phpunit/tests/widgets/wpWidgetMediaImage.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetMediaVideophp">trunk/tests/phpunit/tests/widgets/wpWidgetMediaVideo.php</a></li>
<li><a href="#trunktestsphpunittestswidgetswpWidgetTextphp">trunk/tests/phpunit/tests/widgets/wpWidgetText.php</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestswidgetscustomhtmlwidgetphp">trunk/tests/phpunit/tests/widgets/custom-html-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsmediaaudiowidgetphp">trunk/tests/phpunit/tests/widgets/media-audio-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsmediagallerywidgetphp">trunk/tests/phpunit/tests/widgets/media-gallery-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsmediaimagewidgetphp">trunk/tests/phpunit/tests/widgets/media-image-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsmediavideowidgetphp">trunk/tests/phpunit/tests/widgets/media-video-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsmediawidgetphp">trunk/tests/phpunit/tests/widgets/media-widget.php</a></li>
<li><a href="#trunktestsphpunittestswidgetstextwidgetphp">trunk/tests/phpunit/tests/widgets/text-widget.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsphpunittestswidgetscustomhtmlwidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/custom-html-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/custom-html-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/custom-html-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,358 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Custom_HTML functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-custom-html.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Custom_HTML extends WP_UnitTestCase {
-
- /**
- * Args passed to the widget_custom_html_content filter.
- *
- * @var array
- */
- protected $widget_custom_html_content_args;
-
- /**
- * Args passed to the widget_text filter.
- *
- * @var array
- */
- protected $widget_text_args;
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_style
- */
- public function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Test construct.
- *
- * @covers WP_Widget_Custom_HTML::__construct
- */
- public function test_construct() {
- $widget = new WP_Widget_Custom_HTML();
- $this->assertSame( 'custom_html', $widget->id_base );
- $this->assertSame( 'widget_custom_html', $widget->widget_options['classname'] );
- $this->assertSame( 400, $widget->control_options['width'] );
- $this->assertSame( 350, $widget->control_options['height'] );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Custom_HTML::_register
- */
- public function test__register() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Custom_HTML();
- $widget->_register();
-
- $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
- $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( 'WP_Widget_Custom_HTML', 'render_control_template_scripts' ) ) );
- $this->assertSame( 10, has_action( 'admin_head-widgets.php', array( 'WP_Widget_Custom_HTML', 'add_help_text' ) ) );
- $this->assertContains( 'wp.customHtmlWidgets.idBases.push( "custom_html" );', wp_scripts()->registered['custom-html-widgets']->extra['after'] );
- }
-
- /**
- * Test widget method.
- *
- * @covers WP_Widget_Custom_HTML::widget
- */
- public function test_widget() {
- $widget = new WP_Widget_Custom_HTML();
- $content = "<i>Custom HTML</i>\n\n<b>CODE</b>\nLast line.<u>unclosed";
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => "</h2>\n",
- 'before_widget' => '<section id="custom_html-5" class="widget widget_custom_html">',
- 'after_widget' => "</section>\n",
- );
- $instance = array(
- 'title' => 'Foo',
- 'content' => $content,
- );
-
- // Convert Custom HTML widget instance into Text widget instance data.
- $text_widget_instance = array_merge(
- $instance,
- array(
- 'text' => $instance['content'],
- 'filter' => false,
- 'visual' => false,
- )
- );
- unset( $text_widget_instance['content'] );
-
- update_option( 'use_balanceTags', 0 );
- add_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5, 3 );
- add_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10, 3 );
- ob_start();
- $this->widget_custom_html_content_args = null;
- $this->widget_text_args = null;
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertNotEmpty( $this->widget_custom_html_content_args );
- $this->assertNotEmpty( $this->widget_text_args );
- $this->assertStringContainsString( '[filter:widget_text][filter:widget_custom_html_content]', $output );
- $this->assertStringContainsString( '<section id="custom_html-5" class="widget_text widget widget_custom_html">', $output );
- $this->assertStringContainsString( '<div class="textwidget custom-html-widget">', $output );
- $this->assertStringNotContainsString( '<p>', $output );
- $this->assertStringNotContainsString( '<br>', $output );
- $this->assertStringNotContainsString( '</u>', $output );
- $this->assertSame( $text_widget_instance, $this->widget_text_args[1] );
- $this->assertSame( $instance, $this->widget_custom_html_content_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertSame( $widget, $this->widget_custom_html_content_args[2] );
- remove_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5 );
- remove_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10 );
-
- update_option( 'use_balanceTags', 1 );
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringContainsString( '</u>', $output );
- }
-
- /**
- * Filters the content of the Custom HTML widget using the legacy widget_text filter.
- *
- * @param string $text The widget content.
- * @param array $instance Array of settings for the current widget.
- * @param WP_Widget_Custom_HTML $widget Current widget instance.
- * @return string Widget content.
- */
- public function filter_widget_text( $text, $instance, $widget ) {
- $this->widget_text_args = array( $text, $instance, $widget );
- $text .= '[filter:widget_text]';
- return $text;
- }
-
- /**
- * Filters the content of the Custom HTML widget using the dedicated widget_custom_html_content filter.
- *
- * @param string $widget_content The widget content.
- * @param array $instance Array of settings for the current widget.
- * @param WP_Widget_Custom_HTML $widget Current Custom HTML widget instance.
- * @return string Widget content.
- */
- public function filter_widget_custom_html_content( $widget_content, $instance, $widget ) {
- $this->widget_custom_html_content_args = array( $widget_content, $instance, $widget );
- $widget_content .= '[filter:widget_custom_html_content]';
- return $widget_content;
- }
-
- /**
- * Test update method.
- *
- * @covers WP_Widget_Custom_HTML::update
- */
- public function test_update() {
- $widget = new WP_Widget_Custom_HTML();
- $instance = array(
- 'title' => "The\n<b>Title</b>",
- 'content' => "The\n\n<b>Code</b>",
- );
-
- wp_set_current_user(
- $this->factory()->user->create(
- array(
- 'role' => 'administrator',
- )
- )
- );
-
- // Should return valid instance.
- $expected = array(
- 'title' => sanitize_text_field( $instance['title'] ),
- 'content' => $instance['content'],
- );
- $result = $widget->update( $instance, array() );
- $this->assertSame( $result, $expected );
-
- // Make sure KSES is applying as expected.
- add_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ), 10, 2 );
- $this->assertTrue( current_user_can( 'unfiltered_html' ) );
- $instance['content'] = '<script>alert( "Howdy!" );</script>';
- $expected['content'] = $instance['content'];
- $result = $widget->update( $instance, array() );
- $this->assertSame( $result, $expected );
- remove_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ) );
-
- add_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
- $this->assertFalse( current_user_can( 'unfiltered_html' ) );
- $instance['content'] = '<script>alert( "Howdy!" );</script>';
- $expected['content'] = wp_kses_post( $instance['content'] );
- $result = $widget->update( $instance, array() );
- $this->assertSame( $result, $expected );
- remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10 );
- }
-
- /**
- * Grant unfiltered_html cap via map_meta_cap.
- *
- * @param array $caps Returns the user's actual capabilities.
- * @param string $cap Capability name.
- * @return array Caps.
- */
- public function grant_unfiltered_html_cap( $caps, $cap ) {
- if ( 'unfiltered_html' === $cap ) {
- $caps = array_diff( $caps, array( 'do_not_allow' ) );
- $caps[] = 'unfiltered_html';
- }
- return $caps;
- }
-
- /**
- * Revoke unfiltered_html cap via map_meta_cap.
- *
- * @param array $caps Returns the user's actual capabilities.
- * @param string $cap Capability name.
- * @return array Caps.
- */
- public function revoke_unfiltered_html_cap( $caps, $cap ) {
- if ( 'unfiltered_html' === $cap ) {
- $caps = array_diff( $caps, array( 'unfiltered_html' ) );
- $caps[] = 'do_not_allow';
- }
- return $caps;
- }
-
- /**
- * Test enqueue_admin_scripts method. Condition: logged_in, syntax_highlighting is on.
- *
- * @covers WP_Widget_Custom_HTML::enqueue_admin_scripts
- */
- public function test_enqueue_admin_scripts_when_logged_in_and_syntax_highlighting_on() {
- $user = $this->factory()->user->create();
- wp_set_current_user( $user );
- wp_get_current_user()->syntax_highlighting = 'true';
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Custom_HTML();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'custom-html-widgets', 'enqueued' ) );
- $this->assertTrue( wp_script_is( 'code-editor', 'enqueued' ) );
- $this->assertTrue( wp_script_is( 'wp-codemirror', 'enqueued' ) );
- $this->assertTrue( wp_script_is( 'csslint', 'enqueued' ) );
- $this->assertTrue( wp_script_is( 'jshint', 'enqueued' ) );
- $this->assertTrue( wp_script_is( 'htmlhint', 'enqueued' ) );
- }
-
- /**
- * Test enqueue_admin_scripts method. Condition: logged_in, syntax_highlighting is off.
- *
- * @covers WP_Widget_Custom_HTML::enqueue_admin_scripts
- */
- public function test_enqueue_admin_scripts_when_logged_in_and_syntax_highlighting_off() {
- $user = $this->factory()->user->create();
- wp_set_current_user( $user );
- update_user_meta( $user, 'syntax_highlighting', 'false' );
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Custom_HTML();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'custom-html-widgets', 'enqueued' ) );
- $this->assertFalse( wp_script_is( 'code-editor', 'enqueued' ) );
- $this->assertFalse( wp_script_is( 'wp-codemirror', 'enqueued' ) );
- $this->assertFalse( wp_script_is( 'csslint', 'enqueued' ) );
- $this->assertFalse( wp_script_is( 'jshint', 'enqueued' ) );
- $this->assertFalse( wp_script_is( 'htmlhint', 'enqueued' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Custom_HTML::render_control_template_scripts
- */
- public function test_render_control_template_scripts() {
- ob_start();
- WP_Widget_Custom_HTML::render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-custom-html-control-fields">', $output );
- }
-
- /**
- * Test add_help_text method.
- *
- * @covers WP_Widget_Custom_HTML::add_help_text
- */
- public function test_add_help_text() {
- set_current_screen( 'widgets.php' );
- WP_Widget_Custom_HTML::add_help_text();
- $help_tab = get_current_screen()->get_help_tab( 'custom_html_widget' );
-
- $this->assertStringContainsString( 'Use the Custom HTML widget to add arbitrary HTML code to your widget areas.', $help_tab['content'] );
- }
-
- /**
- * Ensure that rel="noopener" is added to links with a target.
- *
- * @ticket 46421
- */
- function test_render_links_with_target() {
- $widget = new WP_Widget_Custom_HTML();
-
- $content = 'Test content with an external <a href="https://example.org" target="_blank">link</a>.';
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => '</h2>',
- 'before_widget' => '',
- 'after_widget' => '',
- );
-
- $instance = array(
- 'title' => 'Foo',
- 'content' => $content,
- );
-
- $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
- $this->assertStringContainsString( 'rel="noopener"', $output );
- }
-
- /**
- * Ensure that rel="noopener" is not added to links without a target.
- *
- * @ticket 46421
- */
- function test_render_links_without_target() {
- $widget = new WP_Widget_Custom_HTML();
-
- $content = 'Test content with an internal <a href="/">link</a>.';
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => '</h2>',
- 'before_widget' => '',
- 'after_widget' => '',
- );
-
- $instance = array(
- 'title' => 'Foo',
- 'content' => $content,
- );
-
- $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
- $this->assertStringNotContainsString( 'rel="noopener"', $output );
- }
-
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetsmediaaudiowidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/media-audio-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/media-audio-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/media-audio-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,327 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Media_Audio functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-audio.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Media_Audio extends WP_UnitTestCase {
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- */
- function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Audio::get_instance_schema
- */
- function test_get_instance_schema() {
- $wp_widget_audio = new WP_Widget_Media_Audio();
- $schema = $wp_widget_audio->get_instance_schema();
-
- $this->assertSameSets(
- array_merge(
- array(
- 'attachment_id',
- 'preload',
- 'loop',
- 'title',
- 'url',
- ),
- wp_get_audio_extensions()
- ),
- array_keys( $schema )
- );
- }
-
- /**
- * Test get_instance_schema filtering.
- *
- * @covers WP_Widget_Media_Audio::get_instance_schema
- *
- * @ticket 45029
- */
- function test_get_instance_schema_filtering() {
- $wp_widget_audio = new WP_Widget_Media_Audio();
- $schema = $wp_widget_audio->get_instance_schema();
-
- add_filter( 'widget_media_audio_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
- $schema = $wp_widget_audio->get_instance_schema();
-
- $this->assertTrue( $schema['loop']['default'] );
- }
-
- /**
- * Filters instance schema.
- *
- * @since 5.2.0
- *
- * @param array $schema Schema.
- * @param WP_Widget_Media_Audio $widget Widget.
- * @return array
- */
- public function filter_instance_schema( $schema, $widget ) {
- // Override the default loop value (false).
- $schema['loop']['default'] = true;
- return $schema;
- }
-
- /**
- * Test constructor.
- *
- * @covers WP_Widget_Media_Audio::__construct
- */
- function test_constructor() {
- $widget = new WP_Widget_Media_Audio();
-
- $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
- $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
- $this->assertArrayHasKey( 'description', $widget->widget_options );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- $this->assertSame( 'audio', $widget->widget_options['mime_type'] );
- $this->assertSameSets(
- array(
- 'add_to_widget',
- 'replace_media',
- 'edit_media',
- 'media_library_state_multi',
- 'media_library_state_single',
- 'missing_attachment',
- 'no_media_selected',
- 'add_media',
- 'unsupported_file_type',
- ),
- array_keys( $widget->l10n )
- );
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Audio::update
- */
- function test_update() {
- $widget = new WP_Widget_Media_Audio();
- $instance = array();
-
- // Should return valid attachment ID.
- $expected = array(
- 'attachment_id' => 1,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment ID.
- $result = $widget->update(
- array(
- 'attachment_id' => 'media',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment url.
- $expected = array(
- 'url' => 'https://chickenandribs.org',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment url.
- $result = $widget->update(
- array(
- 'url' => 'not_a_url',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
- $this->assertStringStartsWith( 'http://', $result['url'] );
-
- // Should return loop setting.
- $expected = array(
- 'loop' => true,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid loop setting.
- $result = $widget->update(
- array(
- 'loop' => 'not-boolean',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment title.
- $expected = array(
- 'title' => 'An audio sample of parrots',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment title.
- $result = $widget->update(
- array(
- 'title' => '<h1>Cute Baby Goats</h1>',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should return valid preload setting.
- $expected = array(
- 'preload' => 'none',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid preload setting.
- $result = $widget->update(
- array(
- 'preload' => 'nope',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should filter invalid key.
- $result = $widget->update(
- array(
- 'h4x' => 'value',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
- }
-
- /**
- * Test render_media method.
- *
- * @covers WP_Widget_Media_Audio::render_media
- */
- function test_render_media() {
- $test_audio_file = __FILE__ . '../../data/uploads/small-audio.mp3';
- $widget = new WP_Widget_Media_Audio();
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => $test_audio_file,
- 'post_parent' => 0,
- 'post_mime_type' => 'audio/mp3',
- 'post_title' => 'Test Audio',
- )
- );
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_audio_file ) );
-
- // Should be empty when there is no attachment_id.
- ob_start();
- $widget->render_media( array() );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- // Should be empty when there is an invalid attachment_id.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => 777,
- )
- );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- // Tests with audio from library.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- )
- );
- $output = ob_get_clean();
-
- // Check default outputs.
- $this->assertStringContainsString( 'preload="none"', $output );
- $this->assertStringContainsString( 'class="wp-audio-shortcode"', $output );
- $this->assertStringContainsString( 'small-audio.mp3', $output );
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'title' => 'Funny',
- 'preload' => 'auto',
- 'loop' => true,
- )
- );
- $output = ob_get_clean();
-
- // Custom attributes.
- $this->assertStringContainsString( 'preload="auto"', $output );
- $this->assertStringContainsString( 'loop="1"', $output );
- }
-
- /**
- * Test enqueue_preview_scripts method.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- * @covers WP_Widget_Media_Audio::enqueue_preview_scripts
- */
- function test_enqueue_preview_scripts() {
- global $wp_scripts, $wp_styles;
- $wp_scripts = null;
- $wp_styles = null;
- $widget = new WP_Widget_Media_Audio();
-
- $this->assertFalse( wp_script_is( 'wp-mediaelement' ) );
- $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
-
- $widget->enqueue_preview_scripts();
-
- $this->assertTrue( wp_script_is( 'wp-mediaelement' ) );
- $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Media_Audio::enqueue_admin_scripts
- */
- function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Media_Audio();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'media-audio-widget' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Media_Audio::render_control_template_scripts
- */
- function test_render_control_template_scripts() {
- $widget = new WP_Widget_Media_Audio();
-
- ob_start();
- $widget->render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-audio-preview">', $output );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetsmediagallerywidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/media-gallery-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/media-gallery-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/media-gallery-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,204 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Media_Gallery functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-gallery.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Media_Gallery extends WP_UnitTestCase {
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- */
- public function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Gallery::get_instance_schema
- */
- public function test_get_instance_schema() {
- $widget = new WP_Widget_Media_Gallery();
- $schema = $widget->get_instance_schema();
-
- $this->assertSameSets(
- array(
- 'title',
- 'ids',
- 'columns',
- 'size',
- 'link_type',
- 'orderby_random',
- ),
- array_keys( $schema )
- );
- }
-
- /**
- * Test update() method.
- *
- * @covers WP_Widget_Media_Gallery::render_media
- * @requires function imagejpeg
- */
- public function test_render_media() {
- $widget = new WP_Widget_Media_Gallery();
-
- $attachments = array();
- foreach ( array( 'canola.jpg', 'waffles.jpg' ) as $filename ) {
- $test_image = get_temp_dir() . $filename;
- copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => $test_image,
- 'post_parent' => 0,
- 'post_mime_type' => 'image/jpeg',
- 'post_title' => 'Canola',
- )
- );
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
- $attachments[ $filename ] = $attachment_id;
- }
-
- $instance = wp_list_pluck( $widget->get_instance_schema(), 'default' );
- $instance['size'] = 'thumbnail';
- $instance['columns'] = 3;
- $instance['ids'] = array_values( $attachments );
- ob_start();
- $widget->render_media( $instance );
- $output = ob_get_clean();
-
- $this->assertStringContainsString( 'gallery-columns-3', $output );
- $this->assertStringContainsString( 'gallery-size-thumbnail', $output );
- $this->assertStringContainsString( 'canola', $output );
- $this->assertStringContainsString( 'waffles', $output );
- }
-
- /**
- * Test enqueue_admin_scripts() method.
- *
- * @covers WP_Widget_Media_Gallery::enqueue_admin_scripts
- */
- public function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Media_Gallery();
-
- $this->assertFalse( wp_script_is( 'media-gallery-widget' ) );
-
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'media-gallery-widget' ) );
-
- $after = implode( '', wp_scripts()->registered['media-gallery-widget']->extra['after'] );
- $this->assertStringContainsString( 'wp.mediaWidgets.modelConstructors[ "media_gallery" ].prototype', $after );
- }
-
- /**
- * Test update() method.
- *
- * @covers WP_Widget_Media_Gallery::update
- */
- public function test_update() {
- $widget = new WP_Widget_Media_Gallery();
- $schema = $widget->get_instance_schema();
- $instance = wp_list_pluck( $schema, 'default' );
-
- // Field: title.
- $instance['title'] = 'Hello <b>World</b> ';
- $instance = $widget->update( $instance, array() );
- $this->assertSame( 'Hello World', $instance['title'] );
-
- // Field: ids.
- $instance['ids'] = '1,2,3';
- $instance = $widget->update( $instance, array() );
- $this->assertSame( array( 1, 2, 3 ), $instance['ids'] );
-
- $instance['ids'] = array( 1, 2, '3' );
- $instance = $widget->update( $instance, array() );
- $this->assertSame( array( 1, 2, 3 ), $instance['ids'] );
-
- $instance['ids'] = array( 'too', 'bad' );
- $instance = $widget->update( $instance, array( 'ids' => array( 2, 3 ) ) );
- $this->assertSame( array( 2, 3 ), $instance['ids'] );
-
- // Field: columns.
- $instance['columns'] = 4;
- $instance = $widget->update( $instance, array() );
- $this->assertSame( 4, $instance['columns'] );
-
- $instance['columns'] = '2';
- $instance = $widget->update( $instance, array() );
- $this->assertSame( 2, $instance['columns'] );
-
- $instance['columns'] = -1; // Under min of 1.
- $instance = $widget->update( $instance, array( 'columns' => 3 ) );
- $this->assertSame( 3, $instance['columns'] );
-
- $instance['columns'] = 10; // Over max of 9.
- $instance = $widget->update( $instance, array( 'columns' => 3 ) );
- $this->assertSame( 3, $instance['columns'] );
-
- // Field: size.
- $instance['size'] = 'large';
- $instance = $widget->update( $instance, array() );
- $this->assertSame( 'large', $instance['size'] );
-
- $instance['size'] = 'bad';
- $instance = $widget->update( $instance, array( 'size' => 'thumbnail' ) );
- $this->assertSame( 'thumbnail', $instance['size'] );
-
- // Field: link_type.
- $instance['link_type'] = 'none';
- $instance = $widget->update( $instance, array() );
- $this->assertSame( 'none', $instance['link_type'] );
-
- $instance['link_type'] = 'unknown';
- $instance = $widget->update( $instance, array( 'link_type' => 'file' ) );
- $this->assertSame( 'file', $instance['link_type'] );
-
- // Field: orderby_random.
- $instance['orderby_random'] = '1';
- $instance = $widget->update( $instance, array() );
- $this->assertTrue( $instance['orderby_random'] );
-
- $instance['orderby_random'] = true;
- $instance = $widget->update( $instance, array() );
- $this->assertTrue( $instance['orderby_random'] );
-
- $instance['orderby_random'] = '';
- $instance = $widget->update( $instance, array() );
- $this->assertFalse( $instance['orderby_random'] );
-
- $instance['orderby_random'] = false;
- $instance = $widget->update( $instance, array() );
- $this->assertFalse( $instance['orderby_random'] );
- }
-
- /**
- * Test render_control_template_scripts() method.
- *
- * @covers WP_Widget_Media_Gallery::render_control_template_scripts
- */
- public function test_render_control_template_scripts() {
- $widget = new WP_Widget_Media_Gallery();
-
- ob_start();
- $widget->render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-gallery-preview">', $output );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetsmediaimagewidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/media-image-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/media-image-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/media-image-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,633 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Media_Image functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-image.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Media_Image extends WP_UnitTestCase {
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- */
- function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Image::get_instance_schema
- */
- function test_get_instance_schema() {
- $widget = new WP_Widget_Media_Image();
- $schema = $widget->get_instance_schema();
-
- $this->assertSameSets(
- array(
- 'alt',
- 'attachment_id',
- 'caption',
- 'height',
- 'image_classes',
- 'image_title',
- 'link_classes',
- 'link_rel',
- 'link_target_blank',
- 'link_type',
- 'link_url',
- 'size',
- 'title',
- 'url',
- 'width',
- ),
- array_keys( $schema )
- );
- }
-
- /**
- * Test schema filtering.
- *
- * @covers WP_Widget_Media_Image::get_instance_schema
- *
- * @ticket 45029
- */
- function test_get_instance_schema_filtering() {
- $widget = new WP_Widget_Media_Image();
- $schema = $widget->get_instance_schema();
-
- add_filter( 'widget_media_image_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
- $schema = $widget->get_instance_schema();
-
- $this->assertSame( 'large', $schema['size']['default'] );
- }
-
- /**
- * Filters instance schema.
- *
- * @since 5.2.0
- *
- * @param array $schema Schema.
- * @param WP_Widget_Media_Image $widget Widget.
- * @return array
- */
- public function filter_instance_schema( $schema, $widget ) {
- // Override the default size value ('medium').
- $schema['size']['default'] = 'large';
- return $schema;
- }
-
- /**
- * Test constructor.
- *
- * @covers WP_Widget_Media_Image::__construct
- */
- function test_constructor() {
- $widget = new WP_Widget_Media_Image();
-
- $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
- $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
- $this->assertArrayHasKey( 'description', $widget->widget_options );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- $this->assertSame( 'image', $widget->widget_options['mime_type'] );
- $this->assertSameSets(
- array(
- 'add_to_widget',
- 'replace_media',
- 'edit_media',
- 'media_library_state_multi',
- 'media_library_state_single',
- 'missing_attachment',
- 'no_media_selected',
- 'add_media',
- 'unsupported_file_type',
- ),
- array_keys( $widget->l10n )
- );
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Image::update
- */
- function test_update() {
- $widget = new WP_Widget_Media_Image();
- $instance = array();
-
- // Should return valid attachment ID.
- $expected = array(
- 'attachment_id' => 1,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment ID.
- $result = $widget->update(
- array(
- 'attachment_id' => 'media',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment url.
- $expected = array(
- 'url' => 'https://example.org',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment url.
- $result = $widget->update(
- array(
- 'url' => 'not_a_url',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
- $this->assertStringStartsWith( 'http://', $result['url'] );
-
- // Should return valid attachment title.
- $expected = array(
- 'title' => 'What a title',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment title.
- $result = $widget->update(
- array(
- 'title' => '<h1>W00t!</h1>',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should return valid image size.
- $expected = array(
- 'size' => 'thumbnail',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image size.
- $result = $widget->update(
- array(
- 'size' => 'big league',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid image width.
- $expected = array(
- 'width' => 300,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image width.
- $result = $widget->update(
- array(
- 'width' => 'wide',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid image height.
- $expected = array(
- 'height' => 200,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image height.
- $result = $widget->update(
- array(
- 'height' => 'high',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid image caption.
- $expected = array(
- 'caption' => 'A caption with <a href="#">link</a>',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image caption.
- $result = $widget->update(
- array(
- 'caption' => '"><i onload="alert(\'hello\')" />',
- ),
- $instance
- );
- $this->assertSame(
- $result,
- array(
- 'caption' => '"><i />',
- )
- );
-
- // Should return valid alt text.
- $expected = array(
- 'alt' => 'A water tower',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid alt text.
- $result = $widget->update(
- array(
- 'alt' => '"><i onload="alert(\'hello\')" />',
- ),
- $instance
- );
- $this->assertSame(
- $result,
- array(
- 'alt' => '">',
- )
- );
-
- // Should return valid link type.
- $expected = array(
- 'link_type' => 'file',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid link type.
- $result = $widget->update(
- array(
- 'link_type' => 'interesting',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid link url.
- $expected = array(
- 'link_url' => 'https://example.org',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid link url.
- $result = $widget->update(
- array(
- 'link_url' => 'not_a_url',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
- $this->assertStringStartsWith( 'http://', $result['link_url'] );
-
- // Should return valid image classes.
- $expected = array(
- 'image_classes' => 'A water tower',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image classes.
- $result = $widget->update(
- array(
- 'image_classes' => '"><i onload="alert(\'hello\')" />',
- ),
- $instance
- );
- $this->assertSame(
- $result,
- array(
- 'image_classes' => 'i onloadalerthello',
- )
- );
-
- // Should return valid link classes.
- $expected = array(
- 'link_classes' => 'A water tower',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid link classes.
- $result = $widget->update(
- array(
- 'link_classes' => '"><i onload="alert(\'hello\')" />',
- ),
- $instance
- );
- $this->assertSame(
- $result,
- array(
- 'link_classes' => 'i onloadalerthello',
- )
- );
-
- // Should return valid rel text.
- $expected = array(
- 'link_rel' => 'previous',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid rel text.
- $result = $widget->update(
- array(
- 'link_rel' => '"><i onload="alert(\'hello\')" />',
- ),
- $instance
- );
- $this->assertSame(
- $result,
- array(
- 'link_rel' => 'i onloadalerthello',
- )
- );
-
- // Should return valid link target.
- $expected = array(
- 'link_target_blank' => false,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid link target.
- $result = $widget->update(
- array(
- 'link_target_blank' => 'top',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid image title.
- $expected = array(
- 'image_title' => 'What a title',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid image title.
- $result = $widget->update(
- array(
- 'image_title' => '<h1>W00t!</h1>',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should filter invalid key.
- $result = $widget->update(
- array(
- 'imaginary_key' => 'value',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
- }
-
- /**
- * Test render_media method.
- *
- * @covers WP_Widget_Media_Image::render_media
- * @requires function imagejpeg
- */
- function test_render_media() {
- $widget = new WP_Widget_Media_Image();
-
- $test_image = get_temp_dir() . 'canola.jpg';
- copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => $test_image,
- 'post_parent' => 0,
- 'post_mime_type' => 'image/jpeg',
- 'post_title' => 'Canola',
- )
- );
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
-
- // Should be empty when there is no attachment_id.
- ob_start();
- $widget->render_media( array() );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- // Should be empty when there is an invalid attachment_id.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => 666,
- )
- );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- )
- );
- $output = ob_get_clean();
-
- // No default title.
- $this->assertStringNotContainsString( 'title="', $output );
- // Default image classes.
- $this->assertStringContainsString( 'class="image wp-image-' . $attachment_id, $output );
- $this->assertStringContainsString( 'style="max-width: 100%; height: auto;"', $output );
- $this->assertStringContainsString( 'alt=""', $output );
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'image_title' => 'Custom Title',
- 'image_classes' => 'custom-class',
- 'alt' => 'A flower',
- 'size' => 'custom',
- 'width' => 100,
- 'height' => 100,
- )
- );
- $output = ob_get_clean();
-
- // Custom image title.
- $this->assertStringContainsString( 'title="Custom Title"', $output );
- // Custom image class.
- $this->assertStringContainsString( 'class="image wp-image-' . $attachment_id . ' custom-class', $output );
- $this->assertStringContainsString( 'alt="A flower"', $output );
- $this->assertStringContainsString( 'width="100"', $output );
- $this->assertStringContainsString( 'height="100"', $output );
-
- // Embeded images.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => null,
- 'caption' => 'With caption',
- 'height' => 100,
- 'link_type' => 'file',
- 'url' => 'http://example.org/url/to/image.jpg',
- 'width' => 100,
- )
- );
- $output = ob_get_clean();
-
- // Custom image class.
- $this->assertStringContainsString( 'src="http://example.org/url/to/image.jpg"', $output );
-
- // Link settings.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'link_type' => 'file',
- )
- );
- $output = ob_get_clean();
-
- $link = '<a href="' . wp_get_attachment_url( $attachment_id ) . '"';
- $this->assertStringContainsString( $link, $output );
- $this->assertTrue( (bool) preg_match( '#<a href.*?>#', $output, $matches ) );
- $this->assertStringNotContainsString( ' class="', $matches[0] );
- $this->assertStringNotContainsString( ' rel="', $matches[0] );
- $this->assertStringNotContainsString( ' target="', $matches[0] );
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'link_type' => 'post',
- 'link_classes' => 'custom-link-class',
- 'link_rel' => 'attachment',
- 'link_target_blank' => false,
- )
- );
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<a href="' . get_attachment_link( $attachment_id ) . '"', $output );
- $this->assertStringContainsString( 'class="custom-link-class"', $output );
- $this->assertStringContainsString( 'rel="attachment"', $output );
- $this->assertStringNotContainsString( 'target=""', $output );
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'link_type' => 'custom',
- 'link_url' => 'https://example.org',
- 'link_target_blank' => true,
- )
- );
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<a href="https://example.org"', $output );
- $this->assertStringContainsString( 'target="_blank"', $output );
- $this->assertStringContainsString( 'rel="noopener"', $output );
-
- // Populate caption in attachment.
- wp_update_post(
- array(
- 'ID' => $attachment_id,
- 'post_excerpt' => 'Default caption',
- )
- );
-
- // If no caption is supplied, then the default is '', and so the caption will not be displayed.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- )
- );
- $output = ob_get_clean();
- $this->assertStringNotContainsString( 'wp-caption', $output );
- $this->assertStringNotContainsString( '<p class="wp-caption-text">', $output );
-
- // If the caption is explicitly null, then the caption of the underlying attachment will be displayed.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'caption' => null,
- )
- );
- $output = ob_get_clean();
- $this->assertStringContainsString( 'class="wp-caption alignnone"', $output );
- $this->assertStringContainsString( '<p class="wp-caption-text">Default caption</p>', $output );
-
- // If caption is provided, then it will be displayed.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'caption' => 'Custom caption',
- )
- );
- $output = ob_get_clean();
- $this->assertStringContainsString( 'class="wp-caption alignnone"', $output );
- $this->assertStringContainsString( '<p class="wp-caption-text">Custom caption</p>', $output );
-
- // Attachments with custom sizes can render captions.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'size' => 'custom',
- 'width' => '300',
- 'height' => '200',
- 'caption' => 'Caption for an image with custom size',
- )
- );
- $output = ob_get_clean();
- $this->assertStringContainsString( 'style="width: 310px"', $output );
- $this->assertStringContainsString( '<p class="wp-caption-text">Caption for an image with custom size</p>', $output );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Media_Image::enqueue_admin_scripts
- */
- function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Media_Image();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'media-image-widget' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Media_Image::render_control_template_scripts
- */
- function test_render_control_template_scripts() {
- $widget = new WP_Widget_Media_Image();
-
- ob_start();
- $widget->render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-image-preview">', $output );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetsmediavideowidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/media-video-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/media-video-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/media-video-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,355 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Media_Video functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-video.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Media_Video extends WP_UnitTestCase {
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- */
- function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Video::get_instance_schema
- */
- function test_get_instance_schema() {
- $widget = new WP_Widget_Media_Video();
- $schema = $widget->get_instance_schema();
-
- $this->assertSameSets(
- array_merge(
- array(
- 'attachment_id',
- 'preload',
- 'loop',
- 'title',
- 'url',
- 'content',
- ),
- wp_get_video_extensions()
- ),
- array_keys( $schema )
- );
- }
-
- /**
- * Test schema filtering.
- *
- * @covers WP_Widget_Media_Video::get_instance_schema
- *
- * @ticket 45029
- */
- function test_get_instance_schema_filtering() {
- $widget = new WP_Widget_Media_Video();
- $schema = $widget->get_instance_schema();
-
- add_filter( 'widget_media_video_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
- $schema = $widget->get_instance_schema();
-
- $this->assertTrue( $schema['loop']['default'] );
- }
-
- /**
- * Filters instance schema.
- *
- * @since 5.2.0
- *
- * @param array $schema Schema.
- * @param WP_Widget_Media_Video $widget Widget.
- * @return array
- */
- public function filter_instance_schema( $schema, $widget ) {
- // Override the default loop value (false).
- $schema['loop']['default'] = true;
- return $schema;
- }
-
- /**
- * Test constructor.
- *
- * @covers WP_Widget_Media_Video::__construct
- */
- function test_constructor() {
- $widget = new WP_Widget_Media_Video();
-
- $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
- $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
- $this->assertArrayHasKey( 'description', $widget->widget_options );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- $this->assertSame( 'video', $widget->widget_options['mime_type'] );
- $this->assertSameSets(
- array(
- 'add_to_widget',
- 'replace_media',
- 'unsupported_file_type',
- 'edit_media',
- 'media_library_state_multi',
- 'media_library_state_single',
- 'missing_attachment',
- 'no_media_selected',
- 'add_media',
- ),
- array_keys( $widget->l10n )
- );
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media_Video::update
- */
- function test_update() {
- $widget = new WP_Widget_Media_Video();
- $instance = array();
-
- // Should return valid attachment ID.
- $expected = array(
- 'attachment_id' => 1,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment ID.
- $result = $widget->update(
- array(
- 'attachment_id' => 'media',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment url.
- $expected = array(
- 'url' => 'https://chickenandribs.org',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment url.
- $result = $widget->update(
- array(
- 'url' => 'not_a_url',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
- $this->assertStringStartsWith( 'http://', $result['url'] );
-
- // Should return loop setting.
- $expected = array(
- 'loop' => true,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid loop setting.
- $result = $widget->update(
- array(
- 'loop' => 'not-boolean',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment title.
- $expected = array(
- 'title' => 'A video of goats',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment title.
- $result = $widget->update(
- array(
- 'title' => '<h1>Cute Baby Goats</h1>',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should return valid preload setting.
- $expected = array(
- 'preload' => 'none',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid preload setting.
- $result = $widget->update(
- array(
- 'preload' => 'nope',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should filter invalid key.
- $result = $widget->update(
- array(
- 'h4x' => 'value',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
- }
-
- /**
- * Test render_media method.
- *
- * @covers WP_Widget_Media_Video::render_media
- * @covers WP_Widget_Media_Video::inject_video_max_width_style
- */
- function test_render_media() {
- $test_movie_file = __FILE__ . '../../data/uploads/small-video.m4v';
- $widget = new WP_Widget_Media_Video();
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => $test_movie_file,
- 'post_parent' => 0,
- 'post_mime_type' => 'video/mp4',
- 'post_title' => 'Test Video',
- )
- );
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_movie_file ) );
-
- // Should be empty when there is no attachment_id.
- ob_start();
- $widget->render_media( array() );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- // Should be empty when there is an invalid attachment_id.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => 777,
- )
- );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
-
- // Tests with video from library.
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- )
- );
- $output = ob_get_clean();
-
- // Check default outputs.
- $this->assertStringContainsString( 'preload="metadata"', $output );
- $this->assertStringContainsString( 'class="wp-video"', $output );
- $this->assertStringContainsString( 'width:100%', $output );
- $this->assertStringNotContainsString( 'height=', $output );
- $this->assertStringNotContainsString( 'width="', $output );
- $this->assertStringContainsString( 'small-video.m4v', $output );// Auto parses dimensions.
-
- ob_start();
- $widget->render_media(
- array(
- 'attachment_id' => $attachment_id,
- 'title' => 'Open Source Cartoon',
- 'preload' => 'metadata',
- 'loop' => true,
- )
- );
- $output = ob_get_clean();
-
- // Custom attributes.
- $this->assertStringContainsString( 'preload="metadata"', $output );
- $this->assertStringContainsString( 'loop="1"', $output );
-
- // Externally hosted video.
- ob_start();
- $content = '<track srclang="en" label="English" kind="subtitles" src="http://example.com/wp-content/uploads/2017/04/subtitles-en.vtt">';
- $widget->render_media(
- array(
- 'attachment_id' => null,
- 'loop' => false,
- 'url' => 'https://www.youtube.com/watch?v=72xdCU__XCk',
- 'content' => $content,
- )
- );
- $output = ob_get_clean();
-
- // Custom attributes.
- $this->assertStringContainsString( 'preload="metadata"', $output );
- $this->assertStringContainsString( 'src="https://www.youtube.com/watch?v=72xdCU__XCk', $output );
- $this->assertStringContainsString( $content, $output );
- }
-
- /**
- * Test enqueue_preview_scripts method.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- * @covers WP_Widget_Media_Video::enqueue_preview_scripts
- */
- function test_enqueue_preview_scripts() {
- global $wp_scripts, $wp_styles;
- $widget = new WP_Widget_Media_Video();
-
- $wp_scripts = null;
- $wp_styles = null;
- $widget->enqueue_preview_scripts();
- $this->assertTrue( wp_script_is( 'wp-mediaelement' ) );
- $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
- $this->assertTrue( wp_script_is( 'mediaelement-vimeo' ) );
-
- $wp_scripts = null;
- $wp_styles = null;
- add_filter( 'wp_video_shortcode_library', '__return_empty_string' );
- $widget->enqueue_preview_scripts();
- $this->assertFalse( wp_script_is( 'wp-mediaelement' ) );
- $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
- $this->assertFalse( wp_script_is( 'mediaelement-vimeo' ) );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Media_Video::enqueue_admin_scripts
- */
- function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Media_Video();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'media-video-widget' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Media_Video::render_control_template_scripts
- */
- function test_render_control_template_scripts() {
- $widget = new WP_Widget_Media_Video();
-
- ob_start();
- $widget->render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-video-preview">', $output );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetsmediawidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/media-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/media-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/media-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,525 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Media functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Class Test_WP_Widget_Media
- *
- * @group widgets
- */
-class Test_WP_Widget_Media extends WP_UnitTestCase {
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- */
- function clean_up_global_scope() {
- global $wp_scripts, $wp_styles;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- }
-
- /**
- * Get instance for mocked media widget class.
- *
- * @param string $id_base Base ID for the widget, lowercase and unique.
- * @param string $name Name for the widget displayed on the configuration page.
- * @param array $widget_options Optional. Widget options.
- * @param array $control_options Optional. Widget control options.
- * @return PHPUnit_Framework_MockObject_MockObject|WP_Widget_Media Mocked instance.
- */
- function get_mocked_class_instance( $id_base = 'mocked', $name = 'Mocked', $widget_options = array(), $control_options = array() ) {
- $original_class_name = 'WP_Widget_Media';
- $arguments = array( $id_base, $name, $widget_options, $control_options );
- $mock_class_name = '';
- $call_original_constructor = true;
- $call_original_clone = true;
- $call_autoload = true;
- $mocked_methods = array( 'render_media' );
-
- return $this->getMockForAbstractClass( $original_class_name, $arguments, $mock_class_name, $call_original_constructor, $call_original_clone, $call_autoload, $mocked_methods );
- }
-
- /**
- * Test constructor.
- *
- * @covers WP_Widget_Media::__construct
- * @covers WP_Widget_Media::_register
- */
- function test_constructor() {
- $widget = $this->get_mocked_class_instance();
- $widget->_register();
-
- $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
- $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
- $this->assertArrayHasKey( 'description', $widget->widget_options );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- $this->assertEmpty( $widget->widget_options['mime_type'] );
- $this->assertSameSets(
- array(
- 'add_to_widget',
- 'replace_media',
- 'edit_media',
- 'media_library_state_multi',
- 'media_library_state_single',
- 'missing_attachment',
- 'no_media_selected',
- 'add_media',
- 'unsupported_file_type',
- ),
- array_keys( $widget->l10n )
- );
- $this->assertSame( count( $widget->l10n ), count( array_filter( $widget->l10n ) ), 'Expected all translation strings to be defined.' );
- $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
- $this->assertFalse( has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ), 'Did not expect preview scripts to be enqueued when not in customize preview context.' );
- $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( $widget, 'render_control_template_scripts' ) ) );
-
- // With non-default args.
- $id_base = 'media_pdf';
- $name = 'PDF';
- $widget_options = array(
- 'mime_type' => 'application/pdf',
- );
- $control_options = array(
- 'width' => 850,
- 'height' => 1100,
- );
- $widget = $this->get_mocked_class_instance( $id_base, $name, $widget_options, $control_options );
- $this->assertSame( $id_base, $widget->id_base );
- $this->assertSame( $name, $widget->name );
-
- $this->assertArraySubset( $widget_options, $widget->widget_options );
- $this->assertArraySubset( $control_options, $widget->control_options );
- }
-
- /**
- * Test constructor in customize preview.
- *
- * @global WP_Customize_Manager $wp_customize
- * @covers WP_Widget_Media::__construct
- * @covers WP_Widget_Media::_register
- */
- function test_constructor_in_customize_preview() {
- global $wp_customize;
- wp_set_current_user(
- $this->factory()->user->create(
- array(
- 'role' => 'administrator',
- )
- )
- );
- require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
- $wp_customize = new WP_Customize_Manager(
- array(
- 'changeset_uuid' => wp_generate_uuid4(),
- )
- );
- $wp_customize->start_previewing_theme();
-
- $widget = $this->get_mocked_class_instance();
- $widget->_register();
- $this->assertSame( 10, has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
- }
-
- /**
- * Test is_attachment_with_mime_type method.
- *
- * @covers WP_Widget_Media::is_attachment_with_mime_type
- * @requires function imagejpeg
- */
- function test_is_attachment_with_mime_type() {
-
- $test_image = get_temp_dir() . 'canola.jpg';
- copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => $test_image,
- 'post_parent' => 0,
- 'post_mime_type' => 'image/jpeg',
- 'post_title' => 'Canola',
- )
- );
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
- $widget = $this->get_mocked_class_instance();
-
- $this->assertFalse( $widget->is_attachment_with_mime_type( 0, 'image' ) );
- $this->assertFalse( $widget->is_attachment_with_mime_type( -123, 'image' ) );
-
- $post_id = $this->factory()->post->create();
- $this->assertFalse( $widget->is_attachment_with_mime_type( $post_id, 'image' ) );
- $this->assertFalse( $widget->is_attachment_with_mime_type( $attachment_id, 'video' ) );
- $this->assertTrue( $widget->is_attachment_with_mime_type( $attachment_id, 'image' ) );
- }
-
- /**
- * Test sanitize_token_list method.
- *
- * @covers WP_Widget_Media::sanitize_token_list
- */
- function test_sanitize_token_list_string() {
- $widget = $this->get_mocked_class_instance();
-
- $result = $widget->sanitize_token_list( 'What A false class with-token <a href="#">and link</a>' );
- $this->assertSame( 'What A false class with-token a hrefand linka', $result );
-
- $result = $widget->sanitize_token_list( array( 'foo', '<i>bar', '">NO' ) );
- $this->assertSame( $result, 'foo ibar NO' );
- }
-
- /**
- * Instance schema args.
- *
- * @var array
- */
- protected $filter_instance_schema_args;
-
- /**
- * Filter instance schema.
- *
- * @param array $schema Schema.
- * @param WP_Widget_Media $widget Widget.
- * @return array
- */
- public function filter_instance_schema( $schema, $widget ) {
- $this->filter_instance_schema_args = compact( 'schema', 'widget' );
- $schema['injected'] = array(
- 'type' => 'boolean',
- );
- return $schema;
- }
-
- /**
- * Test get_instance_schema method.
- *
- * @covers WP_Widget_Media::get_instance_schema
- */
- function test_get_instance_schema() {
- $widget = $this->get_mocked_class_instance();
- $schema = $widget->get_instance_schema();
-
- $this->assertSameSets(
- array(
- 'attachment_id',
- 'title',
- 'url',
- ),
- array_keys( $schema )
- );
-
- // Check filter usage.
- $this->filter_instance_schema_args = null;
- add_filter( 'widget_mocked_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
- $schema = $widget->get_instance_schema();
- $this->assertIsArray( $this->filter_instance_schema_args );
- $this->assertSame( $widget, $this->filter_instance_schema_args['widget'] );
- $this->assertSameSets( array( 'attachment_id', 'title', 'url' ), array_keys( $this->filter_instance_schema_args['schema'] ) );
- $this->assertArrayHasKey( 'injected', $schema );
- }
-
- /**
- * Test update method.
- *
- * @covers WP_Widget_Media::update
- */
- function test_update() {
- $widget = $this->get_mocked_class_instance();
- $instance = array();
-
- // Should return valid attachment ID.
- $expected = array(
- 'attachment_id' => 1,
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment ID.
- $result = $widget->update(
- array(
- 'attachment_id' => 'media',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- // Should return valid attachment url.
- $expected = array(
- 'url' => 'https://example.org',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment url.
- $result = $widget->update(
- array(
- 'url' => 'not_a_url',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should return valid attachment title.
- $expected = array(
- 'title' => 'What a title',
- );
- $result = $widget->update( $expected, $instance );
- $this->assertSame( $result, $expected );
-
- // Should filter invalid attachment title.
- $result = $widget->update(
- array(
- 'title' => '<h1>W00t!</h1>',
- ),
- $instance
- );
- $this->assertNotSame( $result, $instance );
-
- // Should filter invalid key.
- $result = $widget->update(
- array(
- 'imaginary_key' => 'value',
- ),
- $instance
- );
- $this->assertSame( $result, $instance );
-
- add_filter( 'sanitize_text_field', array( $this, '_return_wp_error' ) );
- $result = $widget->update(
- array(
- 'title' => 'Title',
- ),
- $instance
- );
- remove_filter( 'sanitize_text_field', array( $this, '_return_wp_error' ) );
- $this->assertSame( $result, $instance );
- }
-
- /**
- * Helper function for Test_WP_Widget_Media::test_update().
- *
- * @return \WP_Error
- */
- function _return_wp_error() {
- return new WP_Error( 'some-error', 'This is not valid!' );
- }
-
- /**
- * Test widget method.
- *
- * @covers WP_Widget_Media::widget
- * @covers WP_Widget_Media::render_media
- */
- function test_widget() {
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => "</h2>\n",
- 'before_widget' => '<section>',
- 'after_widget' => "</section>\n",
- );
- $instance = array(
- 'title' => 'Foo',
- 'url' => 'http://example.com/image.jpg',
- 'attachment_id' => 0,
- );
-
- add_filter( 'widget_mocked_instance', array( $this, 'filter_widget_mocked_instance' ), 10, 3 );
-
- ob_start();
- $widget = $this->get_mocked_class_instance();
- $widget->expects( $this->atLeastOnce() )->method( 'render_media' )->with( $instance );
- $this->widget_instance_filter_args = array();
- $widget->widget( $args, $instance );
- $this->assertCount( 3, $this->widget_instance_filter_args );
- $this->assertEquals( $instance, $this->widget_instance_filter_args[0] );
- $this->assertSame( $args, $this->widget_instance_filter_args[1] );
- $this->assertSame( $widget, $this->widget_instance_filter_args[2] );
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<h2>Foo</h2>', $output );
- $this->assertStringContainsString( '<section>', $output );
- $this->assertStringContainsString( '</section>', $output );
-
- // No title.
- ob_start();
- $widget = $this->get_mocked_class_instance();
- $instance['title'] = '';
- $widget->expects( $this->atLeastOnce() )->method( 'render_media' )->with( $instance );
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringNotContainsString( '<h2>Foo</h2>', $output );
-
- // No attachment_id nor url.
- $instance['url'] = '';
- $instance['attachment_id'] = 0;
- ob_start();
- $widget = $this->get_mocked_class_instance();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertEmpty( $output );
- }
-
- /**
- * Args passed to the widget_{$id_base}_instance filter.
- *
- * @var array
- */
- protected $widget_instance_filter_args = array();
-
- /**
- * Filters the media widget instance prior to rendering the media.
- *
- * @param array $instance Instance data.
- * @param array $args Widget args.
- * @param WP_Widget_Media $object Widget object.
- * @return array Instance.
- */
- function filter_widget_mocked_instance( $instance, $args, $object ) {
- $this->widget_instance_filter_args = func_get_args();
- return $instance;
- }
-
- /**
- * Test form method.
- *
- * @covers WP_Widget_Media::form
- */
- function test_form() {
- $widget = $this->get_mocked_class_instance();
-
- ob_start();
- $widget->form( array() );
- $output = ob_get_clean();
-
- $this->assertStringContainsString( 'name="widget-mocked[][attachment_id]"', $output );
- $this->assertStringContainsString( 'name="widget-mocked[][title]"', $output );
- $this->assertStringContainsString( 'name="widget-mocked[][url]"', $output );
- }
-
- /**
- * Test display_media_state method.
- *
- * @covers WP_Widget_Media::display_media_state
- */
- function test_display_media_state() {
- $widget = $this->get_mocked_class_instance();
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => DIR_TESTDATA . '/images/canola.jpg',
- 'post_parent' => 0,
- 'post_mime_type' => 'image/jpeg',
- )
- );
-
- $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
- $this->assertSameSets( array(), $result );
-
- $widget->save_settings(
- array(
- array(
- 'attachment_id' => $attachment_id,
- ),
- )
- );
- $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
- $this->assertSameSets( array( $widget->l10n['media_library_state_single'] ), $result );
-
- $widget->save_settings(
- array(
- array(
- 'attachment_id' => $attachment_id,
- ),
- array(
- 'attachment_id' => $attachment_id,
- ),
- )
- );
- $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
- $this->assertSameSets( array( sprintf( $widget->l10n['media_library_state_multi']['singular'], 2 ) ), $result );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Media::enqueue_admin_scripts
- */
- function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = $this->get_mocked_class_instance();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'media-widgets' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Media::render_control_template_scripts
- */
- function test_render_control_template_scripts() {
- $widget = $this->get_mocked_class_instance();
-
- ob_start();
- $widget->render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-media-mocked-control">', $output );
- }
-
- /**
- * Test has_content method.
- *
- * @covers WP_Widget_Media::has_content
- */
- function test_has_content() {
- $attachment_id = self::factory()->attachment->create_object(
- array(
- 'file' => DIR_TESTDATA . '/images/canola.jpg',
- 'post_parent' => 0,
- 'post_mime_type' => 'image/jpeg',
- )
- );
-
- $wp_widget_media = new ReflectionClass( 'WP_Widget_Media' );
- $has_content = $wp_widget_media->getMethod( 'has_content' );
- $has_content->setAccessible( true );
-
- $result = $has_content->invokeArgs(
- $this->get_mocked_class_instance(),
- array(
- array(
- 'attachment_id' => 0,
- 'url' => '',
- ),
- )
- );
- $this->assertFalse( $result );
-
- $result = $has_content->invokeArgs(
- $this->get_mocked_class_instance(),
- array(
- array(
- 'attachment_id' => $attachment_id,
- 'url' => '',
- ),
- )
- );
- $this->assertTrue( $result );
-
- $result = $has_content->invokeArgs(
- $this->get_mocked_class_instance(),
- array(
- array(
- 'attachment_id' => 0,
- 'url' => 'http://example.com/image.jpg',
- ),
- )
- );
- $this->assertTrue( $result );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetstextwidgetphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/widgets/text-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/text-widget.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/text-widget.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,1058 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Unit tests covering WP_Widget_Text functionality.
- *
- * @package WordPress
- * @subpackage widgets
- */
-
-/**
- * Test wp-includes/widgets/class-wp-widget-text.php
- *
- * @group widgets
- */
-class Test_WP_Widget_Text extends WP_UnitTestCase {
- /**
- * Args passed to the widget_text filter.
- *
- * @var array
- */
- protected $widget_text_args;
-
- /**
- * Args passed to the widget_text_content filter.
- *
- * @var array
- */
- protected $widget_text_content_args;
-
- /**
- * Clean up global scope.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_style
- * @global WP_Customize_Manager $wp_customize
- */
- function clean_up_global_scope() {
- global $wp_scripts, $wp_styles, $wp_customize;
- parent::clean_up_global_scope();
- $wp_scripts = null;
- $wp_styles = null;
- $wp_customize = null;
- }
-
- /**
- * Test constructor method.
- *
- * @covers WP_Widget_Text::__construct
- */
- function test_construct() {
- $widget = new WP_Widget_Text();
- $this->assertSame( 'text', $widget->id_base );
- $this->assertSame( 'widget_text', $widget->widget_options['classname'] );
- $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
- $this->assertSame( 400, $widget->control_options['width'] );
- $this->assertSame( 350, $widget->control_options['height'] );
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Text::_register
- */
- function test__register() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Text();
- $widget->_register();
-
- $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
- $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( 'WP_Widget_Text', 'render_control_template_scripts' ) ) );
- $this->assertContains( 'wp.textWidgets.idBases.push( "text" );', wp_scripts()->registered['text-widgets']->extra['after'] );
- $this->assertFalse( has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
- }
-
- /**
- * Test register in customize preview.
- *
- * @global WP_Customize_Manager $wp_customize
- * @covers WP_Widget_Text::__construct
- * @covers WP_Widget_Text::_register
- */
- function test__register_in_customize_preview() {
- global $wp_customize;
- wp_set_current_user(
- $this->factory()->user->create(
- array(
- 'role' => 'administrator',
- )
- )
- );
- require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
- $wp_customize = new WP_Customize_Manager(
- array(
- 'changeset_uuid' => wp_generate_uuid4(),
- )
- );
- $wp_customize->start_previewing_theme();
-
- $widget = new WP_Widget_Text();
- $widget->_register();
- $this->assertSame( 10, has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
- }
-
- /**
- * Test enqueue_preview_scripts method.
- *
- * @global WP_Scripts $wp_scripts
- * @global WP_Styles $wp_styles
- * @covers WP_Widget_Text::enqueue_preview_scripts
- */
- function test_enqueue_preview_scripts() {
- global $wp_scripts, $wp_styles;
- $wp_scripts = null;
- $wp_styles = null;
- $widget = new WP_Widget_Text();
-
- $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
- $this->assertFalse( wp_script_is( 'wp-playlist' ) );
-
- ob_start();
- $widget->enqueue_preview_scripts();
- ob_end_clean();
-
- $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
- $this->assertTrue( wp_script_is( 'wp-playlist' ) );
- }
-
- /**
- * Test widget method.
- *
- * @covers WP_Widget_Text::widget
- */
- function test_widget() {
- $widget = new WP_Widget_Text();
- $text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n Praesent ut turpis consequat lorem volutpat bibendum vitae vitae ante.";
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => "</h2>\n",
- 'before_widget' => '<section>',
- 'after_widget' => "</section>\n",
- );
-
- add_filter( 'widget_text_content', array( $this, 'filter_widget_text_content' ), 5, 3 );
- add_filter( 'widget_text', array( $this, 'filter_widget_text' ), 5, 3 );
-
- // Test with filter=false, implicit legacy mode.
- $this->widget_text_content_args = null;
- ob_start();
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => false,
- );
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringNotContainsString( '<p>', $output );
- $this->assertStringNotContainsString( '<br />', $output );
- $this->assertEmpty( $this->widget_text_content_args );
- $this->assertNotEmpty( $this->widget_text_args );
- $this->assertStringContainsString( '[filter:widget_text]', $output );
- $this->assertStringNotContainsString( '[filter:widget_text_content]', $output );
-
- // Test with filter=true, implicit legacy mode.
- $this->widget_text_content_args = null;
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => true,
- );
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringContainsString( '<p>', $output );
- $this->assertStringContainsString( '<br />', $output );
- $this->assertNotEmpty( $this->widget_text_args );
- $this->assertSame( $instance['text'], $this->widget_text_args[0] );
- $this->assertSame( $instance, $this->widget_text_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertEmpty( $this->widget_text_content_args );
- $this->assertStringContainsString( '[filter:widget_text]', $output );
- $this->assertStringNotContainsString( '[filter:widget_text_content]', $output );
-
- // Test with filter=content, the upgraded widget, in 4.8.0 only.
- $this->widget_text_content_args = null;
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => 'content',
- );
- $expected_instance = array_merge(
- $instance,
- array(
- 'filter' => true,
- 'visual' => true,
- )
- );
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringContainsString( '<p>', $output );
- $this->assertStringContainsString( '<br />', $output );
- $this->assertCount( 3, $this->widget_text_args );
- $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertCount( 3, $this->widget_text_content_args );
- $this->assertSame( $expected_instance['text'] . '[filter:widget_text]', $this->widget_text_content_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_content_args[1] );
- $this->assertSame( $widget, $this->widget_text_content_args[2] );
- $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text][filter:widget_text_content]' ), $output );
-
- // Test with filter=true&visual=true, the upgraded widget, in 4.8.1 and above.
- $this->widget_text_content_args = null;
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => true,
- 'visual' => true,
- );
- $expected_instance = $instance;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringContainsString( '<p>', $output );
- $this->assertStringContainsString( '<br />', $output );
- $this->assertCount( 3, $this->widget_text_args );
- $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertCount( 3, $this->widget_text_content_args );
- $this->assertSame( $expected_instance['text'] . '[filter:widget_text]', $this->widget_text_content_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_content_args[1] );
- $this->assertSame( $widget, $this->widget_text_content_args[2] );
- $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text][filter:widget_text_content]' ), $output );
-
- // Test with filter=true&visual=true, the upgraded widget, in 4.8.1 and above.
- $this->widget_text_content_args = null;
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => true,
- 'visual' => false,
- );
- $expected_instance = $instance;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringContainsString( '<p>', $output );
- $this->assertStringContainsString( '<br />', $output );
- $this->assertCount( 3, $this->widget_text_args );
- $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertNull( $this->widget_text_content_args );
- $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text]' ), $output );
-
- // Test with filter=false&visual=false, the upgraded widget, in 4.8.1 and above.
- $this->widget_text_content_args = null;
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- 'filter' => false,
- 'visual' => false,
- );
- $expected_instance = $instance;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertStringNotContainsString( '<p>', $output );
- $this->assertStringNotContainsString( '<br />', $output );
- $this->assertCount( 3, $this->widget_text_args );
- $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
- $this->assertSame( $expected_instance, $this->widget_text_args[1] );
- $this->assertSame( $widget, $this->widget_text_args[2] );
- $this->assertNull( $this->widget_text_content_args );
- $this->assertStringContainsString( $expected_instance['text'] . '[filter:widget_text]', $output );
- }
-
- /**
- * Example shortcode content to test for wpautop corruption.
- *
- * @var string
- */
- protected $example_shortcode_content = "<p class='sortcodep'>One\nTwo\n\nThree\n\nThis is testing the <code>[example note='This will not get processed since it is part of shortcode output itself.']</code> shortcode.</p>\n<script>\ndocument.write('Test1');\n\ndocument.write('Test2');\n</script>";
-
- /**
- * The captured global post during shortcode rendering.
- *
- * @var WP_Post|null
- */
- protected $post_during_shortcode = null;
-
- /**
- * Number of times the shortcode was rendered.
- *
- * @var int
- */
- protected $shortcode_render_count = 0;
-
- /**
- * Do example shortcode.
- *
- * @return string Shortcode content.
- */
- function do_example_shortcode() {
- $this->post_during_shortcode = get_post();
- $this->shortcode_render_count++;
- return $this->example_shortcode_content;
- }
-
- /**
- * Test widget method with shortcodes.
- *
- * @covers WP_Widget_Text::widget
- */
- function test_widget_shortcodes() {
- global $post;
- $post_id = $this->factory()->post->create();
- $post = get_post( $post_id );
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => "</h2>\n",
- 'before_widget' => '<section>',
- 'after_widget' => "</section>\n",
- );
- $widget = new WP_Widget_Text();
- add_shortcode( 'example', array( $this, 'do_example_shortcode' ) );
-
- $base_instance = array(
- 'title' => 'Example',
- 'text' => "This is an example:\n\n[example]\n\nHello.",
- 'filter' => false,
- );
-
- // Legacy Text Widget without wpautop().
- $instance = array_merge(
- $base_instance,
- array(
- 'filter' => false,
- )
- );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 1, $this->shortcode_render_count );
- $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
- $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
- $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
- $this->assertNull( $this->post_during_shortcode );
-
- // Legacy Text Widget with wpautop().
- $instance = array_merge(
- $base_instance,
- array(
- 'filter' => true,
- 'visual' => false,
- )
- );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 1, $this->shortcode_render_count );
- $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
- $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
- $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
- $this->assertNull( $this->post_during_shortcode );
-
- // Legacy text widget with plugin adding shortcode support as well.
- add_filter( 'widget_text', 'do_shortcode' );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 1, $this->shortcode_render_count );
- $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
- $this->assertStringContainsString( wpautop( $this->example_shortcode_content ), $output, 'Shortcode was applied *with* wpautop() applying to shortcode output since plugin used legacy filter.' );
- $this->assertNull( $this->post_during_shortcode );
- remove_filter( 'widget_text', 'do_shortcode' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'filter' => true,
- 'visual' => true,
- )
- );
-
- // Visual Text Widget with only core-added widget_text_content filter for do_shortcode().
- $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ) );
- $this->assertSame( 11, has_filter( 'widget_text_content', 'do_shortcode' ), 'Expected core to have set do_shortcode as widget_text_content filter.' );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 1, $this->shortcode_render_count );
- $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
- $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
- $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ), 'The widget_text filter still lacks do_shortcode handler.' );
- $this->assertSame( 11, has_filter( 'widget_text_content', 'do_shortcode' ), 'The widget_text_content filter still has do_shortcode handler.' );
- $this->assertNull( $this->post_during_shortcode );
-
- // Visual Text Widget with both filters applied added, one from core and another via plugin.
- add_filter( 'widget_text', 'do_shortcode' );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 1, $this->shortcode_render_count );
- $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
- $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
- $this->assertSame( 10, has_filter( 'widget_text', 'do_shortcode' ), 'Expected do_shortcode to be restored to widget_text.' );
- $this->assertNull( $this->post_during_shortcode );
- $this->assertNull( $this->post_during_shortcode );
- remove_filter( 'widget_text', 'do_shortcode' );
-
- // Visual Text Widget with shortcode handling disabled via plugin removing filter.
- remove_filter( 'widget_text_content', 'do_shortcode', 11 );
- remove_filter( 'widget_text', 'do_shortcode' );
- $this->shortcode_render_count = 0;
- ob_start();
- $widget->widget( $args, $instance );
- $output = ob_get_clean();
- $this->assertSame( 0, $this->shortcode_render_count );
- $this->assertStringContainsString( '[example]', $output );
- $this->assertStringNotContainsString( $this->example_shortcode_content, $output );
- $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ) );
- $this->assertFalse( has_filter( 'widget_text_content', 'do_shortcode' ) );
- }
-
- /**
- * Filters the content of the Text widget.
- *
- * @param string $widget_text The widget content.
- * @param array $instance Array of settings for the current widget.
- * @param WP_Widget_Text $widget Current Text widget instance.
- * @return string Widget text.
- */
- function filter_widget_text( $widget_text, $instance, $widget ) {
- $this->widget_text_args = func_get_args();
-
- $widget_text .= '[filter:widget_text]';
- return $widget_text;
- }
-
- /**
- * Filters the content of the Text widget to apply changes expected from the visual (TinyMCE) editor.
- *
- * @param string $widget_text The widget content.
- * @param array $instance Array of settings for the current widget.
- * @param WP_Widget_Text $widget Current Text widget instance.
- * @return string Widget content.
- */
- function filter_widget_text_content( $widget_text, $instance, $widget ) {
- $this->widget_text_content_args = func_get_args();
-
- $widget_text .= '[filter:widget_text_content]';
- return $widget_text;
- }
-
- /**
- * Test is_legacy_instance method.
- *
- * @covers WP_Widget_Text::is_legacy_instance
- */
- function test_is_legacy_instance() {
- $widget = new WP_Widget_Text();
- $base_instance = array(
- 'title' => 'Title',
- 'text' => "Hello\n\nWorld",
- );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'visual' => false,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when visual=false prop is present.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'visual' => true,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when visual=true prop is present.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'filter' => 'content',
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when filter is explicitly content (in WP 4.8.0 only).' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => '',
- 'filter' => true,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when text is empty.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "\nOne line",
- 'filter' => false,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when there is leading whitespace.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "\nOne line\n\n",
- 'filter' => false,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when there is trailing whitespace.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "One\nTwo",
- 'filter' => false,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there are line breaks.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "One\n\nTwo",
- 'filter' => false,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there are paragraph breaks.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "One\nTwo",
- 'filter' => true,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not automatically legacy when wpautop and there are line breaks.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => "One\n\nTwo",
- 'filter' => true,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not automatically legacy when wpautop and there are paragraph breaks.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => 'Test<!-- comment -->',
- 'filter' => true,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when HTML comment is present.' );
-
- // Check text examples that will not migrate to TinyMCE.
- $legacy_text_examples = array(
- '<span class="hello"></span>',
- '<blockquote>Quote <footer>Citation</footer></blockquote>',
- '<img src=\"http://example.com/img.jpg\" border=\"0\" title=\"Example\" /></a>',
- '<span></span>',
- "<ul>\n<li><a href=\"#\" class=\"location\"></a>List Item 1</li>\n<li><a href=\"#\" class=\"location\"></a>List Item 2</li>\n</ul>",
- '<a href="#" class="map"></a>',
- "<script>\n\\Line one\n\n\\Line two</script>",
- "<style>body {\ncolor:red;\n}</style>",
- '<span class="fa fa-cc-discover fa-2x" aria-hidden="true"></span>',
- "<p>\nStay updated with our latest news and specials. We never sell your information and you can unsubscribe at any time.\n</p>\n\n<div class=\"custom-form-class\">\n\t<form action=\"#\" method=\"post\" name=\"mc-embedded-subscribe-form\">\n\n\t\t<label class=\"screen-reader-text\" for=\"mce-EMAIL-b\">Email </label>\n\t\t<input id=\"mce-EMAIL-b\" class=\"required email\" name=\"EMAIL\" required=\"\" type=\"email\" value=\"\" placeholder=\"Email Address*\" />\n\n\t\t<input class=\"button\" name=\"subscribe\" type=\"submit\" value=\"Go!\" />\n\n\t</form>\n</div>",
- '<span class="sectiondown"><a href="#front-page-3"><i class="fa fa-chevron-circle-down"></i></a></span>',
- );
- foreach ( $legacy_text_examples as $legacy_text_example ) {
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => $legacy_text_example,
- 'filter' => true,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when wpautop and there is HTML that is not liable to be mutated.' );
-
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => $legacy_text_example,
- 'filter' => false,
- )
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there is HTML that is not liable to be mutated.' );
- }
-
- // Check text examples that will migrate to TinyMCE, where elements and attributes are not in the allowed list.
- $migratable_text_examples = array(
- 'Check out <a href="http://example.com">Example</a>',
- '<img src="http://example.com/img.jpg" alt="Img">',
- '<strong><em>Hello</em></strong>',
- '<b><i><u><s>Hello</s></u></i></b>',
- "<ul>\n<li>One</li>\n<li>One</li>\n<li>One</li>\n</ul>",
- "<ol>\n<li>One</li>\n<li>One</li>\n<li>One</li>\n</ol>",
- "Text\n<hr>\nAddendum",
- "Look at this code:\n\n<code>echo 'Hello World!';</code>",
- );
- foreach ( $migratable_text_examples as $migratable_text_example ) {
- $instance = array_merge(
- $base_instance,
- array(
- 'text' => $migratable_text_example,
- 'filter' => true,
- )
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Legacy when wpautop and there is HTML that is not liable to be mutated.' );
- }
- }
-
- /**
- * Test update method.
- *
- * @covers WP_Widget_Text::form
- */
- function test_form() {
- add_filter( 'user_can_richedit', '__return_true' );
- $widget = new WP_Widget_Text();
- $widget->_set( 2 );
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => false,
- 'visual' => false,
- );
- $this->assertTrue( $widget->is_legacy_instance( $instance ) );
- ob_start();
- $widget->form( $instance );
- $form = ob_get_clean();
- $this->assertStringContainsString( 'class="visual" type="hidden" value=""', $form );
- $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
-
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => 'content',
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ) );
- ob_start();
- $widget->form( $instance );
- $form = ob_get_clean();
- $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
- $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
-
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => true,
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ) );
- ob_start();
- $widget->form( $instance );
- $form = ob_get_clean();
- $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
- $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
-
- $instance = array(
- 'title' => 'Title',
- 'text' => 'This is some HTML Code: <code><strong>BOLD!</strong></code>',
- 'filter' => true,
- 'visual' => true,
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ) );
- ob_start();
- $widget->form( $instance );
- $form = ob_get_clean();
- $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
- $this->assertStringContainsString( '<code>&lt;strong&gt;BOLD!', $form );
- $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
-
- remove_filter( 'user_can_richedit', '__return_true' );
- add_filter( 'user_can_richedit', '__return_false' );
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Evil:</textarea><script>alert("XSS")</script>',
- 'filter' => true,
- 'visual' => true,
- );
- $this->assertFalse( $widget->is_legacy_instance( $instance ) );
- ob_start();
- $widget->form( $instance );
- $form = ob_get_clean();
- $this->assertStringNotContainsString( 'Evil:</textarea>', $form );
- $this->assertStringContainsString( 'Evil:</textarea>', $form );
- }
-
- /**
- * Test update method.
- *
- * @covers WP_Widget_Text::update
- */
- function test_update() {
- $widget = new WP_Widget_Text();
- $instance = array(
- 'title' => "The\nTitle",
- 'text' => "The\n\nText",
- 'filter' => true,
- 'visual' => true,
- );
-
- wp_set_current_user(
- $this->factory()->user->create(
- array(
- 'role' => 'administrator',
- )
- )
- );
-
- $expected = array(
- 'title' => sanitize_text_field( $instance['title'] ),
- 'text' => $instance['text'],
- 'filter' => true,
- 'visual' => true,
- );
- $result = $widget->update( $instance, array() );
- $this->assertSame( $expected, $result );
- $this->assertNotEmpty( $expected['filter'], 'Expected filter prop to be truthy, to handle case where 4.8 is downgraded to 4.7.' );
-
- add_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ), 10, 2 );
- $this->assertTrue( current_user_can( 'unfiltered_html' ) );
- $instance['text'] = '<script>alert( "Howdy!" );</script>';
- $expected['text'] = $instance['text'];
- $result = $widget->update( $instance, array() );
- $this->assertSame( $expected, $result, 'KSES should apply as expected.' );
- remove_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ) );
-
- add_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
- $this->assertFalse( current_user_can( 'unfiltered_html' ) );
- $instance['text'] = '<script>alert( "Howdy!" );</script>';
- $expected['text'] = wp_kses_post( $instance['text'] );
- $result = $widget->update( $instance, array() );
- $this->assertSame( $expected, $result, 'KSES should not apply since user can unfiltered_html.' );
- remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10 );
- }
-
- /**
- * Test update for legacy widgets.
- *
- * @covers WP_Widget_Text::update
- */
- function test_update_legacy() {
- $widget = new WP_Widget_Text();
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'filter' => false,
- );
- $result = $widget->update( $instance, array() );
- $this->assertSameSets( $instance, $result, 'Updating a widget without visual prop and explicit filter=false leaves visual prop absent' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'filter' => true,
- );
- $result = $widget->update( $instance, array() );
- $this->assertSameSets( $instance, $result, 'Updating a widget without visual prop and explicit filter=true leaves legacy prop absent.' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'visual' => true,
- );
- $old_instance = array_merge(
- $instance,
- array(
- 'filter' => false,
- )
- );
- $expected = array_merge(
- $instance,
- array(
- 'filter' => true,
- )
- );
- $result = $widget->update( $instance, $old_instance );
- $this->assertSameSets( $expected, $result, 'Updating a pre-existing widget with visual mode forces filter to be true.' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'filter' => true,
- );
- $old_instance = array_merge(
- $instance,
- array(
- 'visual' => true,
- )
- );
- $result = $widget->update( $instance, $old_instance );
- $expected = array_merge(
- $instance,
- array(
- 'visual' => true,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a pre-existing visual widget retains visual mode when updated.' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- );
- $old_instance = array_merge(
- $instance,
- array(
- 'visual' => true,
- )
- );
- $result = $widget->update( $instance, $old_instance );
- $expected = array_merge(
- $instance,
- array(
- 'visual' => true,
- 'filter' => true,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a pre-existing visual widget retains visual=true and supplies missing filter=true.' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'visual' => true,
- );
- $expected = array_merge(
- $instance,
- array(
- 'filter' => true,
- )
- );
- $result = $widget->update( $instance, array() );
- $this->assertSameSets( $expected, $result, 'Updating a widget with explicit visual=true and absent filter prop causes filter to be set to true.' );
-
- // --
- $instance = array(
- 'title' => 'Legacy',
- 'text' => 'Text',
- 'visual' => false,
- );
- $result = $widget->update( $instance, array() );
- $expected = array_merge(
- $instance,
- array(
- 'filter' => false,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a widget in legacy mode results in filter=false as if checkbox not checked.' );
-
- // --
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => false,
- );
- $old_instance = array_merge(
- $instance,
- array(
- 'visual' => false,
- 'filter' => true,
- )
- );
- $result = $widget->update( $instance, $old_instance );
- $expected = array_merge(
- $instance,
- array(
- 'visual' => false,
- 'filter' => false,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a widget that previously had legacy form results in filter allowed to be false.' );
-
- // --
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => 'content',
- );
- $result = $widget->update( $instance, array() );
- $expected = array_merge(
- $instance,
- array(
- 'filter' => true,
- 'visual' => true,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a widget that had \'content\' as its filter value persists non-legacy mode. This only existed in WP 4.8.0.' );
-
- // --
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- );
- $old_instance = array_merge(
- $instance,
- array(
- 'filter' => 'content',
- )
- );
- $result = $widget->update( $instance, $old_instance );
- $expected = array_merge(
- $instance,
- array(
- 'visual' => true,
- 'filter' => true,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a pre-existing widget with the filter=content prop in WP 4.8.0 upgrades to filter=true&visual=true.' );
-
- // --
- $instance = array(
- 'title' => 'Title',
- 'text' => 'Text',
- 'filter' => 'content',
- );
- $result = $widget->update( $instance, array() );
- $expected = array_merge(
- $instance,
- array(
- 'filter' => true,
- 'visual' => true,
- )
- );
- $this->assertSameSets( $expected, $result, 'Updating a widget with filter=content (from WP 4.8.0) upgrades to filter=true&visual=true.' );
- }
-
- /**
- * Grant unfiltered_html cap via map_meta_cap.
- *
- * @param array $caps Returns the user's actual capabilities.
- * @param string $cap Capability name.
- * @return array Caps.
- */
- function grant_unfiltered_html_cap( $caps, $cap ) {
- if ( 'unfiltered_html' === $cap ) {
- $caps = array_diff( $caps, array( 'do_not_allow' ) );
- $caps[] = 'unfiltered_html';
- }
- return $caps;
- }
-
- /**
- * Revoke unfiltered_html cap via map_meta_cap.
- *
- * @param array $caps Returns the user's actual capabilities.
- * @param string $cap Capability name.
- * @return array Caps.
- */
- function revoke_unfiltered_html_cap( $caps, $cap ) {
- if ( 'unfiltered_html' === $cap ) {
- $caps = array_diff( $caps, array( 'unfiltered_html' ) );
- $caps[] = 'do_not_allow';
- }
- return $caps;
- }
-
- /**
- * Test enqueue_admin_scripts method.
- *
- * @covers WP_Widget_Text::enqueue_admin_scripts
- */
- function test_enqueue_admin_scripts() {
- set_current_screen( 'widgets.php' );
- $widget = new WP_Widget_Text();
- $widget->enqueue_admin_scripts();
-
- $this->assertTrue( wp_script_is( 'text-widgets' ) );
- }
-
- /**
- * Test render_control_template_scripts method.
- *
- * @covers WP_Widget_Text::render_control_template_scripts
- */
- function test_render_control_template_scripts() {
- ob_start();
- WP_Widget_Text::render_control_template_scripts();
- $output = ob_get_clean();
-
- $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-text-control-fields">', $output );
- }
-
- /**
- * Ensure that rel="noopener" is added to links with a target.
- *
- * @ticket 46421
- */
- function test_render_links_with_target() {
- $widget = new WP_Widget_Text();
-
- $text = 'Test content with an external <a href="https://example.org" target="_blank">link</a>.';
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => '</h2>',
- 'before_widget' => '',
- 'after_widget' => '',
- );
-
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- );
-
- $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
-
- $this->assertStringContainsString( 'rel="noopener"', $output );
- }
-
- /**
- * Ensure that rel="noopener" is not added to links without a target.
- *
- * @ticket 46421
- */
- function test_render_links_without_target() {
- $widget = new WP_Widget_Text();
-
- $text = 'Test content with an internal <a href="/">link</a>.';
-
- $args = array(
- 'before_title' => '<h2>',
- 'after_title' => '</h2>',
- 'before_widget' => '',
- 'after_widget' => '',
- );
-
- $instance = array(
- 'title' => 'Foo',
- 'text' => $text,
- );
-
- $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
-
- $this->assertStringNotContainsString( 'rel="noopener"', $output );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetCustomHtmlphpfromrev51492trunktestsphpunittestswidgetscustomhtmlwidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetCustomHtml.php (from rev 51492, trunk/tests/phpunit/tests/widgets/custom-html-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetCustomHtml.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetCustomHtml.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,358 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Custom_HTML functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-custom-html.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetCustomHtml extends WP_UnitTestCase {
+
+ /**
+ * Args passed to the widget_custom_html_content filter.
+ *
+ * @var array
+ */
+ protected $widget_custom_html_content_args;
+
+ /**
+ * Args passed to the widget_text filter.
+ *
+ * @var array
+ */
+ protected $widget_text_args;
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_style
+ */
+ public function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Test construct.
+ *
+ * @covers WP_Widget_Custom_HTML::__construct
+ */
+ public function test_construct() {
+ $widget = new WP_Widget_Custom_HTML();
+ $this->assertSame( 'custom_html', $widget->id_base );
+ $this->assertSame( 'widget_custom_html', $widget->widget_options['classname'] );
+ $this->assertSame( 400, $widget->control_options['width'] );
+ $this->assertSame( 350, $widget->control_options['height'] );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Custom_HTML::_register
+ */
+ public function test__register() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Custom_HTML();
+ $widget->_register();
+
+ $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
+ $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( 'WP_Widget_Custom_HTML', 'render_control_template_scripts' ) ) );
+ $this->assertSame( 10, has_action( 'admin_head-widgets.php', array( 'WP_Widget_Custom_HTML', 'add_help_text' ) ) );
+ $this->assertContains( 'wp.customHtmlWidgets.idBases.push( "custom_html" );', wp_scripts()->registered['custom-html-widgets']->extra['after'] );
+ }
+
+ /**
+ * Test widget method.
+ *
+ * @covers WP_Widget_Custom_HTML::widget
+ */
+ public function test_widget() {
+ $widget = new WP_Widget_Custom_HTML();
+ $content = "<i>Custom HTML</i>\n\n<b>CODE</b>\nLast line.<u>unclosed";
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => "</h2>\n",
+ 'before_widget' => '<section id="custom_html-5" class="widget widget_custom_html">',
+ 'after_widget' => "</section>\n",
+ );
+ $instance = array(
+ 'title' => 'Foo',
+ 'content' => $content,
+ );
+
+ // Convert Custom HTML widget instance into Text widget instance data.
+ $text_widget_instance = array_merge(
+ $instance,
+ array(
+ 'text' => $instance['content'],
+ 'filter' => false,
+ 'visual' => false,
+ )
+ );
+ unset( $text_widget_instance['content'] );
+
+ update_option( 'use_balanceTags', 0 );
+ add_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5, 3 );
+ add_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10, 3 );
+ ob_start();
+ $this->widget_custom_html_content_args = null;
+ $this->widget_text_args = null;
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertNotEmpty( $this->widget_custom_html_content_args );
+ $this->assertNotEmpty( $this->widget_text_args );
+ $this->assertStringContainsString( '[filter:widget_text][filter:widget_custom_html_content]', $output );
+ $this->assertStringContainsString( '<section id="custom_html-5" class="widget_text widget widget_custom_html">', $output );
+ $this->assertStringContainsString( '<div class="textwidget custom-html-widget">', $output );
+ $this->assertStringNotContainsString( '<p>', $output );
+ $this->assertStringNotContainsString( '<br>', $output );
+ $this->assertStringNotContainsString( '</u>', $output );
+ $this->assertSame( $text_widget_instance, $this->widget_text_args[1] );
+ $this->assertSame( $instance, $this->widget_custom_html_content_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertSame( $widget, $this->widget_custom_html_content_args[2] );
+ remove_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5 );
+ remove_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10 );
+
+ update_option( 'use_balanceTags', 1 );
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( '</u>', $output );
+ }
+
+ /**
+ * Filters the content of the Custom HTML widget using the legacy widget_text filter.
+ *
+ * @param string $text The widget content.
+ * @param array $instance Array of settings for the current widget.
+ * @param WP_Widget_Custom_HTML $widget Current widget instance.
+ * @return string Widget content.
+ */
+ public function filter_widget_text( $text, $instance, $widget ) {
+ $this->widget_text_args = array( $text, $instance, $widget );
+ $text .= '[filter:widget_text]';
+ return $text;
+ }
+
+ /**
+ * Filters the content of the Custom HTML widget using the dedicated widget_custom_html_content filter.
+ *
+ * @param string $widget_content The widget content.
+ * @param array $instance Array of settings for the current widget.
+ * @param WP_Widget_Custom_HTML $widget Current Custom HTML widget instance.
+ * @return string Widget content.
+ */
+ public function filter_widget_custom_html_content( $widget_content, $instance, $widget ) {
+ $this->widget_custom_html_content_args = array( $widget_content, $instance, $widget );
+ $widget_content .= '[filter:widget_custom_html_content]';
+ return $widget_content;
+ }
+
+ /**
+ * Test update method.
+ *
+ * @covers WP_Widget_Custom_HTML::update
+ */
+ public function test_update() {
+ $widget = new WP_Widget_Custom_HTML();
+ $instance = array(
+ 'title' => "The\n<b>Title</b>",
+ 'content' => "The\n\n<b>Code</b>",
+ );
+
+ wp_set_current_user(
+ $this->factory()->user->create(
+ array(
+ 'role' => 'administrator',
+ )
+ )
+ );
+
+ // Should return valid instance.
+ $expected = array(
+ 'title' => sanitize_text_field( $instance['title'] ),
+ 'content' => $instance['content'],
+ );
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $result, $expected );
+
+ // Make sure KSES is applying as expected.
+ add_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ), 10, 2 );
+ $this->assertTrue( current_user_can( 'unfiltered_html' ) );
+ $instance['content'] = '<script>alert( "Howdy!" );</script>';
+ $expected['content'] = $instance['content'];
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $result, $expected );
+ remove_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ) );
+
+ add_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
+ $this->assertFalse( current_user_can( 'unfiltered_html' ) );
+ $instance['content'] = '<script>alert( "Howdy!" );</script>';
+ $expected['content'] = wp_kses_post( $instance['content'] );
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $result, $expected );
+ remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10 );
+ }
+
+ /**
+ * Grant unfiltered_html cap via map_meta_cap.
+ *
+ * @param array $caps Returns the user's actual capabilities.
+ * @param string $cap Capability name.
+ * @return array Caps.
+ */
+ public function grant_unfiltered_html_cap( $caps, $cap ) {
+ if ( 'unfiltered_html' === $cap ) {
+ $caps = array_diff( $caps, array( 'do_not_allow' ) );
+ $caps[] = 'unfiltered_html';
+ }
+ return $caps;
+ }
+
+ /**
+ * Revoke unfiltered_html cap via map_meta_cap.
+ *
+ * @param array $caps Returns the user's actual capabilities.
+ * @param string $cap Capability name.
+ * @return array Caps.
+ */
+ public function revoke_unfiltered_html_cap( $caps, $cap ) {
+ if ( 'unfiltered_html' === $cap ) {
+ $caps = array_diff( $caps, array( 'unfiltered_html' ) );
+ $caps[] = 'do_not_allow';
+ }
+ return $caps;
+ }
+
+ /**
+ * Test enqueue_admin_scripts method. Condition: logged_in, syntax_highlighting is on.
+ *
+ * @covers WP_Widget_Custom_HTML::enqueue_admin_scripts
+ */
+ public function test_enqueue_admin_scripts_when_logged_in_and_syntax_highlighting_on() {
+ $user = $this->factory()->user->create();
+ wp_set_current_user( $user );
+ wp_get_current_user()->syntax_highlighting = 'true';
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Custom_HTML();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'custom-html-widgets', 'enqueued' ) );
+ $this->assertTrue( wp_script_is( 'code-editor', 'enqueued' ) );
+ $this->assertTrue( wp_script_is( 'wp-codemirror', 'enqueued' ) );
+ $this->assertTrue( wp_script_is( 'csslint', 'enqueued' ) );
+ $this->assertTrue( wp_script_is( 'jshint', 'enqueued' ) );
+ $this->assertTrue( wp_script_is( 'htmlhint', 'enqueued' ) );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method. Condition: logged_in, syntax_highlighting is off.
+ *
+ * @covers WP_Widget_Custom_HTML::enqueue_admin_scripts
+ */
+ public function test_enqueue_admin_scripts_when_logged_in_and_syntax_highlighting_off() {
+ $user = $this->factory()->user->create();
+ wp_set_current_user( $user );
+ update_user_meta( $user, 'syntax_highlighting', 'false' );
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Custom_HTML();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'custom-html-widgets', 'enqueued' ) );
+ $this->assertFalse( wp_script_is( 'code-editor', 'enqueued' ) );
+ $this->assertFalse( wp_script_is( 'wp-codemirror', 'enqueued' ) );
+ $this->assertFalse( wp_script_is( 'csslint', 'enqueued' ) );
+ $this->assertFalse( wp_script_is( 'jshint', 'enqueued' ) );
+ $this->assertFalse( wp_script_is( 'htmlhint', 'enqueued' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Custom_HTML::render_control_template_scripts
+ */
+ public function test_render_control_template_scripts() {
+ ob_start();
+ WP_Widget_Custom_HTML::render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-custom-html-control-fields">', $output );
+ }
+
+ /**
+ * Test add_help_text method.
+ *
+ * @covers WP_Widget_Custom_HTML::add_help_text
+ */
+ public function test_add_help_text() {
+ set_current_screen( 'widgets.php' );
+ WP_Widget_Custom_HTML::add_help_text();
+ $help_tab = get_current_screen()->get_help_tab( 'custom_html_widget' );
+
+ $this->assertStringContainsString( 'Use the Custom HTML widget to add arbitrary HTML code to your widget areas.', $help_tab['content'] );
+ }
+
+ /**
+ * Ensure that rel="noopener" is added to links with a target.
+ *
+ * @ticket 46421
+ */
+ function test_render_links_with_target() {
+ $widget = new WP_Widget_Custom_HTML();
+
+ $content = 'Test content with an external <a href="https://example.org" target="_blank">link</a>.';
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => '</h2>',
+ 'before_widget' => '',
+ 'after_widget' => '',
+ );
+
+ $instance = array(
+ 'title' => 'Foo',
+ 'content' => $content,
+ );
+
+ $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
+ $this->assertStringContainsString( 'rel="noopener"', $output );
+ }
+
+ /**
+ * Ensure that rel="noopener" is not added to links without a target.
+ *
+ * @ticket 46421
+ */
+ function test_render_links_without_target() {
+ $widget = new WP_Widget_Custom_HTML();
+
+ $content = 'Test content with an internal <a href="/">link</a>.';
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => '</h2>',
+ 'before_widget' => '',
+ 'after_widget' => '',
+ );
+
+ $instance = array(
+ 'title' => 'Foo',
+ 'content' => $content,
+ );
+
+ $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
+ $this->assertStringNotContainsString( 'rel="noopener"', $output );
+ }
+
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetMediaphpfromrev51492trunktestsphpunittestswidgetsmediawidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetMedia.php (from rev 51492, trunk/tests/phpunit/tests/widgets/media-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetMedia.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetMedia.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,525 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Media functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-media.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetMedia extends WP_UnitTestCase {
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+ function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Get instance for mocked media widget class.
+ *
+ * @param string $id_base Base ID for the widget, lowercase and unique.
+ * @param string $name Name for the widget displayed on the configuration page.
+ * @param array $widget_options Optional. Widget options.
+ * @param array $control_options Optional. Widget control options.
+ * @return PHPUnit_Framework_MockObject_MockObject|WP_Widget_Media Mocked instance.
+ */
+ function get_mocked_class_instance( $id_base = 'mocked', $name = 'Mocked', $widget_options = array(), $control_options = array() ) {
+ $original_class_name = 'WP_Widget_Media';
+ $arguments = array( $id_base, $name, $widget_options, $control_options );
+ $mock_class_name = '';
+ $call_original_constructor = true;
+ $call_original_clone = true;
+ $call_autoload = true;
+ $mocked_methods = array( 'render_media' );
+
+ return $this->getMockForAbstractClass( $original_class_name, $arguments, $mock_class_name, $call_original_constructor, $call_original_clone, $call_autoload, $mocked_methods );
+ }
+
+ /**
+ * Test constructor.
+ *
+ * @covers WP_Widget_Media::__construct
+ * @covers WP_Widget_Media::_register
+ */
+ function test_constructor() {
+ $widget = $this->get_mocked_class_instance();
+ $widget->_register();
+
+ $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
+ $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
+ $this->assertArrayHasKey( 'description', $widget->widget_options );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ $this->assertEmpty( $widget->widget_options['mime_type'] );
+ $this->assertSameSets(
+ array(
+ 'add_to_widget',
+ 'replace_media',
+ 'edit_media',
+ 'media_library_state_multi',
+ 'media_library_state_single',
+ 'missing_attachment',
+ 'no_media_selected',
+ 'add_media',
+ 'unsupported_file_type',
+ ),
+ array_keys( $widget->l10n )
+ );
+ $this->assertSame( count( $widget->l10n ), count( array_filter( $widget->l10n ) ), 'Expected all translation strings to be defined.' );
+ $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
+ $this->assertFalse( has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ), 'Did not expect preview scripts to be enqueued when not in customize preview context.' );
+ $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( $widget, 'render_control_template_scripts' ) ) );
+
+ // With non-default args.
+ $id_base = 'media_pdf';
+ $name = 'PDF';
+ $widget_options = array(
+ 'mime_type' => 'application/pdf',
+ );
+ $control_options = array(
+ 'width' => 850,
+ 'height' => 1100,
+ );
+ $widget = $this->get_mocked_class_instance( $id_base, $name, $widget_options, $control_options );
+ $this->assertSame( $id_base, $widget->id_base );
+ $this->assertSame( $name, $widget->name );
+
+ $this->assertArraySubset( $widget_options, $widget->widget_options );
+ $this->assertArraySubset( $control_options, $widget->control_options );
+ }
+
+ /**
+ * Test constructor in customize preview.
+ *
+ * @global WP_Customize_Manager $wp_customize
+ * @covers WP_Widget_Media::__construct
+ * @covers WP_Widget_Media::_register
+ */
+ function test_constructor_in_customize_preview() {
+ global $wp_customize;
+ wp_set_current_user(
+ $this->factory()->user->create(
+ array(
+ 'role' => 'administrator',
+ )
+ )
+ );
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ $wp_customize = new WP_Customize_Manager(
+ array(
+ 'changeset_uuid' => wp_generate_uuid4(),
+ )
+ );
+ $wp_customize->start_previewing_theme();
+
+ $widget = $this->get_mocked_class_instance();
+ $widget->_register();
+ $this->assertSame( 10, has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
+ }
+
+ /**
+ * Test is_attachment_with_mime_type method.
+ *
+ * @covers WP_Widget_Media::is_attachment_with_mime_type
+ * @requires function imagejpeg
+ */
+ function test_is_attachment_with_mime_type() {
+
+ $test_image = get_temp_dir() . 'canola.jpg';
+ copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => $test_image,
+ 'post_parent' => 0,
+ 'post_mime_type' => 'image/jpeg',
+ 'post_title' => 'Canola',
+ )
+ );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
+ $widget = $this->get_mocked_class_instance();
+
+ $this->assertFalse( $widget->is_attachment_with_mime_type( 0, 'image' ) );
+ $this->assertFalse( $widget->is_attachment_with_mime_type( -123, 'image' ) );
+
+ $post_id = $this->factory()->post->create();
+ $this->assertFalse( $widget->is_attachment_with_mime_type( $post_id, 'image' ) );
+ $this->assertFalse( $widget->is_attachment_with_mime_type( $attachment_id, 'video' ) );
+ $this->assertTrue( $widget->is_attachment_with_mime_type( $attachment_id, 'image' ) );
+ }
+
+ /**
+ * Test sanitize_token_list method.
+ *
+ * @covers WP_Widget_Media::sanitize_token_list
+ */
+ function test_sanitize_token_list_string() {
+ $widget = $this->get_mocked_class_instance();
+
+ $result = $widget->sanitize_token_list( 'What A false class with-token <a href="#">and link</a>' );
+ $this->assertSame( 'What A false class with-token a hrefand linka', $result );
+
+ $result = $widget->sanitize_token_list( array( 'foo', '<i>bar', '">NO' ) );
+ $this->assertSame( $result, 'foo ibar NO' );
+ }
+
+ /**
+ * Instance schema args.
+ *
+ * @var array
+ */
+ protected $filter_instance_schema_args;
+
+ /**
+ * Filter instance schema.
+ *
+ * @param array $schema Schema.
+ * @param WP_Widget_Media $widget Widget.
+ * @return array
+ */
+ public function filter_instance_schema( $schema, $widget ) {
+ $this->filter_instance_schema_args = compact( 'schema', 'widget' );
+ $schema['injected'] = array(
+ 'type' => 'boolean',
+ );
+ return $schema;
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media::get_instance_schema
+ */
+ function test_get_instance_schema() {
+ $widget = $this->get_mocked_class_instance();
+ $schema = $widget->get_instance_schema();
+
+ $this->assertSameSets(
+ array(
+ 'attachment_id',
+ 'title',
+ 'url',
+ ),
+ array_keys( $schema )
+ );
+
+ // Check filter usage.
+ $this->filter_instance_schema_args = null;
+ add_filter( 'widget_mocked_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
+ $schema = $widget->get_instance_schema();
+ $this->assertIsArray( $this->filter_instance_schema_args );
+ $this->assertSame( $widget, $this->filter_instance_schema_args['widget'] );
+ $this->assertSameSets( array( 'attachment_id', 'title', 'url' ), array_keys( $this->filter_instance_schema_args['schema'] ) );
+ $this->assertArrayHasKey( 'injected', $schema );
+ }
+
+ /**
+ * Test update method.
+ *
+ * @covers WP_Widget_Media::update
+ */
+ function test_update() {
+ $widget = $this->get_mocked_class_instance();
+ $instance = array();
+
+ // Should return valid attachment ID.
+ $expected = array(
+ 'attachment_id' => 1,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment ID.
+ $result = $widget->update(
+ array(
+ 'attachment_id' => 'media',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment url.
+ $expected = array(
+ 'url' => 'https://example.org',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment url.
+ $result = $widget->update(
+ array(
+ 'url' => 'not_a_url',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should return valid attachment title.
+ $expected = array(
+ 'title' => 'What a title',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment title.
+ $result = $widget->update(
+ array(
+ 'title' => '<h1>W00t!</h1>',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should filter invalid key.
+ $result = $widget->update(
+ array(
+ 'imaginary_key' => 'value',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ add_filter( 'sanitize_text_field', array( $this, '_return_wp_error' ) );
+ $result = $widget->update(
+ array(
+ 'title' => 'Title',
+ ),
+ $instance
+ );
+ remove_filter( 'sanitize_text_field', array( $this, '_return_wp_error' ) );
+ $this->assertSame( $result, $instance );
+ }
+
+ /**
+ * Helper function for Test_WP_Widget_Media::test_update().
+ *
+ * @return \WP_Error
+ */
+ function _return_wp_error() {
+ return new WP_Error( 'some-error', 'This is not valid!' );
+ }
+
+ /**
+ * Test widget method.
+ *
+ * @covers WP_Widget_Media::widget
+ * @covers WP_Widget_Media::render_media
+ */
+ function test_widget() {
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => "</h2>\n",
+ 'before_widget' => '<section>',
+ 'after_widget' => "</section>\n",
+ );
+ $instance = array(
+ 'title' => 'Foo',
+ 'url' => 'http://example.com/image.jpg',
+ 'attachment_id' => 0,
+ );
+
+ add_filter( 'widget_mocked_instance', array( $this, 'filter_widget_mocked_instance' ), 10, 3 );
+
+ ob_start();
+ $widget = $this->get_mocked_class_instance();
+ $widget->expects( $this->atLeastOnce() )->method( 'render_media' )->with( $instance );
+ $this->widget_instance_filter_args = array();
+ $widget->widget( $args, $instance );
+ $this->assertCount( 3, $this->widget_instance_filter_args );
+ $this->assertEquals( $instance, $this->widget_instance_filter_args[0] );
+ $this->assertSame( $args, $this->widget_instance_filter_args[1] );
+ $this->assertSame( $widget, $this->widget_instance_filter_args[2] );
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<h2>Foo</h2>', $output );
+ $this->assertStringContainsString( '<section>', $output );
+ $this->assertStringContainsString( '</section>', $output );
+
+ // No title.
+ ob_start();
+ $widget = $this->get_mocked_class_instance();
+ $instance['title'] = '';
+ $widget->expects( $this->atLeastOnce() )->method( 'render_media' )->with( $instance );
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringNotContainsString( '<h2>Foo</h2>', $output );
+
+ // No attachment_id nor url.
+ $instance['url'] = '';
+ $instance['attachment_id'] = 0;
+ ob_start();
+ $widget = $this->get_mocked_class_instance();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+ }
+
+ /**
+ * Args passed to the widget_{$id_base}_instance filter.
+ *
+ * @var array
+ */
+ protected $widget_instance_filter_args = array();
+
+ /**
+ * Filters the media widget instance prior to rendering the media.
+ *
+ * @param array $instance Instance data.
+ * @param array $args Widget args.
+ * @param WP_Widget_Media $object Widget object.
+ * @return array Instance.
+ */
+ function filter_widget_mocked_instance( $instance, $args, $object ) {
+ $this->widget_instance_filter_args = func_get_args();
+ return $instance;
+ }
+
+ /**
+ * Test form method.
+ *
+ * @covers WP_Widget_Media::form
+ */
+ function test_form() {
+ $widget = $this->get_mocked_class_instance();
+
+ ob_start();
+ $widget->form( array() );
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( 'name="widget-mocked[][attachment_id]"', $output );
+ $this->assertStringContainsString( 'name="widget-mocked[][title]"', $output );
+ $this->assertStringContainsString( 'name="widget-mocked[][url]"', $output );
+ }
+
+ /**
+ * Test display_media_state method.
+ *
+ * @covers WP_Widget_Media::display_media_state
+ */
+ function test_display_media_state() {
+ $widget = $this->get_mocked_class_instance();
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => DIR_TESTDATA . '/images/canola.jpg',
+ 'post_parent' => 0,
+ 'post_mime_type' => 'image/jpeg',
+ )
+ );
+
+ $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
+ $this->assertSameSets( array(), $result );
+
+ $widget->save_settings(
+ array(
+ array(
+ 'attachment_id' => $attachment_id,
+ ),
+ )
+ );
+ $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
+ $this->assertSameSets( array( $widget->l10n['media_library_state_single'] ), $result );
+
+ $widget->save_settings(
+ array(
+ array(
+ 'attachment_id' => $attachment_id,
+ ),
+ array(
+ 'attachment_id' => $attachment_id,
+ ),
+ )
+ );
+ $result = $widget->display_media_state( array(), get_post( $attachment_id ) );
+ $this->assertSameSets( array( sprintf( $widget->l10n['media_library_state_multi']['singular'], 2 ) ), $result );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Media::enqueue_admin_scripts
+ */
+ function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = $this->get_mocked_class_instance();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'media-widgets' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Media::render_control_template_scripts
+ */
+ function test_render_control_template_scripts() {
+ $widget = $this->get_mocked_class_instance();
+
+ ob_start();
+ $widget->render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-media-mocked-control">', $output );
+ }
+
+ /**
+ * Test has_content method.
+ *
+ * @covers WP_Widget_Media::has_content
+ */
+ function test_has_content() {
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => DIR_TESTDATA . '/images/canola.jpg',
+ 'post_parent' => 0,
+ 'post_mime_type' => 'image/jpeg',
+ )
+ );
+
+ $wp_widget_media = new ReflectionClass( 'WP_Widget_Media' );
+ $has_content = $wp_widget_media->getMethod( 'has_content' );
+ $has_content->setAccessible( true );
+
+ $result = $has_content->invokeArgs(
+ $this->get_mocked_class_instance(),
+ array(
+ array(
+ 'attachment_id' => 0,
+ 'url' => '',
+ ),
+ )
+ );
+ $this->assertFalse( $result );
+
+ $result = $has_content->invokeArgs(
+ $this->get_mocked_class_instance(),
+ array(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'url' => '',
+ ),
+ )
+ );
+ $this->assertTrue( $result );
+
+ $result = $has_content->invokeArgs(
+ $this->get_mocked_class_instance(),
+ array(
+ array(
+ 'attachment_id' => 0,
+ 'url' => 'http://example.com/image.jpg',
+ ),
+ )
+ );
+ $this->assertTrue( $result );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetMediaAudiophpfromrev51492trunktestsphpunittestswidgetsmediaaudiowidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetMediaAudio.php (from rev 51492, trunk/tests/phpunit/tests/widgets/media-audio-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetMediaAudio.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetMediaAudio.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,327 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Media_Audio functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-media-audio.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetMediaAudio extends WP_UnitTestCase {
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+ function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Audio::get_instance_schema
+ */
+ function test_get_instance_schema() {
+ $wp_widget_audio = new WP_Widget_Media_Audio();
+ $schema = $wp_widget_audio->get_instance_schema();
+
+ $this->assertSameSets(
+ array_merge(
+ array(
+ 'attachment_id',
+ 'preload',
+ 'loop',
+ 'title',
+ 'url',
+ ),
+ wp_get_audio_extensions()
+ ),
+ array_keys( $schema )
+ );
+ }
+
+ /**
+ * Test get_instance_schema filtering.
+ *
+ * @covers WP_Widget_Media_Audio::get_instance_schema
+ *
+ * @ticket 45029
+ */
+ function test_get_instance_schema_filtering() {
+ $wp_widget_audio = new WP_Widget_Media_Audio();
+ $schema = $wp_widget_audio->get_instance_schema();
+
+ add_filter( 'widget_media_audio_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
+ $schema = $wp_widget_audio->get_instance_schema();
+
+ $this->assertTrue( $schema['loop']['default'] );
+ }
+
+ /**
+ * Filters instance schema.
+ *
+ * @since 5.2.0
+ *
+ * @param array $schema Schema.
+ * @param WP_Widget_Media_Audio $widget Widget.
+ * @return array
+ */
+ public function filter_instance_schema( $schema, $widget ) {
+ // Override the default loop value (false).
+ $schema['loop']['default'] = true;
+ return $schema;
+ }
+
+ /**
+ * Test constructor.
+ *
+ * @covers WP_Widget_Media_Audio::__construct
+ */
+ function test_constructor() {
+ $widget = new WP_Widget_Media_Audio();
+
+ $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
+ $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
+ $this->assertArrayHasKey( 'description', $widget->widget_options );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ $this->assertSame( 'audio', $widget->widget_options['mime_type'] );
+ $this->assertSameSets(
+ array(
+ 'add_to_widget',
+ 'replace_media',
+ 'edit_media',
+ 'media_library_state_multi',
+ 'media_library_state_single',
+ 'missing_attachment',
+ 'no_media_selected',
+ 'add_media',
+ 'unsupported_file_type',
+ ),
+ array_keys( $widget->l10n )
+ );
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Audio::update
+ */
+ function test_update() {
+ $widget = new WP_Widget_Media_Audio();
+ $instance = array();
+
+ // Should return valid attachment ID.
+ $expected = array(
+ 'attachment_id' => 1,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment ID.
+ $result = $widget->update(
+ array(
+ 'attachment_id' => 'media',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment url.
+ $expected = array(
+ 'url' => 'https://chickenandribs.org',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment url.
+ $result = $widget->update(
+ array(
+ 'url' => 'not_a_url',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+ $this->assertStringStartsWith( 'http://', $result['url'] );
+
+ // Should return loop setting.
+ $expected = array(
+ 'loop' => true,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid loop setting.
+ $result = $widget->update(
+ array(
+ 'loop' => 'not-boolean',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment title.
+ $expected = array(
+ 'title' => 'An audio sample of parrots',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment title.
+ $result = $widget->update(
+ array(
+ 'title' => '<h1>Cute Baby Goats</h1>',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should return valid preload setting.
+ $expected = array(
+ 'preload' => 'none',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid preload setting.
+ $result = $widget->update(
+ array(
+ 'preload' => 'nope',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should filter invalid key.
+ $result = $widget->update(
+ array(
+ 'h4x' => 'value',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+ }
+
+ /**
+ * Test render_media method.
+ *
+ * @covers WP_Widget_Media_Audio::render_media
+ */
+ function test_render_media() {
+ $test_audio_file = __FILE__ . '../../data/uploads/small-audio.mp3';
+ $widget = new WP_Widget_Media_Audio();
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => $test_audio_file,
+ 'post_parent' => 0,
+ 'post_mime_type' => 'audio/mp3',
+ 'post_title' => 'Test Audio',
+ )
+ );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_audio_file ) );
+
+ // Should be empty when there is no attachment_id.
+ ob_start();
+ $widget->render_media( array() );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ // Should be empty when there is an invalid attachment_id.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => 777,
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ // Tests with audio from library.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Check default outputs.
+ $this->assertStringContainsString( 'preload="none"', $output );
+ $this->assertStringContainsString( 'class="wp-audio-shortcode"', $output );
+ $this->assertStringContainsString( 'small-audio.mp3', $output );
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'title' => 'Funny',
+ 'preload' => 'auto',
+ 'loop' => true,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Custom attributes.
+ $this->assertStringContainsString( 'preload="auto"', $output );
+ $this->assertStringContainsString( 'loop="1"', $output );
+ }
+
+ /**
+ * Test enqueue_preview_scripts method.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ * @covers WP_Widget_Media_Audio::enqueue_preview_scripts
+ */
+ function test_enqueue_preview_scripts() {
+ global $wp_scripts, $wp_styles;
+ $wp_scripts = null;
+ $wp_styles = null;
+ $widget = new WP_Widget_Media_Audio();
+
+ $this->assertFalse( wp_script_is( 'wp-mediaelement' ) );
+ $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
+
+ $widget->enqueue_preview_scripts();
+
+ $this->assertTrue( wp_script_is( 'wp-mediaelement' ) );
+ $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Media_Audio::enqueue_admin_scripts
+ */
+ function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Media_Audio();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'media-audio-widget' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Media_Audio::render_control_template_scripts
+ */
+ function test_render_control_template_scripts() {
+ $widget = new WP_Widget_Media_Audio();
+
+ ob_start();
+ $widget->render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-audio-preview">', $output );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetMediaGalleryphpfromrev51492trunktestsphpunittestswidgetsmediagallerywidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetMediaGallery.php (from rev 51492, trunk/tests/phpunit/tests/widgets/media-gallery-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetMediaGallery.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetMediaGallery.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,204 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Media_Gallery functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-media-gallery.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetMediaGallery extends WP_UnitTestCase {
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+ public function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Gallery::get_instance_schema
+ */
+ public function test_get_instance_schema() {
+ $widget = new WP_Widget_Media_Gallery();
+ $schema = $widget->get_instance_schema();
+
+ $this->assertSameSets(
+ array(
+ 'title',
+ 'ids',
+ 'columns',
+ 'size',
+ 'link_type',
+ 'orderby_random',
+ ),
+ array_keys( $schema )
+ );
+ }
+
+ /**
+ * Test update() method.
+ *
+ * @covers WP_Widget_Media_Gallery::render_media
+ * @requires function imagejpeg
+ */
+ public function test_render_media() {
+ $widget = new WP_Widget_Media_Gallery();
+
+ $attachments = array();
+ foreach ( array( 'canola.jpg', 'waffles.jpg' ) as $filename ) {
+ $test_image = get_temp_dir() . $filename;
+ copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => $test_image,
+ 'post_parent' => 0,
+ 'post_mime_type' => 'image/jpeg',
+ 'post_title' => 'Canola',
+ )
+ );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
+ $attachments[ $filename ] = $attachment_id;
+ }
+
+ $instance = wp_list_pluck( $widget->get_instance_schema(), 'default' );
+ $instance['size'] = 'thumbnail';
+ $instance['columns'] = 3;
+ $instance['ids'] = array_values( $attachments );
+ ob_start();
+ $widget->render_media( $instance );
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( 'gallery-columns-3', $output );
+ $this->assertStringContainsString( 'gallery-size-thumbnail', $output );
+ $this->assertStringContainsString( 'canola', $output );
+ $this->assertStringContainsString( 'waffles', $output );
+ }
+
+ /**
+ * Test enqueue_admin_scripts() method.
+ *
+ * @covers WP_Widget_Media_Gallery::enqueue_admin_scripts
+ */
+ public function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Media_Gallery();
+
+ $this->assertFalse( wp_script_is( 'media-gallery-widget' ) );
+
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'media-gallery-widget' ) );
+
+ $after = implode( '', wp_scripts()->registered['media-gallery-widget']->extra['after'] );
+ $this->assertStringContainsString( 'wp.mediaWidgets.modelConstructors[ "media_gallery" ].prototype', $after );
+ }
+
+ /**
+ * Test update() method.
+ *
+ * @covers WP_Widget_Media_Gallery::update
+ */
+ public function test_update() {
+ $widget = new WP_Widget_Media_Gallery();
+ $schema = $widget->get_instance_schema();
+ $instance = wp_list_pluck( $schema, 'default' );
+
+ // Field: title.
+ $instance['title'] = 'Hello <b>World</b> ';
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( 'Hello World', $instance['title'] );
+
+ // Field: ids.
+ $instance['ids'] = '1,2,3';
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( array( 1, 2, 3 ), $instance['ids'] );
+
+ $instance['ids'] = array( 1, 2, '3' );
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( array( 1, 2, 3 ), $instance['ids'] );
+
+ $instance['ids'] = array( 'too', 'bad' );
+ $instance = $widget->update( $instance, array( 'ids' => array( 2, 3 ) ) );
+ $this->assertSame( array( 2, 3 ), $instance['ids'] );
+
+ // Field: columns.
+ $instance['columns'] = 4;
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( 4, $instance['columns'] );
+
+ $instance['columns'] = '2';
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( 2, $instance['columns'] );
+
+ $instance['columns'] = -1; // Under min of 1.
+ $instance = $widget->update( $instance, array( 'columns' => 3 ) );
+ $this->assertSame( 3, $instance['columns'] );
+
+ $instance['columns'] = 10; // Over max of 9.
+ $instance = $widget->update( $instance, array( 'columns' => 3 ) );
+ $this->assertSame( 3, $instance['columns'] );
+
+ // Field: size.
+ $instance['size'] = 'large';
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( 'large', $instance['size'] );
+
+ $instance['size'] = 'bad';
+ $instance = $widget->update( $instance, array( 'size' => 'thumbnail' ) );
+ $this->assertSame( 'thumbnail', $instance['size'] );
+
+ // Field: link_type.
+ $instance['link_type'] = 'none';
+ $instance = $widget->update( $instance, array() );
+ $this->assertSame( 'none', $instance['link_type'] );
+
+ $instance['link_type'] = 'unknown';
+ $instance = $widget->update( $instance, array( 'link_type' => 'file' ) );
+ $this->assertSame( 'file', $instance['link_type'] );
+
+ // Field: orderby_random.
+ $instance['orderby_random'] = '1';
+ $instance = $widget->update( $instance, array() );
+ $this->assertTrue( $instance['orderby_random'] );
+
+ $instance['orderby_random'] = true;
+ $instance = $widget->update( $instance, array() );
+ $this->assertTrue( $instance['orderby_random'] );
+
+ $instance['orderby_random'] = '';
+ $instance = $widget->update( $instance, array() );
+ $this->assertFalse( $instance['orderby_random'] );
+
+ $instance['orderby_random'] = false;
+ $instance = $widget->update( $instance, array() );
+ $this->assertFalse( $instance['orderby_random'] );
+ }
+
+ /**
+ * Test render_control_template_scripts() method.
+ *
+ * @covers WP_Widget_Media_Gallery::render_control_template_scripts
+ */
+ public function test_render_control_template_scripts() {
+ $widget = new WP_Widget_Media_Gallery();
+
+ ob_start();
+ $widget->render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-gallery-preview">', $output );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetMediaImagephpfromrev51492trunktestsphpunittestswidgetsmediaimagewidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetMediaImage.php (from rev 51492, trunk/tests/phpunit/tests/widgets/media-image-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetMediaImage.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetMediaImage.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,633 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Media_Image functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-media-image.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetMediaImage extends WP_UnitTestCase {
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+ function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Image::get_instance_schema
+ */
+ function test_get_instance_schema() {
+ $widget = new WP_Widget_Media_Image();
+ $schema = $widget->get_instance_schema();
+
+ $this->assertSameSets(
+ array(
+ 'alt',
+ 'attachment_id',
+ 'caption',
+ 'height',
+ 'image_classes',
+ 'image_title',
+ 'link_classes',
+ 'link_rel',
+ 'link_target_blank',
+ 'link_type',
+ 'link_url',
+ 'size',
+ 'title',
+ 'url',
+ 'width',
+ ),
+ array_keys( $schema )
+ );
+ }
+
+ /**
+ * Test schema filtering.
+ *
+ * @covers WP_Widget_Media_Image::get_instance_schema
+ *
+ * @ticket 45029
+ */
+ function test_get_instance_schema_filtering() {
+ $widget = new WP_Widget_Media_Image();
+ $schema = $widget->get_instance_schema();
+
+ add_filter( 'widget_media_image_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
+ $schema = $widget->get_instance_schema();
+
+ $this->assertSame( 'large', $schema['size']['default'] );
+ }
+
+ /**
+ * Filters instance schema.
+ *
+ * @since 5.2.0
+ *
+ * @param array $schema Schema.
+ * @param WP_Widget_Media_Image $widget Widget.
+ * @return array
+ */
+ public function filter_instance_schema( $schema, $widget ) {
+ // Override the default size value ('medium').
+ $schema['size']['default'] = 'large';
+ return $schema;
+ }
+
+ /**
+ * Test constructor.
+ *
+ * @covers WP_Widget_Media_Image::__construct
+ */
+ function test_constructor() {
+ $widget = new WP_Widget_Media_Image();
+
+ $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
+ $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
+ $this->assertArrayHasKey( 'description', $widget->widget_options );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ $this->assertSame( 'image', $widget->widget_options['mime_type'] );
+ $this->assertSameSets(
+ array(
+ 'add_to_widget',
+ 'replace_media',
+ 'edit_media',
+ 'media_library_state_multi',
+ 'media_library_state_single',
+ 'missing_attachment',
+ 'no_media_selected',
+ 'add_media',
+ 'unsupported_file_type',
+ ),
+ array_keys( $widget->l10n )
+ );
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Image::update
+ */
+ function test_update() {
+ $widget = new WP_Widget_Media_Image();
+ $instance = array();
+
+ // Should return valid attachment ID.
+ $expected = array(
+ 'attachment_id' => 1,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment ID.
+ $result = $widget->update(
+ array(
+ 'attachment_id' => 'media',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment url.
+ $expected = array(
+ 'url' => 'https://example.org',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment url.
+ $result = $widget->update(
+ array(
+ 'url' => 'not_a_url',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+ $this->assertStringStartsWith( 'http://', $result['url'] );
+
+ // Should return valid attachment title.
+ $expected = array(
+ 'title' => 'What a title',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment title.
+ $result = $widget->update(
+ array(
+ 'title' => '<h1>W00t!</h1>',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should return valid image size.
+ $expected = array(
+ 'size' => 'thumbnail',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image size.
+ $result = $widget->update(
+ array(
+ 'size' => 'big league',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid image width.
+ $expected = array(
+ 'width' => 300,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image width.
+ $result = $widget->update(
+ array(
+ 'width' => 'wide',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid image height.
+ $expected = array(
+ 'height' => 200,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image height.
+ $result = $widget->update(
+ array(
+ 'height' => 'high',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid image caption.
+ $expected = array(
+ 'caption' => 'A caption with <a href="#">link</a>',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image caption.
+ $result = $widget->update(
+ array(
+ 'caption' => '"><i onload="alert(\'hello\')" />',
+ ),
+ $instance
+ );
+ $this->assertSame(
+ $result,
+ array(
+ 'caption' => '"><i />',
+ )
+ );
+
+ // Should return valid alt text.
+ $expected = array(
+ 'alt' => 'A water tower',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid alt text.
+ $result = $widget->update(
+ array(
+ 'alt' => '"><i onload="alert(\'hello\')" />',
+ ),
+ $instance
+ );
+ $this->assertSame(
+ $result,
+ array(
+ 'alt' => '">',
+ )
+ );
+
+ // Should return valid link type.
+ $expected = array(
+ 'link_type' => 'file',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid link type.
+ $result = $widget->update(
+ array(
+ 'link_type' => 'interesting',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid link url.
+ $expected = array(
+ 'link_url' => 'https://example.org',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid link url.
+ $result = $widget->update(
+ array(
+ 'link_url' => 'not_a_url',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+ $this->assertStringStartsWith( 'http://', $result['link_url'] );
+
+ // Should return valid image classes.
+ $expected = array(
+ 'image_classes' => 'A water tower',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image classes.
+ $result = $widget->update(
+ array(
+ 'image_classes' => '"><i onload="alert(\'hello\')" />',
+ ),
+ $instance
+ );
+ $this->assertSame(
+ $result,
+ array(
+ 'image_classes' => 'i onloadalerthello',
+ )
+ );
+
+ // Should return valid link classes.
+ $expected = array(
+ 'link_classes' => 'A water tower',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid link classes.
+ $result = $widget->update(
+ array(
+ 'link_classes' => '"><i onload="alert(\'hello\')" />',
+ ),
+ $instance
+ );
+ $this->assertSame(
+ $result,
+ array(
+ 'link_classes' => 'i onloadalerthello',
+ )
+ );
+
+ // Should return valid rel text.
+ $expected = array(
+ 'link_rel' => 'previous',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid rel text.
+ $result = $widget->update(
+ array(
+ 'link_rel' => '"><i onload="alert(\'hello\')" />',
+ ),
+ $instance
+ );
+ $this->assertSame(
+ $result,
+ array(
+ 'link_rel' => 'i onloadalerthello',
+ )
+ );
+
+ // Should return valid link target.
+ $expected = array(
+ 'link_target_blank' => false,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid link target.
+ $result = $widget->update(
+ array(
+ 'link_target_blank' => 'top',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid image title.
+ $expected = array(
+ 'image_title' => 'What a title',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid image title.
+ $result = $widget->update(
+ array(
+ 'image_title' => '<h1>W00t!</h1>',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should filter invalid key.
+ $result = $widget->update(
+ array(
+ 'imaginary_key' => 'value',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+ }
+
+ /**
+ * Test render_media method.
+ *
+ * @covers WP_Widget_Media_Image::render_media
+ * @requires function imagejpeg
+ */
+ function test_render_media() {
+ $widget = new WP_Widget_Media_Image();
+
+ $test_image = get_temp_dir() . 'canola.jpg';
+ copy( DIR_TESTDATA . '/images/canola.jpg', $test_image );
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => $test_image,
+ 'post_parent' => 0,
+ 'post_mime_type' => 'image/jpeg',
+ 'post_title' => 'Canola',
+ )
+ );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_image ) );
+
+ // Should be empty when there is no attachment_id.
+ ob_start();
+ $widget->render_media( array() );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ // Should be empty when there is an invalid attachment_id.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => 666,
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ )
+ );
+ $output = ob_get_clean();
+
+ // No default title.
+ $this->assertStringNotContainsString( 'title="', $output );
+ // Default image classes.
+ $this->assertStringContainsString( 'class="image wp-image-' . $attachment_id, $output );
+ $this->assertStringContainsString( 'style="max-width: 100%; height: auto;"', $output );
+ $this->assertStringContainsString( 'alt=""', $output );
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'image_title' => 'Custom Title',
+ 'image_classes' => 'custom-class',
+ 'alt' => 'A flower',
+ 'size' => 'custom',
+ 'width' => 100,
+ 'height' => 100,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Custom image title.
+ $this->assertStringContainsString( 'title="Custom Title"', $output );
+ // Custom image class.
+ $this->assertStringContainsString( 'class="image wp-image-' . $attachment_id . ' custom-class', $output );
+ $this->assertStringContainsString( 'alt="A flower"', $output );
+ $this->assertStringContainsString( 'width="100"', $output );
+ $this->assertStringContainsString( 'height="100"', $output );
+
+ // Embeded images.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => null,
+ 'caption' => 'With caption',
+ 'height' => 100,
+ 'link_type' => 'file',
+ 'url' => 'http://example.org/url/to/image.jpg',
+ 'width' => 100,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Custom image class.
+ $this->assertStringContainsString( 'src="http://example.org/url/to/image.jpg"', $output );
+
+ // Link settings.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'link_type' => 'file',
+ )
+ );
+ $output = ob_get_clean();
+
+ $link = '<a href="' . wp_get_attachment_url( $attachment_id ) . '"';
+ $this->assertStringContainsString( $link, $output );
+ $this->assertTrue( (bool) preg_match( '#<a href.*?>#', $output, $matches ) );
+ $this->assertStringNotContainsString( ' class="', $matches[0] );
+ $this->assertStringNotContainsString( ' rel="', $matches[0] );
+ $this->assertStringNotContainsString( ' target="', $matches[0] );
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'link_type' => 'post',
+ 'link_classes' => 'custom-link-class',
+ 'link_rel' => 'attachment',
+ 'link_target_blank' => false,
+ )
+ );
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<a href="' . get_attachment_link( $attachment_id ) . '"', $output );
+ $this->assertStringContainsString( 'class="custom-link-class"', $output );
+ $this->assertStringContainsString( 'rel="attachment"', $output );
+ $this->assertStringNotContainsString( 'target=""', $output );
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'link_type' => 'custom',
+ 'link_url' => 'https://example.org',
+ 'link_target_blank' => true,
+ )
+ );
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<a href="https://example.org"', $output );
+ $this->assertStringContainsString( 'target="_blank"', $output );
+ $this->assertStringContainsString( 'rel="noopener"', $output );
+
+ // Populate caption in attachment.
+ wp_update_post(
+ array(
+ 'ID' => $attachment_id,
+ 'post_excerpt' => 'Default caption',
+ )
+ );
+
+ // If no caption is supplied, then the default is '', and so the caption will not be displayed.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertStringNotContainsString( 'wp-caption', $output );
+ $this->assertStringNotContainsString( '<p class="wp-caption-text">', $output );
+
+ // If the caption is explicitly null, then the caption of the underlying attachment will be displayed.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'caption' => null,
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( 'class="wp-caption alignnone"', $output );
+ $this->assertStringContainsString( '<p class="wp-caption-text">Default caption</p>', $output );
+
+ // If caption is provided, then it will be displayed.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'caption' => 'Custom caption',
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( 'class="wp-caption alignnone"', $output );
+ $this->assertStringContainsString( '<p class="wp-caption-text">Custom caption</p>', $output );
+
+ // Attachments with custom sizes can render captions.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'size' => 'custom',
+ 'width' => '300',
+ 'height' => '200',
+ 'caption' => 'Caption for an image with custom size',
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( 'style="width: 310px"', $output );
+ $this->assertStringContainsString( '<p class="wp-caption-text">Caption for an image with custom size</p>', $output );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Media_Image::enqueue_admin_scripts
+ */
+ function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Media_Image();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'media-image-widget' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Media_Image::render_control_template_scripts
+ */
+ function test_render_control_template_scripts() {
+ $widget = new WP_Widget_Media_Image();
+
+ ob_start();
+ $widget->render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-image-preview">', $output );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetMediaVideophpfromrev51492trunktestsphpunittestswidgetsmediavideowidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetMediaVideo.php (from rev 51492, trunk/tests/phpunit/tests/widgets/media-video-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetMediaVideo.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetMediaVideo.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,355 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Media_Video functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-media-video.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetMediaVideo extends WP_UnitTestCase {
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+ function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Video::get_instance_schema
+ */
+ function test_get_instance_schema() {
+ $widget = new WP_Widget_Media_Video();
+ $schema = $widget->get_instance_schema();
+
+ $this->assertSameSets(
+ array_merge(
+ array(
+ 'attachment_id',
+ 'preload',
+ 'loop',
+ 'title',
+ 'url',
+ 'content',
+ ),
+ wp_get_video_extensions()
+ ),
+ array_keys( $schema )
+ );
+ }
+
+ /**
+ * Test schema filtering.
+ *
+ * @covers WP_Widget_Media_Video::get_instance_schema
+ *
+ * @ticket 45029
+ */
+ function test_get_instance_schema_filtering() {
+ $widget = new WP_Widget_Media_Video();
+ $schema = $widget->get_instance_schema();
+
+ add_filter( 'widget_media_video_instance_schema', array( $this, 'filter_instance_schema' ), 10, 2 );
+ $schema = $widget->get_instance_schema();
+
+ $this->assertTrue( $schema['loop']['default'] );
+ }
+
+ /**
+ * Filters instance schema.
+ *
+ * @since 5.2.0
+ *
+ * @param array $schema Schema.
+ * @param WP_Widget_Media_Video $widget Widget.
+ * @return array
+ */
+ public function filter_instance_schema( $schema, $widget ) {
+ // Override the default loop value (false).
+ $schema['loop']['default'] = true;
+ return $schema;
+ }
+
+ /**
+ * Test constructor.
+ *
+ * @covers WP_Widget_Media_Video::__construct
+ */
+ function test_constructor() {
+ $widget = new WP_Widget_Media_Video();
+
+ $this->assertArrayHasKey( 'mime_type', $widget->widget_options );
+ $this->assertArrayHasKey( 'customize_selective_refresh', $widget->widget_options );
+ $this->assertArrayHasKey( 'description', $widget->widget_options );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ $this->assertSame( 'video', $widget->widget_options['mime_type'] );
+ $this->assertSameSets(
+ array(
+ 'add_to_widget',
+ 'replace_media',
+ 'unsupported_file_type',
+ 'edit_media',
+ 'media_library_state_multi',
+ 'media_library_state_single',
+ 'missing_attachment',
+ 'no_media_selected',
+ 'add_media',
+ ),
+ array_keys( $widget->l10n )
+ );
+ }
+
+ /**
+ * Test get_instance_schema method.
+ *
+ * @covers WP_Widget_Media_Video::update
+ */
+ function test_update() {
+ $widget = new WP_Widget_Media_Video();
+ $instance = array();
+
+ // Should return valid attachment ID.
+ $expected = array(
+ 'attachment_id' => 1,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment ID.
+ $result = $widget->update(
+ array(
+ 'attachment_id' => 'media',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment url.
+ $expected = array(
+ 'url' => 'https://chickenandribs.org',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment url.
+ $result = $widget->update(
+ array(
+ 'url' => 'not_a_url',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+ $this->assertStringStartsWith( 'http://', $result['url'] );
+
+ // Should return loop setting.
+ $expected = array(
+ 'loop' => true,
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid loop setting.
+ $result = $widget->update(
+ array(
+ 'loop' => 'not-boolean',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should return valid attachment title.
+ $expected = array(
+ 'title' => 'A video of goats',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid attachment title.
+ $result = $widget->update(
+ array(
+ 'title' => '<h1>Cute Baby Goats</h1>',
+ ),
+ $instance
+ );
+ $this->assertNotSame( $result, $instance );
+
+ // Should return valid preload setting.
+ $expected = array(
+ 'preload' => 'none',
+ );
+ $result = $widget->update( $expected, $instance );
+ $this->assertSame( $result, $expected );
+
+ // Should filter invalid preload setting.
+ $result = $widget->update(
+ array(
+ 'preload' => 'nope',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+
+ // Should filter invalid key.
+ $result = $widget->update(
+ array(
+ 'h4x' => 'value',
+ ),
+ $instance
+ );
+ $this->assertSame( $result, $instance );
+ }
+
+ /**
+ * Test render_media method.
+ *
+ * @covers WP_Widget_Media_Video::render_media
+ * @covers WP_Widget_Media_Video::inject_video_max_width_style
+ */
+ function test_render_media() {
+ $test_movie_file = __FILE__ . '../../data/uploads/small-video.m4v';
+ $widget = new WP_Widget_Media_Video();
+ $attachment_id = self::factory()->attachment->create_object(
+ array(
+ 'file' => $test_movie_file,
+ 'post_parent' => 0,
+ 'post_mime_type' => 'video/mp4',
+ 'post_title' => 'Test Video',
+ )
+ );
+ wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $test_movie_file ) );
+
+ // Should be empty when there is no attachment_id.
+ ob_start();
+ $widget->render_media( array() );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ // Should be empty when there is an invalid attachment_id.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => 777,
+ )
+ );
+ $output = ob_get_clean();
+ $this->assertEmpty( $output );
+
+ // Tests with video from library.
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Check default outputs.
+ $this->assertStringContainsString( 'preload="metadata"', $output );
+ $this->assertStringContainsString( 'class="wp-video"', $output );
+ $this->assertStringContainsString( 'width:100%', $output );
+ $this->assertStringNotContainsString( 'height=', $output );
+ $this->assertStringNotContainsString( 'width="', $output );
+ $this->assertStringContainsString( 'small-video.m4v', $output );// Auto parses dimensions.
+
+ ob_start();
+ $widget->render_media(
+ array(
+ 'attachment_id' => $attachment_id,
+ 'title' => 'Open Source Cartoon',
+ 'preload' => 'metadata',
+ 'loop' => true,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Custom attributes.
+ $this->assertStringContainsString( 'preload="metadata"', $output );
+ $this->assertStringContainsString( 'loop="1"', $output );
+
+ // Externally hosted video.
+ ob_start();
+ $content = '<track srclang="en" label="English" kind="subtitles" src="http://example.com/wp-content/uploads/2017/04/subtitles-en.vtt">';
+ $widget->render_media(
+ array(
+ 'attachment_id' => null,
+ 'loop' => false,
+ 'url' => 'https://www.youtube.com/watch?v=72xdCU__XCk',
+ 'content' => $content,
+ )
+ );
+ $output = ob_get_clean();
+
+ // Custom attributes.
+ $this->assertStringContainsString( 'preload="metadata"', $output );
+ $this->assertStringContainsString( 'src="https://www.youtube.com/watch?v=72xdCU__XCk', $output );
+ $this->assertStringContainsString( $content, $output );
+ }
+
+ /**
+ * Test enqueue_preview_scripts method.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ * @covers WP_Widget_Media_Video::enqueue_preview_scripts
+ */
+ function test_enqueue_preview_scripts() {
+ global $wp_scripts, $wp_styles;
+ $widget = new WP_Widget_Media_Video();
+
+ $wp_scripts = null;
+ $wp_styles = null;
+ $widget->enqueue_preview_scripts();
+ $this->assertTrue( wp_script_is( 'wp-mediaelement' ) );
+ $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
+ $this->assertTrue( wp_script_is( 'mediaelement-vimeo' ) );
+
+ $wp_scripts = null;
+ $wp_styles = null;
+ add_filter( 'wp_video_shortcode_library', '__return_empty_string' );
+ $widget->enqueue_preview_scripts();
+ $this->assertFalse( wp_script_is( 'wp-mediaelement' ) );
+ $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
+ $this->assertFalse( wp_script_is( 'mediaelement-vimeo' ) );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Media_Video::enqueue_admin_scripts
+ */
+ function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Media_Video();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'media-video-widget' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Media_Video::render_control_template_scripts
+ */
+ function test_render_control_template_scripts() {
+ $widget = new WP_Widget_Media_Video();
+
+ ob_start();
+ $widget->render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-wp-media-widget-video-preview">', $output );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetRssphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/widgets/wpWidgetRss.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetRss.php 2021-07-26 19:09:41 UTC (rev 51492)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetRss.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,7 +11,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @group widgets
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class Test_Widgets_wpWidgetRss extends WP_UnitTestCase {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class Tests_Widgets_wpWidgetRss extends WP_UnitTestCase {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53278
</span></span></pre></div>
<a id="trunktestsphpunittestswidgetswpWidgetTextphpfromrev51492trunktestsphpunittestswidgetstextwidgetphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/widgets/wpWidgetText.php (from rev 51492, trunk/tests/phpunit/tests/widgets/text-widget.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets/wpWidgetText.php (rev 0)
+++ trunk/tests/phpunit/tests/widgets/wpWidgetText.php 2021-07-26 19:25:09 UTC (rev 51493)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,1058 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Widget_Text functionality.
+ *
+ * @package WordPress
+ * @subpackage widgets
+ */
+
+/**
+ * Test wp-includes/widgets/class-wp-widget-text.php
+ *
+ * @group widgets
+ */
+class Tests_Widgets_wpWidgetText extends WP_UnitTestCase {
+ /**
+ * Args passed to the widget_text filter.
+ *
+ * @var array
+ */
+ protected $widget_text_args;
+
+ /**
+ * Args passed to the widget_text_content filter.
+ *
+ * @var array
+ */
+ protected $widget_text_content_args;
+
+ /**
+ * Clean up global scope.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_style
+ * @global WP_Customize_Manager $wp_customize
+ */
+ function clean_up_global_scope() {
+ global $wp_scripts, $wp_styles, $wp_customize;
+ parent::clean_up_global_scope();
+ $wp_scripts = null;
+ $wp_styles = null;
+ $wp_customize = null;
+ }
+
+ /**
+ * Test constructor method.
+ *
+ * @covers WP_Widget_Text::__construct
+ */
+ function test_construct() {
+ $widget = new WP_Widget_Text();
+ $this->assertSame( 'text', $widget->id_base );
+ $this->assertSame( 'widget_text', $widget->widget_options['classname'] );
+ $this->assertTrue( $widget->widget_options['customize_selective_refresh'] );
+ $this->assertSame( 400, $widget->control_options['width'] );
+ $this->assertSame( 350, $widget->control_options['height'] );
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Text::_register
+ */
+ function test__register() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Text();
+ $widget->_register();
+
+ $this->assertSame( 10, has_action( 'admin_print_scripts-widgets.php', array( $widget, 'enqueue_admin_scripts' ) ) );
+ $this->assertSame( 10, has_action( 'admin_footer-widgets.php', array( 'WP_Widget_Text', 'render_control_template_scripts' ) ) );
+ $this->assertContains( 'wp.textWidgets.idBases.push( "text" );', wp_scripts()->registered['text-widgets']->extra['after'] );
+ $this->assertFalse( has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
+ }
+
+ /**
+ * Test register in customize preview.
+ *
+ * @global WP_Customize_Manager $wp_customize
+ * @covers WP_Widget_Text::__construct
+ * @covers WP_Widget_Text::_register
+ */
+ function test__register_in_customize_preview() {
+ global $wp_customize;
+ wp_set_current_user(
+ $this->factory()->user->create(
+ array(
+ 'role' => 'administrator',
+ )
+ )
+ );
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ $wp_customize = new WP_Customize_Manager(
+ array(
+ 'changeset_uuid' => wp_generate_uuid4(),
+ )
+ );
+ $wp_customize->start_previewing_theme();
+
+ $widget = new WP_Widget_Text();
+ $widget->_register();
+ $this->assertSame( 10, has_action( 'wp_enqueue_scripts', array( $widget, 'enqueue_preview_scripts' ) ) );
+ }
+
+ /**
+ * Test enqueue_preview_scripts method.
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ * @covers WP_Widget_Text::enqueue_preview_scripts
+ */
+ function test_enqueue_preview_scripts() {
+ global $wp_scripts, $wp_styles;
+ $wp_scripts = null;
+ $wp_styles = null;
+ $widget = new WP_Widget_Text();
+
+ $this->assertFalse( wp_style_is( 'wp-mediaelement' ) );
+ $this->assertFalse( wp_script_is( 'wp-playlist' ) );
+
+ ob_start();
+ $widget->enqueue_preview_scripts();
+ ob_end_clean();
+
+ $this->assertTrue( wp_style_is( 'wp-mediaelement' ) );
+ $this->assertTrue( wp_script_is( 'wp-playlist' ) );
+ }
+
+ /**
+ * Test widget method.
+ *
+ * @covers WP_Widget_Text::widget
+ */
+ function test_widget() {
+ $widget = new WP_Widget_Text();
+ $text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n Praesent ut turpis consequat lorem volutpat bibendum vitae vitae ante.";
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => "</h2>\n",
+ 'before_widget' => '<section>',
+ 'after_widget' => "</section>\n",
+ );
+
+ add_filter( 'widget_text_content', array( $this, 'filter_widget_text_content' ), 5, 3 );
+ add_filter( 'widget_text', array( $this, 'filter_widget_text' ), 5, 3 );
+
+ // Test with filter=false, implicit legacy mode.
+ $this->widget_text_content_args = null;
+ ob_start();
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => false,
+ );
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringNotContainsString( '<p>', $output );
+ $this->assertStringNotContainsString( '<br />', $output );
+ $this->assertEmpty( $this->widget_text_content_args );
+ $this->assertNotEmpty( $this->widget_text_args );
+ $this->assertStringContainsString( '[filter:widget_text]', $output );
+ $this->assertStringNotContainsString( '[filter:widget_text_content]', $output );
+
+ // Test with filter=true, implicit legacy mode.
+ $this->widget_text_content_args = null;
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => true,
+ );
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( '<p>', $output );
+ $this->assertStringContainsString( '<br />', $output );
+ $this->assertNotEmpty( $this->widget_text_args );
+ $this->assertSame( $instance['text'], $this->widget_text_args[0] );
+ $this->assertSame( $instance, $this->widget_text_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertEmpty( $this->widget_text_content_args );
+ $this->assertStringContainsString( '[filter:widget_text]', $output );
+ $this->assertStringNotContainsString( '[filter:widget_text_content]', $output );
+
+ // Test with filter=content, the upgraded widget, in 4.8.0 only.
+ $this->widget_text_content_args = null;
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => 'content',
+ );
+ $expected_instance = array_merge(
+ $instance,
+ array(
+ 'filter' => true,
+ 'visual' => true,
+ )
+ );
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( '<p>', $output );
+ $this->assertStringContainsString( '<br />', $output );
+ $this->assertCount( 3, $this->widget_text_args );
+ $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertCount( 3, $this->widget_text_content_args );
+ $this->assertSame( $expected_instance['text'] . '[filter:widget_text]', $this->widget_text_content_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_content_args[1] );
+ $this->assertSame( $widget, $this->widget_text_content_args[2] );
+ $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text][filter:widget_text_content]' ), $output );
+
+ // Test with filter=true&visual=true, the upgraded widget, in 4.8.1 and above.
+ $this->widget_text_content_args = null;
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => true,
+ 'visual' => true,
+ );
+ $expected_instance = $instance;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( '<p>', $output );
+ $this->assertStringContainsString( '<br />', $output );
+ $this->assertCount( 3, $this->widget_text_args );
+ $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertCount( 3, $this->widget_text_content_args );
+ $this->assertSame( $expected_instance['text'] . '[filter:widget_text]', $this->widget_text_content_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_content_args[1] );
+ $this->assertSame( $widget, $this->widget_text_content_args[2] );
+ $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text][filter:widget_text_content]' ), $output );
+
+ // Test with filter=true&visual=true, the upgraded widget, in 4.8.1 and above.
+ $this->widget_text_content_args = null;
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => true,
+ 'visual' => false,
+ );
+ $expected_instance = $instance;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringContainsString( '<p>', $output );
+ $this->assertStringContainsString( '<br />', $output );
+ $this->assertCount( 3, $this->widget_text_args );
+ $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertNull( $this->widget_text_content_args );
+ $this->assertStringContainsString( wpautop( $expected_instance['text'] . '[filter:widget_text]' ), $output );
+
+ // Test with filter=false&visual=false, the upgraded widget, in 4.8.1 and above.
+ $this->widget_text_content_args = null;
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ 'filter' => false,
+ 'visual' => false,
+ );
+ $expected_instance = $instance;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertStringNotContainsString( '<p>', $output );
+ $this->assertStringNotContainsString( '<br />', $output );
+ $this->assertCount( 3, $this->widget_text_args );
+ $this->assertSame( $expected_instance['text'], $this->widget_text_args[0] );
+ $this->assertSame( $expected_instance, $this->widget_text_args[1] );
+ $this->assertSame( $widget, $this->widget_text_args[2] );
+ $this->assertNull( $this->widget_text_content_args );
+ $this->assertStringContainsString( $expected_instance['text'] . '[filter:widget_text]', $output );
+ }
+
+ /**
+ * Example shortcode content to test for wpautop corruption.
+ *
+ * @var string
+ */
+ protected $example_shortcode_content = "<p class='sortcodep'>One\nTwo\n\nThree\n\nThis is testing the <code>[example note='This will not get processed since it is part of shortcode output itself.']</code> shortcode.</p>\n<script>\ndocument.write('Test1');\n\ndocument.write('Test2');\n</script>";
+
+ /**
+ * The captured global post during shortcode rendering.
+ *
+ * @var WP_Post|null
+ */
+ protected $post_during_shortcode = null;
+
+ /**
+ * Number of times the shortcode was rendered.
+ *
+ * @var int
+ */
+ protected $shortcode_render_count = 0;
+
+ /**
+ * Do example shortcode.
+ *
+ * @return string Shortcode content.
+ */
+ function do_example_shortcode() {
+ $this->post_during_shortcode = get_post();
+ $this->shortcode_render_count++;
+ return $this->example_shortcode_content;
+ }
+
+ /**
+ * Test widget method with shortcodes.
+ *
+ * @covers WP_Widget_Text::widget
+ */
+ function test_widget_shortcodes() {
+ global $post;
+ $post_id = $this->factory()->post->create();
+ $post = get_post( $post_id );
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => "</h2>\n",
+ 'before_widget' => '<section>',
+ 'after_widget' => "</section>\n",
+ );
+ $widget = new WP_Widget_Text();
+ add_shortcode( 'example', array( $this, 'do_example_shortcode' ) );
+
+ $base_instance = array(
+ 'title' => 'Example',
+ 'text' => "This is an example:\n\n[example]\n\nHello.",
+ 'filter' => false,
+ );
+
+ // Legacy Text Widget without wpautop().
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'filter' => false,
+ )
+ );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 1, $this->shortcode_render_count );
+ $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
+ $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
+ $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
+ $this->assertNull( $this->post_during_shortcode );
+
+ // Legacy Text Widget with wpautop().
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'filter' => true,
+ 'visual' => false,
+ )
+ );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 1, $this->shortcode_render_count );
+ $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
+ $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
+ $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
+ $this->assertNull( $this->post_during_shortcode );
+
+ // Legacy text widget with plugin adding shortcode support as well.
+ add_filter( 'widget_text', 'do_shortcode' );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 1, $this->shortcode_render_count );
+ $this->assertStringNotContainsString( '[example]', $output, 'Expected shortcode to be processed in legacy widget with plugin adding filter' );
+ $this->assertStringContainsString( wpautop( $this->example_shortcode_content ), $output, 'Shortcode was applied *with* wpautop() applying to shortcode output since plugin used legacy filter.' );
+ $this->assertNull( $this->post_during_shortcode );
+ remove_filter( 'widget_text', 'do_shortcode' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'filter' => true,
+ 'visual' => true,
+ )
+ );
+
+ // Visual Text Widget with only core-added widget_text_content filter for do_shortcode().
+ $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ) );
+ $this->assertSame( 11, has_filter( 'widget_text_content', 'do_shortcode' ), 'Expected core to have set do_shortcode as widget_text_content filter.' );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 1, $this->shortcode_render_count );
+ $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
+ $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
+ $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ), 'The widget_text filter still lacks do_shortcode handler.' );
+ $this->assertSame( 11, has_filter( 'widget_text_content', 'do_shortcode' ), 'The widget_text_content filter still has do_shortcode handler.' );
+ $this->assertNull( $this->post_during_shortcode );
+
+ // Visual Text Widget with both filters applied added, one from core and another via plugin.
+ add_filter( 'widget_text', 'do_shortcode' );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 1, $this->shortcode_render_count );
+ $this->assertStringContainsString( $this->example_shortcode_content, $output, 'Shortcode was applied without wpautop corrupting it.' );
+ $this->assertStringNotContainsString( '<p>' . $this->example_shortcode_content . '</p>', $output, 'Expected shortcode_unautop() to have run.' );
+ $this->assertSame( 10, has_filter( 'widget_text', 'do_shortcode' ), 'Expected do_shortcode to be restored to widget_text.' );
+ $this->assertNull( $this->post_during_shortcode );
+ $this->assertNull( $this->post_during_shortcode );
+ remove_filter( 'widget_text', 'do_shortcode' );
+
+ // Visual Text Widget with shortcode handling disabled via plugin removing filter.
+ remove_filter( 'widget_text_content', 'do_shortcode', 11 );
+ remove_filter( 'widget_text', 'do_shortcode' );
+ $this->shortcode_render_count = 0;
+ ob_start();
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertSame( 0, $this->shortcode_render_count );
+ $this->assertStringContainsString( '[example]', $output );
+ $this->assertStringNotContainsString( $this->example_shortcode_content, $output );
+ $this->assertFalse( has_filter( 'widget_text', 'do_shortcode' ) );
+ $this->assertFalse( has_filter( 'widget_text_content', 'do_shortcode' ) );
+ }
+
+ /**
+ * Filters the content of the Text widget.
+ *
+ * @param string $widget_text The widget content.
+ * @param array $instance Array of settings for the current widget.
+ * @param WP_Widget_Text $widget Current Text widget instance.
+ * @return string Widget text.
+ */
+ function filter_widget_text( $widget_text, $instance, $widget ) {
+ $this->widget_text_args = func_get_args();
+
+ $widget_text .= '[filter:widget_text]';
+ return $widget_text;
+ }
+
+ /**
+ * Filters the content of the Text widget to apply changes expected from the visual (TinyMCE) editor.
+ *
+ * @param string $widget_text The widget content.
+ * @param array $instance Array of settings for the current widget.
+ * @param WP_Widget_Text $widget Current Text widget instance.
+ * @return string Widget content.
+ */
+ function filter_widget_text_content( $widget_text, $instance, $widget ) {
+ $this->widget_text_content_args = func_get_args();
+
+ $widget_text .= '[filter:widget_text_content]';
+ return $widget_text;
+ }
+
+ /**
+ * Test is_legacy_instance method.
+ *
+ * @covers WP_Widget_Text::is_legacy_instance
+ */
+ function test_is_legacy_instance() {
+ $widget = new WP_Widget_Text();
+ $base_instance = array(
+ 'title' => 'Title',
+ 'text' => "Hello\n\nWorld",
+ );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'visual' => false,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when visual=false prop is present.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'visual' => true,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when visual=true prop is present.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'filter' => 'content',
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when filter is explicitly content (in WP 4.8.0 only).' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => '',
+ 'filter' => true,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when text is empty.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "\nOne line",
+ 'filter' => false,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when there is leading whitespace.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "\nOne line\n\n",
+ 'filter' => false,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not legacy when there is trailing whitespace.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "One\nTwo",
+ 'filter' => false,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there are line breaks.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "One\n\nTwo",
+ 'filter' => false,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there are paragraph breaks.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "One\nTwo",
+ 'filter' => true,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not automatically legacy when wpautop and there are line breaks.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => "One\n\nTwo",
+ 'filter' => true,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Not automatically legacy when wpautop and there are paragraph breaks.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => 'Test<!-- comment -->',
+ 'filter' => true,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when HTML comment is present.' );
+
+ // Check text examples that will not migrate to TinyMCE.
+ $legacy_text_examples = array(
+ '<span class="hello"></span>',
+ '<blockquote>Quote <footer>Citation</footer></blockquote>',
+ '<img src=\"http://example.com/img.jpg\" border=\"0\" title=\"Example\" /></a>',
+ '<span></span>',
+ "<ul>\n<li><a href=\"#\" class=\"location\"></a>List Item 1</li>\n<li><a href=\"#\" class=\"location\"></a>List Item 2</li>\n</ul>",
+ '<a href="#" class="map"></a>',
+ "<script>\n\\Line one\n\n\\Line two</script>",
+ "<style>body {\ncolor:red;\n}</style>",
+ '<span class="fa fa-cc-discover fa-2x" aria-hidden="true"></span>',
+ "<p>\nStay updated with our latest news and specials. We never sell your information and you can unsubscribe at any time.\n</p>\n\n<div class=\"custom-form-class\">\n\t<form action=\"#\" method=\"post\" name=\"mc-embedded-subscribe-form\">\n\n\t\t<label class=\"screen-reader-text\" for=\"mce-EMAIL-b\">Email </label>\n\t\t<input id=\"mce-EMAIL-b\" class=\"required email\" name=\"EMAIL\" required=\"\" type=\"email\" value=\"\" placeholder=\"Email Address*\" />\n\n\t\t<input class=\"button\" name=\"subscribe\" type=\"submit\" value=\"Go!\" />\n\n\t</form>\n</div>",
+ '<span class="sectiondown"><a href="#front-page-3"><i class="fa fa-chevron-circle-down"></i></a></span>',
+ );
+ foreach ( $legacy_text_examples as $legacy_text_example ) {
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => $legacy_text_example,
+ 'filter' => true,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when wpautop and there is HTML that is not liable to be mutated.' );
+
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => $legacy_text_example,
+ 'filter' => false,
+ )
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ), 'Legacy when not-wpautop and there is HTML that is not liable to be mutated.' );
+ }
+
+ // Check text examples that will migrate to TinyMCE, where elements and attributes are not in the allowed list.
+ $migratable_text_examples = array(
+ 'Check out <a href="http://example.com">Example</a>',
+ '<img src="http://example.com/img.jpg" alt="Img">',
+ '<strong><em>Hello</em></strong>',
+ '<b><i><u><s>Hello</s></u></i></b>',
+ "<ul>\n<li>One</li>\n<li>One</li>\n<li>One</li>\n</ul>",
+ "<ol>\n<li>One</li>\n<li>One</li>\n<li>One</li>\n</ol>",
+ "Text\n<hr>\nAddendum",
+ "Look at this code:\n\n<code>echo 'Hello World!';</code>",
+ );
+ foreach ( $migratable_text_examples as $migratable_text_example ) {
+ $instance = array_merge(
+ $base_instance,
+ array(
+ 'text' => $migratable_text_example,
+ 'filter' => true,
+ )
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ), 'Legacy when wpautop and there is HTML that is not liable to be mutated.' );
+ }
+ }
+
+ /**
+ * Test update method.
+ *
+ * @covers WP_Widget_Text::form
+ */
+ function test_form() {
+ add_filter( 'user_can_richedit', '__return_true' );
+ $widget = new WP_Widget_Text();
+ $widget->_set( 2 );
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => false,
+ 'visual' => false,
+ );
+ $this->assertTrue( $widget->is_legacy_instance( $instance ) );
+ ob_start();
+ $widget->form( $instance );
+ $form = ob_get_clean();
+ $this->assertStringContainsString( 'class="visual" type="hidden" value=""', $form );
+ $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
+
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => 'content',
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ) );
+ ob_start();
+ $widget->form( $instance );
+ $form = ob_get_clean();
+ $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
+ $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
+
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => true,
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ) );
+ ob_start();
+ $widget->form( $instance );
+ $form = ob_get_clean();
+ $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
+ $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
+
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'This is some HTML Code: <code><strong>BOLD!</strong></code>',
+ 'filter' => true,
+ 'visual' => true,
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ) );
+ ob_start();
+ $widget->form( $instance );
+ $form = ob_get_clean();
+ $this->assertStringContainsString( 'class="visual sync-input" type="hidden" value="on"', $form );
+ $this->assertStringContainsString( '<code>&lt;strong&gt;BOLD!', $form );
+ $this->assertStringNotContainsString( 'class="visual sync-input" type="hidden" value=""', $form );
+
+ remove_filter( 'user_can_richedit', '__return_true' );
+ add_filter( 'user_can_richedit', '__return_false' );
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Evil:</textarea><script>alert("XSS")</script>',
+ 'filter' => true,
+ 'visual' => true,
+ );
+ $this->assertFalse( $widget->is_legacy_instance( $instance ) );
+ ob_start();
+ $widget->form( $instance );
+ $form = ob_get_clean();
+ $this->assertStringNotContainsString( 'Evil:</textarea>', $form );
+ $this->assertStringContainsString( 'Evil:</textarea>', $form );
+ }
+
+ /**
+ * Test update method.
+ *
+ * @covers WP_Widget_Text::update
+ */
+ function test_update() {
+ $widget = new WP_Widget_Text();
+ $instance = array(
+ 'title' => "The\nTitle",
+ 'text' => "The\n\nText",
+ 'filter' => true,
+ 'visual' => true,
+ );
+
+ wp_set_current_user(
+ $this->factory()->user->create(
+ array(
+ 'role' => 'administrator',
+ )
+ )
+ );
+
+ $expected = array(
+ 'title' => sanitize_text_field( $instance['title'] ),
+ 'text' => $instance['text'],
+ 'filter' => true,
+ 'visual' => true,
+ );
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $expected, $result );
+ $this->assertNotEmpty( $expected['filter'], 'Expected filter prop to be truthy, to handle case where 4.8 is downgraded to 4.7.' );
+
+ add_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ), 10, 2 );
+ $this->assertTrue( current_user_can( 'unfiltered_html' ) );
+ $instance['text'] = '<script>alert( "Howdy!" );</script>';
+ $expected['text'] = $instance['text'];
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $expected, $result, 'KSES should apply as expected.' );
+ remove_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ) );
+
+ add_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
+ $this->assertFalse( current_user_can( 'unfiltered_html' ) );
+ $instance['text'] = '<script>alert( "Howdy!" );</script>';
+ $expected['text'] = wp_kses_post( $instance['text'] );
+ $result = $widget->update( $instance, array() );
+ $this->assertSame( $expected, $result, 'KSES should not apply since user can unfiltered_html.' );
+ remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10 );
+ }
+
+ /**
+ * Test update for legacy widgets.
+ *
+ * @covers WP_Widget_Text::update
+ */
+ function test_update_legacy() {
+ $widget = new WP_Widget_Text();
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'filter' => false,
+ );
+ $result = $widget->update( $instance, array() );
+ $this->assertSameSets( $instance, $result, 'Updating a widget without visual prop and explicit filter=false leaves visual prop absent' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'filter' => true,
+ );
+ $result = $widget->update( $instance, array() );
+ $this->assertSameSets( $instance, $result, 'Updating a widget without visual prop and explicit filter=true leaves legacy prop absent.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'visual' => true,
+ );
+ $old_instance = array_merge(
+ $instance,
+ array(
+ 'filter' => false,
+ )
+ );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'filter' => true,
+ )
+ );
+ $result = $widget->update( $instance, $old_instance );
+ $this->assertSameSets( $expected, $result, 'Updating a pre-existing widget with visual mode forces filter to be true.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'filter' => true,
+ );
+ $old_instance = array_merge(
+ $instance,
+ array(
+ 'visual' => true,
+ )
+ );
+ $result = $widget->update( $instance, $old_instance );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'visual' => true,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a pre-existing visual widget retains visual mode when updated.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ );
+ $old_instance = array_merge(
+ $instance,
+ array(
+ 'visual' => true,
+ )
+ );
+ $result = $widget->update( $instance, $old_instance );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'visual' => true,
+ 'filter' => true,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a pre-existing visual widget retains visual=true and supplies missing filter=true.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'visual' => true,
+ );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'filter' => true,
+ )
+ );
+ $result = $widget->update( $instance, array() );
+ $this->assertSameSets( $expected, $result, 'Updating a widget with explicit visual=true and absent filter prop causes filter to be set to true.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Legacy',
+ 'text' => 'Text',
+ 'visual' => false,
+ );
+ $result = $widget->update( $instance, array() );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'filter' => false,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a widget in legacy mode results in filter=false as if checkbox not checked.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => false,
+ );
+ $old_instance = array_merge(
+ $instance,
+ array(
+ 'visual' => false,
+ 'filter' => true,
+ )
+ );
+ $result = $widget->update( $instance, $old_instance );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'visual' => false,
+ 'filter' => false,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a widget that previously had legacy form results in filter allowed to be false.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => 'content',
+ );
+ $result = $widget->update( $instance, array() );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'filter' => true,
+ 'visual' => true,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a widget that had \'content\' as its filter value persists non-legacy mode. This only existed in WP 4.8.0.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ );
+ $old_instance = array_merge(
+ $instance,
+ array(
+ 'filter' => 'content',
+ )
+ );
+ $result = $widget->update( $instance, $old_instance );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'visual' => true,
+ 'filter' => true,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a pre-existing widget with the filter=content prop in WP 4.8.0 upgrades to filter=true&visual=true.' );
+
+ // --
+ $instance = array(
+ 'title' => 'Title',
+ 'text' => 'Text',
+ 'filter' => 'content',
+ );
+ $result = $widget->update( $instance, array() );
+ $expected = array_merge(
+ $instance,
+ array(
+ 'filter' => true,
+ 'visual' => true,
+ )
+ );
+ $this->assertSameSets( $expected, $result, 'Updating a widget with filter=content (from WP 4.8.0) upgrades to filter=true&visual=true.' );
+ }
+
+ /**
+ * Grant unfiltered_html cap via map_meta_cap.
+ *
+ * @param array $caps Returns the user's actual capabilities.
+ * @param string $cap Capability name.
+ * @return array Caps.
+ */
+ function grant_unfiltered_html_cap( $caps, $cap ) {
+ if ( 'unfiltered_html' === $cap ) {
+ $caps = array_diff( $caps, array( 'do_not_allow' ) );
+ $caps[] = 'unfiltered_html';
+ }
+ return $caps;
+ }
+
+ /**
+ * Revoke unfiltered_html cap via map_meta_cap.
+ *
+ * @param array $caps Returns the user's actual capabilities.
+ * @param string $cap Capability name.
+ * @return array Caps.
+ */
+ function revoke_unfiltered_html_cap( $caps, $cap ) {
+ if ( 'unfiltered_html' === $cap ) {
+ $caps = array_diff( $caps, array( 'unfiltered_html' ) );
+ $caps[] = 'do_not_allow';
+ }
+ return $caps;
+ }
+
+ /**
+ * Test enqueue_admin_scripts method.
+ *
+ * @covers WP_Widget_Text::enqueue_admin_scripts
+ */
+ function test_enqueue_admin_scripts() {
+ set_current_screen( 'widgets.php' );
+ $widget = new WP_Widget_Text();
+ $widget->enqueue_admin_scripts();
+
+ $this->assertTrue( wp_script_is( 'text-widgets' ) );
+ }
+
+ /**
+ * Test render_control_template_scripts method.
+ *
+ * @covers WP_Widget_Text::render_control_template_scripts
+ */
+ function test_render_control_template_scripts() {
+ ob_start();
+ WP_Widget_Text::render_control_template_scripts();
+ $output = ob_get_clean();
+
+ $this->assertStringContainsString( '<script type="text/html" id="tmpl-widget-text-control-fields">', $output );
+ }
+
+ /**
+ * Ensure that rel="noopener" is added to links with a target.
+ *
+ * @ticket 46421
+ */
+ function test_render_links_with_target() {
+ $widget = new WP_Widget_Text();
+
+ $text = 'Test content with an external <a href="https://example.org" target="_blank">link</a>.';
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => '</h2>',
+ 'before_widget' => '',
+ 'after_widget' => '',
+ );
+
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ );
+
+ $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
+
+ $this->assertStringContainsString( 'rel="noopener"', $output );
+ }
+
+ /**
+ * Ensure that rel="noopener" is not added to links without a target.
+ *
+ * @ticket 46421
+ */
+ function test_render_links_without_target() {
+ $widget = new WP_Widget_Text();
+
+ $text = 'Test content with an internal <a href="/">link</a>.';
+
+ $args = array(
+ 'before_title' => '<h2>',
+ 'after_title' => '</h2>',
+ 'before_widget' => '',
+ 'after_widget' => '',
+ );
+
+ $instance = array(
+ 'title' => 'Foo',
+ 'text' => $text,
+ );
+
+ $output = get_echo( array( $widget, 'widget' ), array( $args, $instance ) );
+
+ $this->assertStringNotContainsString( 'rel="noopener"', $output );
+ }
+}
</ins></span></pre>
</div>
</div>
</body>
</html>