WordPress.org

Make WordPress Core

Ticket #36944: 36944.3.diff

File 36944.3.diff, 23.7 KB (added by westonruter, 5 years ago)

https://github.com/xwp/wordpress-develop/pull/151/commits/e4279662ed6c5440a309d1c2daa168db39558640

  • src/wp-admin/js/customize-controls.js

    diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
    index 2a5a5b9..c5c41c2 100644
     
    4343                                case 'postMessage':
    4444                                        return this.previewer.send( 'setting', [ this.id, this() ] );
    4545                        }
     46                },
     47
     48                /**
     49                 * Find controls associated with this setting.
     50                 *
     51                 * @since 4.6.0
     52                 * @returns {wp.customize.Control[]} Controls associated with setting.
     53                 */
     54                findControls: function() {
     55                        var setting = this, controls = [];
     56                        api.control.each( function( control ) {
     57                                _.each( control.settings, function( controlSetting ) {
     58                                        if ( controlSetting.id === setting.id ) {
     59                                                controls.push( control );
     60                                        }
     61                                } );
     62                        } );
     63                        return controls;
    4664                }
    4765        });
    4866
     
    15431561
    15441562                                        control.setting = control.settings['default'] || null;
    15451563
     1564                                        // Add setting notifications to the control notification.
    15461565                                        _.each( control.settings, function( setting ) {
    15471566                                                setting.notifications.bind( 'add', function( settingNotification ) {
    1548                                                         var controlNotification = new api.Notification( setting.id + ':' + settingNotification.code, settingNotification );
     1567                                                        var controlNotification, code, params;
     1568                                                        code = setting.id + ':' + settingNotification.code;
     1569                                                        params = _.extend(
     1570                                                                {},
     1571                                                                settingNotification,
     1572                                                                {
     1573                                                                        setting: setting.id
     1574                                                                }
     1575                                                        );
     1576                                                        controlNotification = new api.Notification( code, params );
    15491577                                                        control.notifications.add( controlNotification.code, controlNotification );
    15501578                                                } );
    15511579                                                setting.notifications.bind( 'remove', function( settingNotification ) {
     
    29082936                                                }
    29092937                                        } );
    29102938                                } );
     2939
     2940                                if ( data.settingValidities ) {
     2941                                        api._handleSettingValidities( {
     2942                                                settingValidities: data.settingValidities,
     2943                                                focusInvalidControl: false
     2944                                        } );
     2945                                }
    29112946                        } );
    29122947
    29132948                        this.request = $.ajax( this.previewUrl(), {
     
    34303465                                };
    34313466                        },
    34323467
    3433                         /**
    3434                          * Handle invalid_settings in an error response for the customize-save request.
    3435                          *
    3436                          * Add notifications to the settings and focus on the first control that has an invalid setting.
    3437                          *
    3438                          * @since 4.6.0
    3439                          * @private
    3440                          *
    3441                          * @param {object} response
    3442                          * @param {object} response.invalid_settings
    3443                          * @returns {void}
    3444                          */
    3445                         _handleInvalidSettingsError: function( response ) {
    3446                                 var invalidControls = [], wasFocused = false;
    3447                                 if ( _.isEmpty( response.invalid_settings ) ) {
    3448                                         return;
    3449                                 }
    3450 
    3451                                 // Find the controls that correspond to each invalid setting.
    3452                                 _.each( response.invalid_settings, function( notifications, settingId ) {
    3453                                         var setting = api( settingId );
    3454                                         if ( setting ) {
    3455                                                 _.each( notifications, function( notificationParams, code ) {
    3456                                                         var notification = new api.Notification( code, notificationParams );
    3457                                                         setting.notifications.add( code, notification );
    3458                                                 } );
    3459                                         }
    3460 
    3461                                         api.control.each( function( control ) {
    3462                                                 _.each( control.settings, function( controlSetting ) {
    3463                                                         if ( controlSetting.id === settingId ) {
    3464                                                                 invalidControls.push( control );
    3465                                                         }
    3466                                                 } );
    3467                                         } );
    3468                                 } );
    3469 
    3470                                 // Focus on the first control that is inside of an expanded section (one that is visible).
    3471                                 _( invalidControls ).find( function( control ) {
    3472                                         var isExpanded = control.section() && api.section.has( control.section() ) && api.section( control.section() ).expanded();
    3473                                         if ( isExpanded && control.expanded ) {
    3474                                                 isExpanded = control.expanded();
    3475                                         }
    3476                                         if ( isExpanded ) {
    3477                                                 control.focus();
    3478                                                 wasFocused = true;
    3479                                         }
    3480                                         return wasFocused;
    3481                                 } );
    3482 
    3483                                 // Focus on the first invalid control.
    3484                                 if ( ! wasFocused && invalidControls[0] ) {
    3485                                         invalidControls[0].focus();
    3486                                 }
    3487                         },
    3488 
    34893468                        save: function() {
    34903469                                var self = this,
    34913470                                        processing = api.state( 'processing' ),
    34923471                                        submitWhenDoneProcessing,
    34933472                                        submit,
    3494                                         modifiedWhileSaving = {};
     3473                                        modifiedWhileSaving = {},
     3474                                        invalidSettings = [],
     3475                                        invalidControls;
    34953476
    34963477                                body.addClass( 'saving' );
    34973478
     
    35023483
    35033484                                submit = function () {
    35043485                                        var request, query;
     3486
     3487                                        /*
     3488                                         * Block saving if there are any settings that are marked as
     3489                                         * invalid from the client (not from the server). Focus on
     3490                                         * the control.
     3491                                         */
     3492                                        api.each( function( setting ) {
     3493                                                setting.notifications.each( function( notification ) {
     3494                                                        if ( 'error' === notification.type && ( ! notification.data || ! notification.data.from_server ) ) {
     3495                                                                invalidSettings.push( setting.id );
     3496                                                        }
     3497                                                } );
     3498                                        } );
     3499                                        invalidControls = api.findControlsForSettings( invalidSettings );
     3500                                        if ( ! _.isEmpty( invalidControls ) ) {
     3501                                                _.values( invalidControls )[0][0].focus();
     3502                                                body.removeClass( 'saving' );
     3503                                                api.unbind( 'change', captureSettingModifiedDuringSave );
     3504                                                return;
     3505                                        }
     3506
    35053507                                        query = $.extend( self.query(), {
    35063508                                                nonce:  self.nonce.save
    35073509                                        } );
     
    35123514
    35133515                                        api.trigger( 'save', request );
    35143516
    3515                                         /*
    3516                                          * Remove all setting error notifications prior to save, allowing
    3517                                          * server to respond with fresh validation error notifications.
    3518                                          */
    3519                                         api.each( function( setting ) {
    3520                                                 setting.notifications.each( function( notification ) {
    3521                                                         if ( 'error' === notification.type ) {
    3522                                                                 setting.notifications.remove( notification.code );
    3523                                                         }
    3524                                                 } );
    3525                                         } );
    3526 
    35273517                                        request.always( function () {
    35283518                                                body.removeClass( 'saving' );
    35293519                                                saveBtn.prop( 'disabled', false );
     
    35483538                                                        } );
    35493539                                                }
    35503540
    3551                                                 self._handleInvalidSettingsError( response );
     3541                                                if ( response.setting_validities ) {
     3542                                                        api._handleSettingValidities( {
     3543                                                                settingValidities: response.setting_validities,
     3544                                                                focusInvalidControl: true
     3545                                                        } );
     3546                                                }
    35523547
    35533548                                                api.trigger( 'error', response );
    35543549                                        } );
     
    35643559
    35653560                                                api.previewer.send( 'saved', response );
    35663561
     3562                                                if ( response.setting_validities ) {
     3563                                                        api._handleSettingValidities( {
     3564                                                                settingValidities: response.setting_validities,
     3565                                                                focusInvalidControl: true
     3566                                                        } );
     3567                                                }
     3568
    35673569                                                api.trigger( 'saved', response );
    35683570
    35693571                                                // Restore the global dirty state if any settings were modified during save.
     
    36703672                });
    36713673
    36723674                /**
     3675                 * Handle setting_validities in an error response for the customize-save request.
     3676                 *
     3677                 * Add notifications to the settings and focus on the first control that has an invalid setting.
     3678                 *
     3679                 * @since 4.6.0
     3680                 * @private
     3681                 *
     3682                 * @param {object}  args
     3683                 * @param {object}  args.settingValidities
     3684                 * @param {boolean} [args.focusInvalidControl=false]
     3685                 * @returns {void}
     3686                 */
     3687                api._handleSettingValidities = function handleSettingValidities( args ) {
     3688                        var invalidSettingControls, invalidSettings = [], wasFocused = false;
     3689
     3690                        // Find the controls that correspond to each invalid setting.
     3691                        _.each( args.settingValidities, function( validity, settingId ) {
     3692                                var setting = api( settingId );
     3693                                if ( setting ) {
     3694
     3695                                        // Add notifications for invalidities.
     3696                                        if ( _.isObject( validity ) ) {
     3697                                                _.each( validity, function( params, code ) {
     3698                                                        var notification = new api.Notification( code, params ), existingNotification, needsReplacement = false;
     3699
     3700                                                        // Remove existing notification if already exists for code but differs in parameters.
     3701                                                        existingNotification = setting.notifications( notification.code );
     3702                                                        if ( existingNotification ) {
     3703                                                                needsReplacement = ( notification.type !== existingNotification.type ) || ! _.isEqual( notification.data, existingNotification.data );
     3704                                                        }
     3705                                                        if ( needsReplacement ) {
     3706                                                                setting.notifications.remove( code );
     3707                                                        }
     3708
     3709                                                        if ( ! setting.notifications.has( notification.code ) ) {
     3710                                                                setting.notifications.add( code, notification );
     3711                                                        }
     3712                                                        invalidSettings.push( setting.id );
     3713                                                } );
     3714                                        }
     3715
     3716                                        // Remove notification errors that are no longer valid.
     3717                                        setting.notifications.each( function( notification ) {
     3718                                                if ( 'error' === notification.type && ( true === validity || ! validity[ notification.code ] ) ) {
     3719                                                        setting.notifications.remove( notification.code );
     3720                                                }
     3721                                        } );
     3722                                }
     3723                        } );
     3724
     3725                        if ( args.focusInvalidControl ) {
     3726                                invalidSettingControls = api.findControlsForSettings( invalidSettings );
     3727
     3728                                // Focus on the first control that is inside of an expanded section (one that is visible).
     3729                                _( _.values( invalidSettingControls ) ).find( function( controls ) {
     3730                                        return _( controls ).find( function( control ) {
     3731                                                var isExpanded = control.section() && api.section.has( control.section() ) && api.section( control.section() ).expanded();
     3732                                                if ( isExpanded && control.expanded ) {
     3733                                                        isExpanded = control.expanded();
     3734                                                }
     3735                                                if ( isExpanded ) {
     3736                                                        control.focus();
     3737                                                        wasFocused = true;
     3738                                                }
     3739                                                return wasFocused;
     3740                                        } );
     3741                                } );
     3742
     3743                                // Focus on the first invalid control.
     3744                                if ( ! wasFocused && ! _.isEmpty( invalidSettingControls ) ) {
     3745                                        _.values( invalidSettingControls )[0][0].focus();
     3746                                }
     3747                        }
     3748                };
     3749
     3750                /**
     3751                 * Find all controls associated with the given settings.
     3752                 *
     3753                 * @since 4.6.0
     3754                 * @param {string[]} settingIds Setting IDs.
     3755                 * @returns {object<string, wp.customize.Control>} Mapping setting ids to arrays of controls.
     3756                 */
     3757                api.findControlsForSettings = function findControlsForSettings( settingIds ) {
     3758                        var controls = {}, settingControls;
     3759                        _.each( _.unique( settingIds ), function( settingId ) {
     3760                                var setting = api( settingId );
     3761                                if ( setting ) {
     3762                                        settingControls = setting.findControls();
     3763                                        if ( settingControls && settingControls.length > 0 ) {
     3764                                                controls[ settingId ] = settingControls;
     3765                                        }
     3766                                }
     3767                        } );
     3768                        return controls;
     3769                };
     3770
     3771                /**
    36733772                 * Sort panels, sections, controls by priorities. Hide empty sections and panels.
    36743773                 *
    36753774                 * @since 4.1.0
     
    40404139                        });
    40414140                });
    40424141
     4142                // Update the setting validities.
     4143                api.previewer.bind( 'selective-refresh-setting-validities', function handleSelectiveRefreshedSettingValidities( settingValidities ) {
     4144                        api._handleSettingValidities( {
     4145                                settingValidities: settingValidities,
     4146                                focusInvalidControl: false
     4147                        } );
     4148                } );
     4149
    40434150                // Focus on the control that is associated with the given setting.
    40444151                api.previewer.bind( 'focus-control-for-setting', function( settingId ) {
    40454152                        var matchedControl;
  • src/wp-includes/class-wp-customize-manager.php

    diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
    index f89887e..63d9f1d 100644
    final class WP_Customize_Manager { 
    825825         * @since 3.4.0
    826826         */
    827827        public function customize_preview_settings() {
     828                $setting_validities = $this->validate_setting_values( $this->unsanitized_post_values() );
     829                $exported_setting_validities = array_map( array( $this, 'prepare_setting_validity_for_js' ), $setting_validities );
     830
    828831                $settings = array(
    829832                        'theme' => array(
    830833                                'stylesheet' => $this->get_stylesheet(),
    final class WP_Customize_Manager { 
    837840                        'activePanels' => array(),
    838841                        'activeSections' => array(),
    839842                        'activeControls' => array(),
     843                        'settingValidities' => $exported_setting_validities,
    840844                        'nonce' => $this->get_nonces(),
    841845                        'l10n' => array(
    842846                                'shiftClickToEdit' => __( 'Shift-click to edit this element.' ),
    final class WP_Customize_Manager { 
    991995         * @since 4.6.0
    992996         * @access public
    993997         * @see WP_REST_Request::has_valid_params()
     998         * @see WP_Customize_Setting::validate()
    994999         *
    9951000         * @param array $setting_values Mapping of setting IDs to values to sanitize and validate.
    996          * @return array Empty array if all settings were valid. One or more instances of `WP_Error` if any were invalid.
     1001         * @return array Mapping of setting IDs to return value of validate method calls, either `true` or `WP_Error`.
    9971002         */
    9981003        public function validate_setting_values( $setting_values ) {
    999                 $validity_errors = array();
     1004                $validities = array();
    10001005                foreach ( $setting_values as $setting_id => $unsanitized_value ) {
    10011006                        $setting = $this->get_setting( $setting_id );
    10021007                        if ( ! $setting || is_null( $unsanitized_value ) ) {
    final class WP_Customize_Manager { 
    10061011                        if ( false === $validity || null === $validity ) {
    10071012                                $validity = new WP_Error( 'invalid_value', __( 'Invalid value.' ) );
    10081013                        }
    1009                         if ( is_wp_error( $validity ) ) {
    1010                                 $validity_errors[ $setting_id ] = $validity;
     1014                        $validities[ $setting_id ] = $validity;
     1015                }
     1016                return $validities;
     1017        }
     1018
     1019        /**
     1020         * Prepare setting validity for exporting to the client (JS).
     1021         *
     1022         * Converts `WP_Error` instance into array suitable for passing into the
     1023         * `wp.customize.Notification` JS model.
     1024         *
     1025         * @since 4.6.0
     1026         * @access public
     1027         *
     1028         * @param true|WP_Error $validity Setting validity.
     1029         * @return true|array If `$validity` was `WP_Error` then array mapping the error
     1030         *                    codes to their respective `message` and `data` to pass
     1031         *                    into the `wp.customize.Notification` JS model.
     1032         */
     1033        public function prepare_setting_validity_for_js( $validity ) {
     1034                if ( is_wp_error( $validity ) ) {
     1035                        $notification = array();
     1036                        foreach ( $validity->errors as $error_code => $error_messages ) {
     1037                                $error_data = $validity->get_error_data( $error_code );
     1038                                if ( is_null( $error_data ) ) {
     1039                                        $error_data = array();
     1040                                }
     1041                                $error_data = array_merge(
     1042                                        $error_data,
     1043                                        array( 'from_server' => true )
     1044                                );
     1045                                $notification[ $error_code ] = array(
     1046                                        'message' => join( ' ', $error_messages ),
     1047                                        'data' => $error_data,
     1048                                );
    10111049                        }
     1050                        return $notification;
     1051                } else {
     1052                        return true;
    10121053                }
    1013                 return $validity_errors;
    10141054        }
    10151055
    10161056        /**
    final class WP_Customize_Manager { 
    10411081                do_action( 'customize_save_validation_before', $this );
    10421082
    10431083                // Validate settings.
    1044                 $validity_errors = $this->validate_setting_values( $this->unsanitized_post_values() );
    1045                 $invalid_count = count( $validity_errors );
    1046                 if ( $invalid_count > 0 ) {
    1047                         $settings_errors = array();
    1048                         foreach ( $validity_errors as $setting_id => $validity_error ) {
    1049                                 $settings_errors[ $setting_id ] = array();
    1050                                 foreach ( $validity_error->errors as $error_code => $error_messages ) {
    1051                                         $settings_errors[ $setting_id ][ $error_code ] = array(
    1052                                                 'message' => join( ' ', $error_messages ),
    1053                                                 'data' => $validity_error->get_error_data( $error_code ),
    1054                                         );
    1055                                 }
    1056                         }
     1084                $setting_validities = $this->validate_setting_values( $this->unsanitized_post_values() );
     1085                $invalid_setting_count = count( array_filter( $setting_validities, 'is_wp_error' ) );
     1086                $exported_setting_validities = array_map( array( $this, 'prepare_setting_validity_for_js' ), $setting_validities );
     1087                if ( $invalid_setting_count > 0 ) {
    10571088                        $response = array(
    1058                                 'invalid_settings' => $settings_errors,
    1059                                 'message' => sprintf( _n( 'There is %s invalid setting.', 'There are %s invalid settings.', $invalid_count ), number_format_i18n( $invalid_count ) ),
     1089                                'setting_validities' => $exported_setting_validities,
     1090                                'message' => sprintf( _n( 'There is %s invalid setting.', 'There are %s invalid settings.', $invalid_setting_count ), number_format_i18n( $invalid_setting_count ) ),
    10601091                        );
    10611092
    10621093                        /** This filter is documented in wp-includes/class-wp-customize-manager.php */
    final class WP_Customize_Manager { 
    10971128                 */
    10981129                do_action( 'customize_save_after', $this );
    10991130
     1131                $data = array(
     1132                        'setting_validities' => $exported_setting_validities,
     1133                );
     1134
    11001135                /**
    11011136                 * Filters response data for a successful customize_save AJAX request.
    11021137                 *
    final class WP_Customize_Manager { 
    11081143                 *                                   event on `wp.customize`.
    11091144                 * @param WP_Customize_Manager $this WP_Customize_Manager instance.
    11101145                 */
    1111                 $response = apply_filters( 'customize_save_response', array(), $this );
     1146                $response = apply_filters( 'customize_save_response', $data, $this );
    11121147                wp_send_json_success( $response );
    11131148        }
    11141149
  • src/wp-includes/customize/class-wp-customize-selective-refresh.php

    diff --git src/wp-includes/customize/class-wp-customize-selective-refresh.php src/wp-includes/customize/class-wp-customize-selective-refresh.php
    index f90f0f9..245d32a 100644
    final class WP_Customize_Selective_Refresh { 
    402402                        $response['errors'] = $this->triggered_errors;
    403403                }
    404404
     405                $setting_validities = $this->manager->validate_setting_values( $this->manager->unsanitized_post_values() );
     406                $exported_setting_validities = array_map( array( $this->manager, 'prepare_setting_validity_for_js' ), $setting_validities );
     407                $response['setting_validities'] = $exported_setting_validities;
     408
    405409                /**
    406410                 * Filters the response from rendering the partials.
    407411                 *
  • src/wp-includes/js/customize-preview.js

    diff --git src/wp-includes/js/customize-preview.js src/wp-includes/js/customize-preview.js
    index ac77551..f5569ed 100644
     
    172172                api.preview.send( 'ready', {
    173173                        activePanels: api.settings.activePanels,
    174174                        activeSections: api.settings.activeSections,
    175                         activeControls: api.settings.activeControls
     175                        activeControls: api.settings.activeControls,
     176                        settingValidities: api.settings.settingValidities
    176177                } );
    177178
    178179                // Display a loading indicator when preview is reloading, and remove on failure.
  • src/wp-includes/js/customize-selective-refresh.js

    diff --git src/wp-includes/js/customize-selective-refresh.js src/wp-includes/js/customize-selective-refresh.js
    index 7efee3d..ec51058 100644
    wp.customize.selectiveRefresh = ( function( $, api ) { 
    847847                        }
    848848                } );
    849849
     850                /**
     851                 * Handle setting validities in partial refresh response.
     852                 *
     853                 * @param {object} data Response data.
     854                 * @param {object} data.setting_validities Setting validities.
     855                 */
     856                api.selectiveRefresh.bind( 'render-partials-response', function handleSettingValiditiesResponse( data ) {
     857                        if ( data.setting_validities ) {
     858                                api.preview.send( 'selective-refresh-setting-validities', data.setting_validities );
     859                        }
     860                } );
     861
    850862                api.preview.bind( 'active', function() {
    851863
    852864                        // Make all partials ready.
  • tests/phpunit/tests/customize/manager.php

    diff --git tests/phpunit/tests/customize/manager.php tests/phpunit/tests/customize/manager.php
    index 666db6f..437f410 100644
    class Tests_WP_Customize_Manager extends WP_UnitTestCase { 
    196196         * @see WP_Customize_Manager::validate_setting_values()
    197197         */
    198198        function test_validate_setting_values() {
    199                 $default_value = 'foo_default';
    200199                $setting = $this->manager->add_setting( 'foo', array(
    201200                        'validate_callback' => array( $this, 'filter_customize_validate_foo' ),
    202201                        'sanitize_callback' => array( $this, 'filter_customize_sanitize_foo' ),
    class Tests_WP_Customize_Manager extends WP_UnitTestCase { 
    204203
    205204                $post_value = 'bar';
    206205                $this->manager->set_post_value( 'foo', $post_value );
    207                 $this->assertEmpty( $this->manager->validate_setting_values( $this->manager->unsanitized_post_values() ) );
     206                $validities = $this->manager->validate_setting_values( $this->manager->unsanitized_post_values() );
     207                $this->assertCount( 1, $validities );
     208                $this->assertEquals( array( 'foo' => true ), $validities );
    208209
    209210                $this->manager->set_post_value( 'foo', 'return_wp_error_in_sanitize' );
    210211                $invalid_settings = $this->manager->validate_setting_values( $this->manager->unsanitized_post_values() );
    class Tests_WP_Customize_Manager extends WP_UnitTestCase { 
    234235        }
    235236
    236237        /**
     238         * Test WP_Customize_Manager::prepare_setting_validity_for_js().
     239         *
     240         * @see WP_Customize_Manager::prepare_setting_validity_for_js()
     241         */
     242        function test_prepare_setting_validity_for_js() {
     243                $this->assertTrue( $this->manager->prepare_setting_validity_for_js( true ) );
     244                $error = new WP_Error();
     245                $error->add( 'bad_letter', 'Bad letter' );
     246                $error->add( 'bad_letter', 'Bad letra' );
     247                $error->add( 'bad_number', 'Bad number', array( 'number' => 123 ) );
     248                $validity = $this->manager->prepare_setting_validity_for_js( $error );
     249                $this->assertInternalType( 'array', $validity );
     250                foreach ( $error->errors as $code => $messages ) {
     251                        $this->assertArrayHasKey( $code, $validity );
     252                        $this->assertInternalType( 'array', $validity[ $code ] );
     253                        $this->assertEquals( join( ' ', $messages ), $validity[ $code ]['message'] );
     254                        $this->assertArrayHasKey( 'data', $validity[ $code ] );
     255                        $this->assertArrayHasKey( 'from_server', $validity[ $code ]['data'] );
     256                }
     257                $this->assertArrayHasKey( 'number', $validity['bad_number']['data'] );
     258                $this->assertEquals( 123, $validity['bad_number']['data']['number'] );
     259        }
     260
     261        /**
    237262         * Test WP_Customize_Manager::set_post_value().
    238263         *
    239264         * @see WP_Customize_Manager::set_post_value()
    class Tests_WP_Customize_Manager extends WP_UnitTestCase { 
    565590                $this->assertArrayHasKey( 'activePanels', $settings );
    566591                $this->assertArrayHasKey( 'activeSections', $settings );
    567592                $this->assertArrayHasKey( 'activeControls', $settings );
     593                $this->assertArrayHasKey( 'settingValidities', $settings );
    568594                $this->assertArrayHasKey( 'nonce', $settings );
    569595                $this->assertArrayHasKey( '_dirty', $settings );
    570596
  • tests/phpunit/tests/customize/selective-refresh-ajax.php

    diff --git tests/phpunit/tests/customize/selective-refresh-ajax.php tests/phpunit/tests/customize/selective-refresh-ajax.php
    index b60f23a..d2a9cdf 100644
    class Test_WP_Customize_Selective_Refresh_Ajax extends WP_UnitTestCase { 
    344344                $this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
    345345                $output = json_decode( ob_get_clean(), true );
    346346                $this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_blogname'] );
     347                $this->assertArrayHasKey( 'setting_validities', $output['data'] );
    347348        }
    348349
    349350        /**
  • tests/qunit/wp-admin/js/customize-controls.js

    diff --git tests/qunit/wp-admin/js/customize-controls.js tests/qunit/wp-admin/js/customize-controls.js
    index 23ca9ac..d806e46 100644
    jQuery( window ).load( function (){ 
    9696                ok( setting.notifications.extended( wp.customize.Values ) );
    9797                equal( wp.customize.Notification, setting.notifications.prototype.constructor.defaultConstructor );
    9898        } );
     99        test( 'Setting has findControls method', function() {
     100                var controls, setting = wp.customize( 'fixture-setting' );
     101                equal( 'function', typeof setting.findControls );
     102                controls = setting.findControls();
     103                equal( 1, controls.length );
     104                equal( 'fixture-control', controls[0].id );
     105        } );
    99106        test( 'Setting constructor object exists', function( assert ) {
    100107                assert.ok( _.isObject( wp.customize.settingConstructor ) );
    101108        } );
    jQuery( window ).load( function (){ 
    505512        test( 'Panel instance is not contextuallyActive', function () {
    506513                equal( mockPanel.isContextuallyActive(), false );
    507514        });
     515
     516        module( 'Test wp.customize.findControlsForSettings' );
     517        test( 'findControlsForSettings(blogname)', function() {
     518                var controlsForSettings, settingId = 'fixture-setting', controlId = 'fixture-control';
     519                ok( wp.customize.control.has( controlId ) );
     520                ok( wp.customize.has( settingId ) );
     521                controlsForSettings = wp.customize.findControlsForSettings( [ settingId ] );
     522                ok( _.isObject( controlsForSettings ), 'Response is object' );
     523                ok( _.isArray( controlsForSettings['fixture-setting'] ), 'Response has a fixture-setting array' );
     524                equal( 1, controlsForSettings['fixture-setting'].length );
     525                equal( wp.customize.control( controlId ), controlsForSettings['fixture-setting'][0] );
     526        } );
    508527});