Customize: Add selective refresh framework with implementation for widgets and re-implementation for nav menus.

See https://make.wordpress.org/core/2016/02/16/selective-refresh-in-the-customizer/.

Props westonruter, valendesigns, DrewAPicture, ocean90.
Fixes #27355.


git-svn-id: https://develop.svn.wordpress.org/trunk@36586 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Weston Ruter
2016-02-19 18:40:06 +00:00
parent 29e2274793
commit 03360d143d
23 changed files with 4204 additions and 578 deletions
+1 -1
View File
@@ -425,7 +425,7 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
$data = json_decode( $json, true );
$this->assertNotEmpty( $data );
$this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices' ), array_keys( $data ) );
$this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'selectiveRefreshEnabled' ), array_keys( $data ) );
$this->assertEquals( $autofocus, $data['autofocus'] );
$this->assertArrayHasKey( 'save', $data['nonce'] );
$this->assertArrayHasKey( 'preview', $data['nonce'] );
@@ -69,7 +69,6 @@ class Test_WP_Customize_Nav_Menu_Item_Setting extends WP_UnitTestCase {
$setting = new WP_Customize_Nav_Menu_Item_Setting( $this->wp_customize, 'nav_menu_item[123]' );
$this->assertEquals( 'nav_menu_item', $setting->type );
$this->assertEquals( 'postMessage', $setting->transport );
$this->assertEquals( 123, $setting->post_id );
$this->assertNull( $setting->previous_post_id );
$this->assertNull( $setting->update_status );
+93 -46
View File
@@ -353,11 +353,11 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
$expected = array( 'type' => 'nav_menu_item' );
$results = $menus->filter_dynamic_setting_args( $this->wp_customize, 'nav_menu_item[123]' );
$this->assertEquals( $expected, $results );
$this->assertEquals( $expected['type'], $results['type'] );
$expected = array( 'type' => 'nav_menu' );
$results = $menus->filter_dynamic_setting_args( $this->wp_customize, 'nav_menu[123]' );
$this->assertEquals( $expected, $results );
$this->assertEquals( $expected['type'], $results['type'] );
}
/**
@@ -522,6 +522,28 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
$this->assertContains( 'data-object="custom_object"', $template );
}
/**
* Test WP_Customize_Nav_Menus::customize_dynamic_partial_args().
*
* @see WP_Customize_Nav_Menus::customize_dynamic_partial_args()
*/
function test_customize_dynamic_partial_args() {
do_action( 'customize_register', $this->wp_customize );
$args = apply_filters( 'customize_dynamic_partial_args', false, 'nav_menu_instance[68b329da9893e34099c7d8ad5cb9c940]' );
$this->assertInternalType( 'array', $args );
$this->assertEquals( 'nav_menu_instance', $args['type'] );
$this->assertEquals( array( $this->wp_customize->nav_menus, 'render_nav_menu_partial' ), $args['render_callback'] );
$this->assertTrue( $args['container_inclusive'] );
$args = apply_filters( 'customize_dynamic_partial_args', array( 'fallback_refresh' => false ), 'nav_menu_instance[4099c7d8ad5cb9c94068b329da9893e3]' );
$this->assertInternalType( 'array', $args );
$this->assertEquals( 'nav_menu_instance', $args['type'] );
$this->assertEquals( array( $this->wp_customize->nav_menus, 'render_nav_menu_partial' ), $args['render_callback'] );
$this->assertTrue( $args['container_inclusive'] );
$this->assertFalse( $args['fallback_refresh'] );
}
/**
* Test the customize_preview_init method.
*
@@ -532,13 +554,9 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
$menus->customize_preview_init();
$this->assertEquals( 10, has_action( 'template_redirect', array( $menus, 'render_menu' ) ) );
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $menus, 'customize_preview_enqueue_deps' ) ) );
if ( ! isset( $_REQUEST[ WP_Customize_Nav_Menus::RENDER_QUERY_VAR ] ) ) {
$this->assertEquals( 1000, has_filter( 'wp_nav_menu_args', array( $menus, 'filter_wp_nav_menu_args' ) ) );
$this->assertEquals( 10, has_filter( 'wp_nav_menu', array( $menus, 'filter_wp_nav_menu' ) ) );
}
$this->assertEquals( 1000, has_filter( 'wp_nav_menu_args', array( $menus, 'filter_wp_nav_menu_args' ) ) );
$this->assertEquals( 10, has_filter( 'wp_nav_menu', array( $menus, 'filter_wp_nav_menu' ) ) );
}
/**
@@ -548,37 +566,36 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
*/
function test_filter_wp_nav_menu_args() {
do_action( 'customize_register', $this->wp_customize );
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
$menus = $this->wp_customize->nav_menus;
$results = $menus->filter_wp_nav_menu_args( array(
'echo' => true,
'fallback_cb' => 'wp_page_menu',
'walker' => '',
'menu' => wp_create_nav_menu( 'Foo' ),
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) );
$this->assertEquals( 1, $results['can_partial_refresh'] );
$this->assertArrayHasKey( 'customize_preview_nav_menus_args', $results );
$expected = array(
'echo',
'can_partial_refresh',
'fallback_cb',
'instance_number',
'walker',
);
$results = $menus->filter_wp_nav_menu_args( array(
'echo' => false,
'fallback_cb' => 'wp_page_menu',
'walker' => new Walker_Nav_Menu(),
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) );
$this->assertEqualSets( $expected, array_keys( $results ) );
$this->assertArrayNotHasKey( 'customize_preview_nav_menus_args', $results );
$this->assertEquals( 'wp_page_menu', $results['fallback_cb'] );
$this->assertEquals( 0, $results['can_partial_refresh'] );
$this->assertNotEmpty( $menus->preview_nav_menu_instance_args[ $results['instance_number'] ] );
$preview_nav_menu_instance_args = $menus->preview_nav_menu_instance_args[ $results['instance_number'] ];
$this->assertEquals( '', $preview_nav_menu_instance_args['fallback_cb'] );
$this->assertEquals( '', $preview_nav_menu_instance_args['walker'] );
$this->assertNotEmpty( $preview_nav_menu_instance_args['args_hash'] );
$nav_menu_term = get_term( wp_create_nav_menu( 'Bar' ) );
$results = $menus->filter_wp_nav_menu_args( array(
'echo' => true,
'fallback_cb' => 'wp_page_menu',
'walker' => '',
'menu' => $nav_menu_term,
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) );
$this->assertArrayHasKey( 'customize_preview_nav_menus_args', $results );
$this->assertEquals( $nav_menu_term->term_id, $results['customize_preview_nav_menus_args']['menu'] );
}
/**
@@ -595,19 +612,18 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
'menu' => wp_create_nav_menu( 'Foo' ),
'fallback_cb' => 'wp_page_menu',
'walker' => '',
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) );
ob_start();
wp_nav_menu( $args );
$nav_menu_content = ob_get_clean();
$object_args = json_decode( json_encode( $args ), false );
$result = $menus->filter_wp_nav_menu( $nav_menu_content, $object_args );
$expected = sprintf(
'<div class="partial-refreshable-nav-menu partial-refreshable-nav-menu-%1$d menu">',
$args['instance_number']
);
$this->assertStringStartsWith( $expected, $result );
$result = $menus->filter_wp_nav_menu( $nav_menu_content, (object) $args );
$this->assertContains( sprintf( ' data-customize-partial-id="nav_menu_instance[%s]"', $args['customize_preview_nav_menus_args']['args_hmac'] ), $result );
$this->assertContains( ' data-customize-partial-type="nav_menu_instance"', $result );
$this->assertContains( ' data-customize-partial-placement-context="', $result );
}
/**
@@ -622,31 +638,62 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
$menus->customize_preview_enqueue_deps();
$this->assertTrue( wp_script_is( 'customize-preview-nav-menus' ) );
$this->assertEquals( 10, has_action( 'wp_print_footer_scripts', array( $menus, 'export_preview_data' ) ) );
}
/**
* Test the export_preview_data method.
* Test WP_Customize_Nav_Menus::export_preview_data() method.
*
* @see WP_Customize_Nav_Menus::export_preview_data()
*/
function test_export_preview_data() {
do_action( 'customize_register', $this->wp_customize );
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
$this->setExpectedDeprecated( 'WP_Customize_Nav_Menus::export_preview_data' );
$this->wp_customize->nav_menus->export_preview_data();
}
$request_uri = $_SERVER['REQUEST_URI'];
/**
* Test WP_Customize_Nav_Menus::render_nav_menu_partial() method.
*
* @see WP_Customize_Nav_Menus::render_nav_menu_partial()
*/
function test_render_nav_menu_partial() {
$this->wp_customize->nav_menus->customize_preview_init();
ob_start();
$_SERVER['REQUEST_URI'] = '/wp-admin';
$menus->export_preview_data();
$data = ob_get_clean();
$menu = wp_create_nav_menu( 'Foo' );
wp_update_nav_menu_item( $menu, 0, array(
'menu-item-type' => 'custom',
'menu-item-title' => 'WordPress.org',
'menu-item-url' => 'https://wordpress.org',
'menu-item-status' => 'publish',
) );
$_SERVER['REQUEST_URI'] = $request_uri;
$nav_menu_args = $this->wp_customize->nav_menus->filter_wp_nav_menu_args( array(
'echo' => true,
'menu' => $menu,
'fallback_cb' => 'wp_page_menu',
'walker' => '',
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) );
$this->assertContains( '_wpCustomizePreviewNavMenusExports', $data );
$this->assertContains( 'renderQueryVar', $data );
$this->assertContains( 'renderNonceValue', $data );
$this->assertContains( 'renderNoncePostKey', $data );
$this->assertContains( 'navMenuInstanceArgs', $data );
$partial_id = sprintf( 'nav_menu_instance[%s]', $nav_menu_args['customize_preview_nav_menus_args']['args_hmac'] );
$partials = $this->wp_customize->selective_refresh->add_dynamic_partials( array( $partial_id ) );
$this->assertNotEmpty( $partials );
$partial = array_shift( $partials );
$this->assertEquals( $partial_id, $partial->id );
$missing_args_hmac_args = array_merge(
$nav_menu_args['customize_preview_nav_menus_args'],
array( 'args_hmac' => null )
);
$this->assertFalse( $partial->render( $missing_args_hmac_args ) );
$args_hmac_mismatch_args = array_merge(
$nav_menu_args['customize_preview_nav_menus_args'],
array( 'args_hmac' => strrev( $nav_menu_args['customize_preview_nav_menus_args']['args_hmac'] ) )
);
$this->assertFalse( $partial->render( $args_hmac_mismatch_args ) );
$rendered = $partial->render( $nav_menu_args['customize_preview_nav_menus_args'] );
$this->assertContains( 'data-customize-partial-type="nav_menu_instance"', $rendered );
$this->assertContains( 'WordPress.org', $rendered );
}
}
+311
View File
@@ -0,0 +1,311 @@
<?php
/**
* Test_WP_Customize_Partial tests.
*
* @package WordPress
*/
/**
* Tests for the Test_WP_Customize_Partial class.
*
* @group customize
*/
class Test_WP_Customize_Partial extends WP_UnitTestCase {
/**
* Manager.
*
* @var WP_Customize_Manager
*/
public $wp_customize;
/**
* Component.
*
* @var WP_Customize_Selective_Refresh
*/
public $selective_refresh;
/**
* Set up.
*/
function setUp() {
parent::setUp();
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
// @codingStandardsIgnoreStart
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
// @codingStandardsIgnoreEnd
$this->wp_customize = $GLOBALS['wp_customize'];
if ( isset( $this->wp_customize->selective_refresh ) ) {
$this->selective_refresh = $this->wp_customize->selective_refresh;
}
}
/**
* Test WP_Customize_Partial::__construct().
*
* @see WP_Customize_Partial::__construct()
*/
function test_construct_default_args() {
$partial_id = 'blogname';
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id );
$this->assertEquals( $partial_id, $partial->id );
$this->assertEquals( $this->selective_refresh, $partial->component );
$this->assertEquals( 'default', $partial->type );
$this->assertEmpty( $partial->selector );
$this->assertEquals( array( $partial_id ), $partial->settings );
$this->assertEquals( $partial_id, $partial->primary_setting );
$this->assertEquals( array( $partial, 'render_callback' ), $partial->render_callback );
$this->assertEquals( false, $partial->container_inclusive );
$this->assertEquals( true, $partial->fallback_refresh );
}
/**
* Render post content partial.
*
* @param WP_Customize_Partial $partial Partial.
* @return string|false Content or false if error.
*/
function render_post_content_partial( $partial ) {
$id_data = $partial->id_data();
$post_id = intval( $id_data['keys'][0] );
if ( empty( $post_id ) ) {
return false;
}
$post = get_post( $post_id );
if ( ! $post ) {
return false;
}
return apply_filters( 'the_content', $post->post_content );
}
/**
* Test WP_Customize_Partial::__construct().
*
* @see WP_Customize_Partial::__construct()
*/
function test_construct_non_default_args() {
$post_id = self::factory()->post->create( array(
'post_title' => 'Hello World',
'post_content' => 'Lorem Ipsum',
) );
$partial_id = sprintf( 'post_content[%d]', $post_id );
$args = array(
'type' => 'post',
'selector' => "article.post-$post_id .entry-content",
'settings' => array( 'user[1]', "post[$post_id]" ),
'primary_setting' => "post[$post_id]",
'render_callback' => array( $this, 'render_post_content_partial' ),
'container_inclusive' => false,
'fallback_refresh' => false,
);
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, $args );
$this->assertEquals( $partial_id, $partial->id );
$this->assertEquals( $this->selective_refresh, $partial->component );
$this->assertEquals( $args['type'], $partial->type );
$this->assertEquals( $args['selector'], $partial->selector );
$this->assertEqualSets( $args['settings'], $partial->settings );
$this->assertEquals( $args['primary_setting'], $partial->primary_setting );
$this->assertEquals( $args['render_callback'], $partial->render_callback );
$this->assertEquals( false, $partial->container_inclusive );
$this->assertEquals( false, $partial->fallback_refresh );
$this->assertContains( 'Lorem Ipsum', $partial->render() );
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, array(
'settings' => 'blogdescription',
) );
$this->assertEquals( array( 'blogdescription' ), $partial->settings );
$this->assertEquals( 'blogdescription', $partial->primary_setting );
}
/**
* Test WP_Customize_Partial::id_data().
*
* @see WP_Customize_Partial::id_data()
*/
function test_id_data() {
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo' );
$id_data = $partial->id_data();
$this->assertEquals( 'foo', $id_data['base'] );
$this->assertEquals( array(), $id_data['keys'] );
$partial = new WP_Customize_Partial( $this->selective_refresh, 'bar[baz][quux]' );
$id_data = $partial->id_data();
$this->assertEquals( 'bar', $id_data['base'] );
$this->assertEquals( array( 'baz', 'quux' ), $id_data['keys'] );
}
/**
* Keep track of filter calls to customize_partial_render.
*
* @var int
*/
protected $count_filter_customize_partial_render = 0;
/**
* Keep track of filter calls to customize_partial_render_{$partial->id}.
*
* @var int
*/
protected $count_filter_customize_partial_render_with_id = 0;
/**
* Filter customize_partial_render.
*
* @param string|false $rendered Content.
* @param WP_Customize_Partial $partial Partial.
* @param array $container_context Data.
* @return string|false Content.
*/
function filter_customize_partial_render( $rendered, $partial, $container_context ) {
$this->assertTrue( false === $rendered || is_string( $rendered ) );
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
$this->assertInternalType( 'array', $container_context );
$this->count_filter_customize_partial_render += 1;
return $rendered;
}
/**
* Filter customize_partial_render_{$partial->id}.
*
* @param string|false $rendered Content.
* @param WP_Customize_Partial $partial Partial.
* @param array $container_context Data.
* @return string|false Content.
*/
function filter_customize_partial_render_with_id( $rendered, $partial, $container_context ) {
$this->assertEquals( sprintf( 'customize_partial_render_%s', $partial->id ), current_filter() );
$this->assertTrue( false === $rendered || is_string( $rendered ) );
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
$this->assertInternalType( 'array', $container_context );
$this->count_filter_customize_partial_render_with_id += 1;
return $rendered;
}
/**
* Bad render_callback().
*
* @return string Content.
*/
function render_echo_and_return() {
echo 'foo';
return 'bar';
}
/**
* Echo render_callback().
*/
function render_echo() {
echo 'foo';
}
/**
* Return render_callback().
*
* @return string Content.
*/
function render_return() {
return 'bar';
}
/**
* Test WP_Customize_Partial::render() with a bad return_callback.
*
* @see WP_Customize_Partial::render()
*/
function test_render_bad_callback() {
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
'render_callback' => array( $this, 'render_echo_and_return' ),
) );
$this->setExpectedIncorrectUsage( 'render' );
$partial->render();
}
/**
* Test WP_Customize_Partial::render() with a return_callback that echos.
*
* @see WP_Customize_Partial::render()
*/
function test_render_echo_callback() {
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
'render_callback' => array( $this, 'render_echo' ),
) );
$count_filter_customize_partial_render = $this->count_filter_customize_partial_render;
$count_filter_customize_partial_render_with_id = $this->count_filter_customize_partial_render_with_id;
add_filter( 'customize_partial_render', array( $this, 'filter_customize_partial_render' ), 10, 3 );
add_filter( "customize_partial_render_{$partial->id}", array( $this, 'filter_customize_partial_render_with_id' ), 10, 3 );
$rendered = $partial->render();
$this->assertEquals( 'foo', $rendered );
$this->assertEquals( $count_filter_customize_partial_render + 1, $this->count_filter_customize_partial_render );
$this->assertEquals( $count_filter_customize_partial_render_with_id + 1, $this->count_filter_customize_partial_render_with_id );
}
/**
* Test WP_Customize_Partial::render() with a return_callback that echos.
*
* @see WP_Customize_Partial::render()
*/
function test_render_return_callback() {
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
'render_callback' => array( $this, 'render_return' ),
) );
$count_filter_customize_partial_render = $this->count_filter_customize_partial_render;
$count_filter_customize_partial_render_with_id = $this->count_filter_customize_partial_render_with_id;
add_filter( 'customize_partial_render', array( $this, 'filter_customize_partial_render' ), 10, 3 );
add_filter( "customize_partial_render_{$partial->id}", array( $this, 'filter_customize_partial_render_with_id' ), 10, 3 );
$rendered = $partial->render();
$this->assertEquals( 'bar', $rendered );
$this->assertEquals( $count_filter_customize_partial_render + 1, $this->count_filter_customize_partial_render );
$this->assertEquals( $count_filter_customize_partial_render_with_id + 1, $this->count_filter_customize_partial_render_with_id );
}
/**
* Test WP_Customize_Partial::render_callback() default.
*
* @see WP_Customize_Partial::render_callback()
*/
function test_render_callback_default() {
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo' );
$this->assertFalse( $partial->render_callback() );
$this->assertFalse( call_user_func( $partial->render_callback ) );
}
/**
* Test WP_Customize_Partial::json() default.
*
* @see WP_Customize_Partial::json()
*/
function test_json() {
$post_id = 123;
$partial_id = sprintf( 'post_content[%d]', $post_id );
$args = array(
'type' => 'post',
'selector' => "article.post-$post_id .entry-content",
'settings' => array( 'user[1]', "post[$post_id]" ),
'primary_setting' => "post[$post_id]",
'render_callback' => array( $this, 'render_post_content_partial' ),
'container_inclusive' => false,
'fallback_refresh' => false,
);
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, $args );
$exported = $partial->json();
$this->assertArrayHasKey( 'settings', $exported );
$this->assertArrayHasKey( 'primarySetting', $exported );
$this->assertArrayHasKey( 'selector', $exported );
$this->assertArrayHasKey( 'type', $exported );
$this->assertArrayHasKey( 'fallbackRefresh', $exported );
$this->assertArrayHasKey( 'containerInclusive', $exported );
}
/**
* Tear down.
*/
function tearDown() {
$this->wp_customize = null;
unset( $GLOBALS['wp_customize'] );
parent::tearDown();
}
}
@@ -0,0 +1,449 @@
<?php
/**
* WP_Customize_Selective_Refresh Ajax tests.
*
* @package WordPress
* @subpackage UnitTests
*/
/**
* Tests for the WP_Customize_Selective_Refresh class Ajax.
*
* Note that this is intentionally not extending WP_Ajax_UnitTestCase because it
* is not admin ajax.
*
* @since 4.5.0
* @group ajax
*/
class Test_WP_Customize_Selective_Refresh_Ajax extends WP_UnitTestCase {
/**
* Manager.
*
* @var WP_Customize_Manager
*/
public $wp_customize;
/**
* Component.
*
* @var WP_Customize_Selective_Refresh
*/
public $selective_refresh;
/**
* Set up the test fixture.
*/
function setUp() {
parent::setUp();
// Define DOING_AJAX so that wp_die() will be used instead of die().
if ( ! defined( 'DOING_AJAX' ) ) {
define( 'DOING_AJAX', true );
}
add_filter( 'wp_die_ajax_handler', array( $this, 'get_wp_die_handler' ), 1, 1 );
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
// @codingStandardsIgnoreStart
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
// @codingStandardsIgnoreEnd
$this->wp_customize = $GLOBALS['wp_customize'];
if ( isset( $this->wp_customize->selective_refresh ) ) {
$this->selective_refresh = $this->wp_customize->selective_refresh;
}
}
/**
* Do Customizer boot actions.
*/
function do_customize_boot_actions() {
// Remove actions that call add_theme_support( 'title-tag' ).
remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
remove_action( 'after_setup_theme', 'twentysixteen_setup' );
$_SERVER['REQUEST_METHOD'] = 'POST';
do_action( 'setup_theme' );
do_action( 'after_setup_theme' );
do_action( 'init' );
do_action( 'customize_register', $this->wp_customize );
$this->wp_customize->customize_preview_init();
do_action( 'wp', $GLOBALS['wp'] );
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request().
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_for_unauthenticated_user() {
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
// Check current_user_cannot_customize.
ob_start();
try {
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
unset( $e );
}
$output = json_decode( ob_get_clean(), true );
$this->assertFalse( $output['success'] );
$this->assertEquals( 'expected_customize_preview', $output['data'] );
// Check expected_customize_preview.
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
$_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
ob_start();
try {
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
unset( $e );
}
$output = json_decode( ob_get_clean(), true );
$this->assertFalse( $output['success'] );
$this->assertEquals( 'expected_customize_preview', $output['data'] );
// Check missing_partials.
$this->do_customize_boot_actions();
ob_start();
try {
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
unset( $e );
}
$output = json_decode( ob_get_clean(), true );
$this->assertFalse( $output['success'] );
$this->assertEquals( 'missing_partials', $output['data'] );
// Check missing_partials.
$_POST['partials'] = 'bad';
$this->do_customize_boot_actions();
ob_start();
try {
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$output = json_decode( ob_get_clean(), true );
$this->assertFalse( $output['success'] );
$this->assertEquals( 'malformed_partials', $output['data'] );
}
/**
* Set the current user to be an admin, add the preview nonce, and set the query var.
*/
function setup_valid_render_partials_request_environment() {
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
$_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
$this->do_customize_boot_actions();
}
/**
* Make sure that the Customizer "signature" is not included in partial render responses.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_removes_customize_signature() {
$this->setup_valid_render_partials_request_environment();
$this->assertTrue( is_customize_preview() );
$this->assertEquals( 1000, has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
ob_start();
try {
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
unset( $e );
}
ob_end_clean();
$this->assertFalse( has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for an unrecognized partial.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_for_unrecognized_partial() {
$this->setup_valid_render_partials_request_environment();
$context_data = array();
$placements = array( $context_data );
$_POST['partials'] = wp_slash( wp_json_encode( array(
'foo' => $placements,
) ) );
ob_start();
try {
$this->expected_partial_ids = array( 'foo' );
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$output = json_decode( ob_get_clean(), true );
$this->assertTrue( $output['success'] );
$this->assertInternalType( 'array', $output['data'] );
$this->assertArrayHasKey( 'contents', $output['data'] );
$this->assertArrayHasKey( 'errors', $output['data'] );
$this->assertArrayHasKey( 'foo', $output['data']['contents'] );
$this->assertEquals( null, $output['data']['contents']['foo'] );
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for a partial that does not render.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_for_non_rendering_partial() {
$this->setup_valid_render_partials_request_environment();
$this->wp_customize->selective_refresh->add_partial( 'foo', array( 'settings' => array( 'home' ) ) );
$context_data = array();
$placements = array( $context_data );
$_POST['partials'] = wp_slash( wp_json_encode( array(
'foo' => $placements,
) ) );
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
ob_start();
try {
$this->expected_partial_ids = array( 'foo' );
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
$output = json_decode( ob_get_clean(), true );
$this->assertEquals( array( false ), $output['data']['contents']['foo'] );
}
/**
* Get the rendered blogname.
*
* @param WP_Customize_Partial $partial Partial.
* @param array $context Context data.
* @return string
*/
function render_callback_blogname( $partial, $context ) {
$this->assertInternalType( 'array', $context );
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
return get_bloginfo( 'name', 'display' );
}
/**
* Get the rendered blogdescription.
*
* @param WP_Customize_Partial $partial Partial.
* @param array $context Context data.
* @return string
*/
function render_callback_blogdescription( $partial, $context ) {
$this->assertInternalType( 'array', $context );
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
$x = get_bloginfo( 'description', 'display' );
return $x;
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for a partial that does render.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_with_single_valid_placement() {
$this->setup_valid_render_partials_request_environment();
$this->wp_customize->selective_refresh->add_partial( 'test_blogname', array(
'settings' => array( 'blogname' ),
'render_callback' => array( $this, 'render_callback_blogname' ),
) );
$context_data = array();
$placements = array( $context_data );
$_POST['partials'] = wp_slash( wp_json_encode( array(
'test_blogname' => $placements,
) ) );
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
ob_start();
try {
$this->expected_partial_ids = array( 'test_blogname' );
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
$output = json_decode( ob_get_clean(), true );
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_blogname'] );
}
/**
* Filter customize_dynamic_partial_args.
*
* @param array $partial_args Partial args.
* @param string $partial_id Partial ID.
*
* @return array|false Args.
*/
function filter_customize_dynamic_partial_args( $partial_args, $partial_id ) {
if ( 'test_dynamic_blogname' === $partial_id ) {
$partial_args = array(
'settings' => array( 'blogname' ),
'render_callback' => array( $this, 'render_callback_blogname' ),
);
}
return $partial_args;
}
/**
* Filter customize_render_partials_response.
*
* @param array $response Response.
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
* @param array $partial_placements Placements' context data for the partials rendered in the request.
* The array is keyed by partial ID, with each item being an array of
* the placements' context data.
* @return array Response.
*/
function filter_customize_render_partials_response( $response, $component, $partial_placements ) {
$this->assertInternalType( 'array', $response );
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
if ( isset( $this->expected_partial_ids ) ) {
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
}
return $response;
}
/**
* Expected partial IDs.
*
* @var array
*/
protected $expected_partial_ids;
/**
* Handle 'customize_render_partials_before' action.
*
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
* @param array $partial_placements Partial IDs.
*/
function handle_action_customize_render_partials_after( $component, $partial_placements ) {
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
if ( isset( $this->expected_partial_ids ) ) {
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
}
}
/**
* Handle 'customize_render_partials_after' action.
*
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
* @param array $partial_placements Partial IDs.
*/
function handle_action_customize_render_partials_before( $component, $partial_placements ) {
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
if ( isset( $this->expected_partial_ids ) ) {
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
}
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request()dynamic partials are recognized.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_for_dynamic_partial() {
$this->setup_valid_render_partials_request_environment();
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
$context_data = array();
$placements = array( $context_data );
$_POST['partials'] = wp_slash( wp_json_encode( array(
'test_dynamic_blogname' => $placements,
) ) );
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
ob_start();
try {
$this->expected_partial_ids = array( 'test_dynamic_blogname' );
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
$output = json_decode( ob_get_clean(), true );
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_dynamic_blogname'] );
}
/**
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() to multiple partials can be requested at once.
*
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
*/
function test_handle_render_partials_request_for_multiple_partials_placements() {
$this->setup_valid_render_partials_request_environment();
$this->wp_customize->selective_refresh->add_partial( 'test_blogname', array(
'settings' => array( 'blogname' ),
'render_callback' => array( $this, 'render_callback_blogname' ),
) );
$this->wp_customize->selective_refresh->add_partial( 'test_blogdescription', array(
'settings' => array( 'blogdescription' ),
'render_callback' => array( $this, 'render_callback_blogdescription' ),
) );
$placement_context_data = array();
$_POST['partials'] = wp_slash( wp_json_encode( array(
'test_blogname' => array( $placement_context_data ),
'test_blogdescription' => array( $placement_context_data, $placement_context_data ),
) ) );
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
ob_start();
try {
$this->expected_partial_ids = array( 'test_blogname', 'test_blogdescription' );
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
$this->selective_refresh->handle_render_partials_request();
} catch ( WPDieException $e ) {
$this->assertEquals( '', $e->getMessage() );
}
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
$output = json_decode( ob_get_clean(), true );
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_blogname'] );
$this->assertEquals( array_fill( 0, 2, get_bloginfo( 'description', 'display' ) ), $output['data']['contents']['test_blogdescription'] );
}
/**
* Tear down.
*/
function tearDown() {
$this->expected_partial_ids = null;
$this->wp_customize = null;
unset( $GLOBALS['wp_customize'] );
unset( $GLOBALS['wp_scripts'] );
parent::tearDown();
}
}
@@ -0,0 +1,260 @@
<?php
/**
* WP_Customize_Selective_Refresh tests.
*
* @package WordPress
*/
/**
* Tests for the WP_Customize_Selective_Refresh class.
*
* @group customize
*/
class Test_WP_Customize_Selective_Refresh extends WP_UnitTestCase {
/**
* Manager.
*
* @var WP_Customize_Manager
*/
public $wp_customize;
/**
* Component.
*
* @var WP_Customize_Selective_Refresh
*/
public $selective_refresh;
/**
* Set up the test fixture.
*/
function setUp() {
parent::setUp();
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
// @codingStandardsIgnoreStart
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
// @codingStandardsIgnoreEnd
$this->wp_customize = $GLOBALS['wp_customize'];
if ( isset( $this->wp_customize->selective_refresh ) ) {
$this->selective_refresh = $this->wp_customize->selective_refresh;
}
}
/**
* Test WP_Customize_Selective_Refresh::__construct().
*
* @see WP_Customize_Selective_Refresh::__construct()
*/
function test_construct() {
$this->assertEquals( $this->selective_refresh, $this->wp_customize->selective_refresh );
}
/**
* Test WP_Customize_Selective_Refresh::register_scripts().
*
* @see WP_Customize_Selective_Refresh::register_scripts()
*/
function test_register_scripts() {
$scripts = new WP_Scripts();
$handles = array(
'customize-selective-refresh',
'customize-preview-nav-menus',
'customize-preview-widgets',
);
foreach ( $handles as $handle ) {
$this->assertArrayHasKey( $handle, $scripts->registered );
}
}
/**
* Test WP_Customize_Selective_Refresh::partials().
*
* @see WP_Customize_Selective_Refresh::partials()
*/
function test_partials() {
$this->assertInternalType( 'array', $this->selective_refresh->partials() );
}
/**
* Test CRUD methods for partials.
*
* @see WP_Customize_Selective_Refresh::get_partial()
* @see WP_Customize_Selective_Refresh::add_partial()
* @see WP_Customize_Selective_Refresh::remove_partial()
*/
function test_crud_partial() {
$partial = $this->selective_refresh->add_partial( 'foo' );
$this->assertEquals( $this->selective_refresh, $partial->component );
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
$this->assertEquals( $partial, $this->selective_refresh->get_partial( $partial->id ) );
$this->assertArrayHasKey( $partial->id, $this->selective_refresh->partials() );
$this->selective_refresh->remove_partial( $partial->id );
$this->assertEmpty( $this->selective_refresh->get_partial( $partial->id ) );
$this->assertArrayNotHasKey( $partial->id, $this->selective_refresh->partials() );
$partial = new WP_Customize_Partial( $this->selective_refresh, 'bar' );
$this->assertEquals( $partial, $this->selective_refresh->add_partial( $partial ) );
$this->assertEquals( $partial, $this->selective_refresh->get_partial( 'bar' ) );
$this->assertEqualSets( array( 'bar' ), array_keys( $this->selective_refresh->partials() ) );
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
add_filter( 'customize_dynamic_partial_class', array( $this, 'filter_customize_dynamic_partial_class' ), 10, 3 );
$partial = $this->selective_refresh->add_partial( 'recognized-class' );
$this->assertInstanceOf( 'Tested_Custom_Partial', $partial );
$this->assertEquals( '.recognized', $partial->selector );
}
/**
* Test WP_Customize_Selective_Refresh::init_preview().
*
* @see WP_Customize_Selective_Refresh::init_preview()
*/
function test_init_preview() {
$this->selective_refresh->init_preview();
$this->assertEquals( 10, has_action( 'template_redirect', array( $this->selective_refresh, 'handle_render_partials_request' ) ) );
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $this->selective_refresh, 'enqueue_preview_scripts' ) ) );
}
/**
* Test WP_Customize_Selective_Refresh::enqueue_preview_scripts().
*
* @see WP_Customize_Selective_Refresh::enqueue_preview_scripts()
*/
function test_enqueue_preview_scripts() {
$scripts = wp_scripts();
$this->assertNotContains( 'customize-selective-refresh', $scripts->queue );
$this->selective_refresh->enqueue_preview_scripts();
$this->assertContains( 'customize-selective-refresh', $scripts->queue );
$this->assertEquals( 1000, has_action( 'wp_footer', array( $this->selective_refresh, 'export_preview_data' ) ) );
}
/**
* Test WP_Customize_Selective_Refresh::export_preview_data().
*
* @see WP_Customize_Selective_Refresh::export_preview_data()
*/
function test_export_preview_data() {
$this->selective_refresh->add_partial( 'blogname', array(
'selector' => '#site-title',
) );
ob_start();
$this->selective_refresh->export_preview_data();
$html = ob_get_clean();
$this->assertTrue( (bool) preg_match( '/_customizePartialRefreshExports = ({.+})/s', $html, $matches ) );
$exported_data = json_decode( $matches[1], true );
$this->assertInternalType( 'array', $exported_data );
$this->assertArrayHasKey( 'partials', $exported_data );
$this->assertInternalType( 'array', $exported_data['partials'] );
$this->assertArrayHasKey( 'blogname', $exported_data['partials'] );
$this->assertEquals( '#site-title', $exported_data['partials']['blogname']['selector'] );
$this->assertArrayHasKey( 'renderQueryVar', $exported_data );
$this->assertArrayHasKey( 'l10n', $exported_data );
}
/**
* Test WP_Customize_Selective_Refresh::add_dynamic_partials().
*
* @see WP_Customize_Selective_Refresh::add_dynamic_partials()
*/
function test_add_dynamic_partials() {
$partial_ids = array( 'recognized', 'recognized-class', 'unrecognized', 'already-added' );
$partials = $this->selective_refresh->add_dynamic_partials( $partial_ids );
$this->assertEmpty( $partials );
$this->selective_refresh->add_partial( 'already-added' );
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
add_filter( 'customize_dynamic_partial_class', array( $this, 'filter_customize_dynamic_partial_class' ), 10, 3 );
$partials = $this->selective_refresh->add_dynamic_partials( $partial_ids );
$this->assertEqualSets( array( 'recognized', 'recognized-class' ), wp_list_pluck( $partials, 'id' ) );
$this->assertInstanceOf( 'Tested_Custom_Partial', $this->selective_refresh->get_partial( 'recognized-class' ) );
$this->assertNotInstanceOf( 'Tested_Custom_Partial', $this->selective_refresh->get_partial( 'recognized' ) );
$this->assertEquals( '.recognized', $this->selective_refresh->get_partial( 'recognized' )->selector );
}
/**
* Filter customize_dynamic_partial_args.
*
* @see Test_WP_Customize_Selective_Refresh::test_add_dynamic_partials()
*
* @param false|array $partial_args The arguments to the WP_Customize_Partial constructor.
* @param string $partial_id ID for dynamic partial.
* @return false|array $args Dynamic partial args.
*/
function filter_customize_dynamic_partial_args( $partial_args, $partial_id ) {
$this->assertTrue( false === $partial_args || is_array( $partial_args ) );
$this->assertInternalType( 'string', $partial_id );
if ( preg_match( '/^recognized/', $partial_id ) ) {
$partial_args = array(
'selector' => '.recognized',
);
}
return $partial_args;
}
/**
* Filter customize_dynamic_partial_class.
*
* @see Test_WP_Customize_Selective_Refresh::test_add_dynamic_partials()
*
* @param string $partial_class WP_Customize_Partial or a subclass.
* @param string $partial_id ID for dynamic partial.
* @param array $partial_args The arguments to the WP_Customize_Partial constructor.
* @return string
*/
function filter_customize_dynamic_partial_class( $partial_class, $partial_id, $partial_args ) {
$this->assertInternalType( 'array', $partial_args );
$this->assertInternalType( 'string', $partial_id );
$this->assertInternalType( 'string', $partial_class );
if ( 'recognized-class' === $partial_id ) {
$partial_class = 'Tested_Custom_Partial';
}
return $partial_class;
}
/**
* Test WP_Customize_Selective_Refresh::is_render_partials_request().
*
* @see WP_Customize_Selective_Refresh::is_render_partials_request()
*/
function test_is_render_partials_request() {
$this->assertFalse( $this->selective_refresh->is_render_partials_request() );
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
$this->assertTrue( $this->selective_refresh->is_render_partials_request() );
}
/**
* Tear down.
*/
function tearDown() {
$this->wp_customize = null;
unset( $GLOBALS['wp_customize'] );
unset( $GLOBALS['wp_scripts'] );
parent::tearDown();
}
}
require_once ABSPATH . WPINC . '/customize/class-wp-customize-partial.php';
/**
* Class Tested_Custom_Partial
*/
class Tested_Custom_Partial extends WP_Customize_Partial {
/**
* Type.
*
* @var string
*/
public $type = 'custom';
}
+145 -2
View File
@@ -39,6 +39,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
// @todo We should not be including a theme anyway
remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
remove_action( 'after_setup_theme', 'twentysixteen_setup' );
remove_action( 'customize_register', 'twentysixteen_customize_register', 11 );
$user_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
wp_set_current_user( $user_id );
@@ -121,7 +122,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
$default_args = array(
'type' => 'option',
'capability' => 'edit_theme_options',
'transport' => 'refresh',
'transport' => 'postMessage',
'default' => array(),
'sanitize_callback' => array( $this->manager->widgets, 'sanitize_widget_instance' ),
'sanitize_js_callback' => array( $this->manager->widgets, 'sanitize_widget_js_instance' ),
@@ -150,7 +151,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
$default_args = array(
'type' => 'option',
'capability' => 'edit_theme_options',
'transport' => 'refresh',
'transport' => 'postMessage',
'default' => array(),
'sanitize_callback' => array( $this->manager->widgets, 'sanitize_sidebar_widgets' ),
'sanitize_js_callback' => array( $this->manager->widgets, 'sanitize_sidebar_widgets_js_instance' ),
@@ -346,4 +347,146 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
$this->assertArrayHasKey( 'is_widget_customizer_js_value', $post_value );
$this->assertEquals( $post_value, $this->manager->widgets->sanitize_widget_js_instance( $instance ) );
}
/**
* Test WP_Customize_Widgets::customize_dynamic_partial_args().
*
* @see WP_Customize_Widgets::customize_dynamic_partial_args()
*/
function test_customize_dynamic_partial_args() {
do_action( 'customize_register', $this->manager );
$args = apply_filters( 'customize_dynamic_partial_args', false, 'widget[search-2]' );
$this->assertInternalType( 'array', $args );
$this->assertEquals( 'widget', $args['type'] );
$this->assertEquals( array( $this->manager->widgets, 'render_widget_partial' ), $args['render_callback'] );
$this->assertTrue( $args['container_inclusive'] );
$args = apply_filters( 'customize_dynamic_partial_args', array( 'fallback_refresh' => false ), 'widget[search-2]' );
$this->assertInternalType( 'array', $args );
$this->assertEquals( 'widget', $args['type'] );
$this->assertEquals( array( $this->manager->widgets, 'render_widget_partial' ), $args['render_callback'] );
$this->assertTrue( $args['container_inclusive'] );
$this->assertFalse( $args['fallback_refresh'] );
}
/**
* Test WP_Customize_Widgets::selective_refresh_init().
*
* @see WP_Customize_Widgets::selective_refresh_init()
*/
function test_selective_refresh_init() {
$this->manager->widgets->selective_refresh_init();
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $this->manager->widgets, 'customize_preview_enqueue_deps' ) ) );
$this->assertEquals( 10, has_action( 'dynamic_sidebar_before', array( $this->manager->widgets, 'start_dynamic_sidebar' ) ) );
$this->assertEquals( 10, has_action( 'dynamic_sidebar_after', array( $this->manager->widgets, 'end_dynamic_sidebar' ) ) );
$this->assertEquals( 10, has_filter( 'dynamic_sidebar_params', array( $this->manager->widgets, 'filter_dynamic_sidebar_params' ) ) );
$this->assertEquals( 10, has_filter( 'wp_kses_allowed_html', array( $this->manager->widgets, 'filter_wp_kses_allowed_data_attributes' ) ) );
}
/**
* Test WP_Customize_Widgets::customize_preview_enqueue_deps().
*
* @see WP_Customize_Widgets::customize_preview_enqueue_deps()
*/
function test_customize_preview_enqueue_deps() {
$this->manager->widgets->customize_preview_enqueue_deps();
$this->assertTrue( wp_script_is( 'customize-preview-widgets', 'enqueued' ) );
$this->assertTrue( wp_style_is( 'customize-preview', 'enqueued' ) );
$script = wp_scripts()->registered['customize-preview-widgets'];
$this->assertContains( 'customize-selective-refresh', $script->deps );
}
/**
* Test extensions to dynamic_sidebar().
*
* @see WP_Customize_Widgets::filter_dynamic_sidebar_params()
* @see WP_Customize_Widgets::start_dynamic_sidebar()
* @see WP_Customize_Widgets::end_dynamic_sidebar()
*/
function test_filter_dynamic_sidebar_params() {
global $wp_registered_sidebars;
register_sidebar( array(
'id' => 'foo',
) );
$this->manager->widgets->selective_refresh_init();
$params = array(
array_merge(
$wp_registered_sidebars['foo'],
array(
'widget_id' => 'search-2',
)
),
array(),
);
$this->assertEquals( $params, $this->manager->widgets->filter_dynamic_sidebar_params( $params ), 'Expected short-circuit if not called after dynamic_sidebar_before.' );
ob_start();
do_action( 'dynamic_sidebar_before', 'foo' );
$output = ob_get_clean();
$this->assertEquals( '<!--dynamic_sidebar_before:foo:1-->', trim( $output ) );
$bad_params = $params;
unset( $bad_params[0]['id'] );
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
$bad_params = $params;
$bad_params[0]['id'] = 'non-existing';
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
$bad_params = $params;
$bad_params[0]['before_widget'] = ' <oops>';
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
$filtered_params = $this->manager->widgets->filter_dynamic_sidebar_params( $params );
$this->assertNotEquals( $params, $filtered_params );
ob_start();
do_action( 'dynamic_sidebar_after', 'foo' );
$output = ob_get_clean();
$this->assertEquals( '<!--dynamic_sidebar_after:foo:1-->', trim( $output ) );
$output = wp_kses_post( $filtered_params[0]['before_widget'] );
$this->assertContains( 'data-customize-partial-id="widget[search-2]"', $output );
$this->assertContains( 'data-customize-partial-type="widget"', $output );
}
/**
* Test WP_Customize_Widgets::render_widget_partial() method.
*
* @see WP_Customize_Widgets::render_widget_partial()
*/
function test_render_widget_partial() {
$this->manager->widgets->selective_refresh_init();
$partial_id = 'widget[search-2]';
$partials = $this->manager->selective_refresh->add_dynamic_partials( array( $partial_id ) );
$this->assertNotEmpty( $partials );
$partial = array_shift( $partials );
$this->assertEquals( $partial_id, $partial->id );
$this->assertFalse( $this->manager->widgets->render_widget_partial( $partial, array() ) );
$this->assertFalse( $this->manager->widgets->render_widget_partial( $partial, array( 'sidebar_id' => 'non-existing' ) ) );
$output = $this->manager->widgets->render_widget_partial( $partial, array( 'sidebar_id' => 'sidebar-1' ) );
$this->assertEquals( 1, substr_count( $output, 'data-customize-partial-id' ) );
$this->assertEquals( 1, substr_count( $output, 'data-customize-partial-type="widget"' ) );
$this->assertContains( ' id="search-2"', $output );
}
/**
* Test deprecated methods.
*/
public function test_deprecated_methods() {
$this->setExpectedDeprecated( 'WP_Customize_Widgets::setup_widget_addition_previews' );
$this->setExpectedDeprecated( 'WP_Customize_Widgets::prepreview_added_sidebars_widgets' );
$this->setExpectedDeprecated( 'WP_Customize_Widgets::prepreview_added_widget_instance' );
$this->setExpectedDeprecated( 'WP_Customize_Widgets::remove_prepreview_filters' );
$this->manager->widgets->setup_widget_addition_previews();
$this->manager->widgets->prepreview_added_sidebars_widgets();
$this->manager->widgets->prepreview_added_widget_instance();
$this->manager->widgets->remove_prepreview_filters();
}
}