/* global JSON, wp, test, ok, equal, module */ wp.customize.settingConstructor.abbreviation = wp.customize.Setting.extend({ validate: function( value ) { return value.toUpperCase(); } }); jQuery( window ).load( function (){ 'use strict'; var controlId, controlLabel, controlType, controlContent, controlDescription, controlData, mockControl, mockControlInstance, controlExpectedValues, sectionId, sectionContent, sectionData, mockSection, sectionInstance, sectionExpectedValues, panelId, panelTitle, panelDescription, panelContent, panelData, mockPanel, panelExpectedValues, testCustomizerModel, settingId, settingValue, mockSetting; testCustomizerModel = function( model, expectedValues ) { if ( ! expectedValues.type || ! wp.customize[ expectedValues.type ] ) { throw new Error( 'Must pass value type in expectedValues.' ); } var type = expectedValues.type; test( 'Model extends proper type', function () { ok( model.extended( wp.customize[ type ] ) ); } ); if ( expectedValues.hasOwnProperty( 'id' ) ) { test( type + ' instance has the right id', function () { equal( model.id, expectedValues.id ); }); } if ( expectedValues.hasOwnProperty( 'title') ) { test( type + ' instance has the right title.', function () { equal( model.params.title, expectedValues.title ); }); } if ( expectedValues.hasOwnProperty( 'description' ) ) { test( type + ' instance has the right description.', function () { equal( model.params.description, expectedValues.description ); }); } if ( expectedValues.hasOwnProperty( 'content' ) ) { test( type + ' instance has the right content.', function () { equal( model.params.content, expectedValues.content ); }); } if ( expectedValues.hasOwnProperty( 'priority' ) ) { test( type + ' instance has the right priority.', function () { equal( model.priority(), expectedValues.priority ); }); } if ( expectedValues.hasOwnProperty( 'active' ) ) { test( type + ' instance has the right active state.', function () { equal( model.active(), expectedValues.active ); }); } test( type + ' can be deactivated', function () { model.activate(); model.deactivate(); equal( model.active(), false ); model.activate(); equal( model.active(), true ); ok(true); }); if ( type === 'Panel' || type === 'Section' ) { if ( expectedValues.hasOwnProperty( 'expanded' ) ) { test( type + ' instance has the right expanded state.', function () { equal( model.expanded(), expectedValues.expanded ); } ); } test( type + ' instance is collapsed after calling .collapse()', function () { model.collapse(); ok( ! model.expanded() ); }); test( type + ' instance is expanded after calling .expand()', function () { model.expand(); ok( model.expanded() ); }); } }; module( 'Customizer notifications collection' ); test( 'Notifications collection exists', function() { ok( wp.customize.notifications ); equal( wp.customize.notifications.defaultConstructor, wp.customize.Notification ); } ); test( 'Notification objects are rendered as part of notifications collection', function() { var container = jQuery( '#customize-notifications-test' ), items, collection; collection = new wp.customize.Notifications({ container: container }); collection.add( 'mycode-1', new wp.customize.Notification( 'mycode-1' ) ); collection.render(); items = collection.container.find( 'li' ); equal( items.length, 1 ); equal( items.first().data( 'code' ), 'mycode-1' ); collection.add( 'mycode-2', new wp.customize.Notification( 'mycode-2', { dismissible: true } ) ); collection.render(); items = collection.container.find( 'li' ); equal( items.length, 2 ); equal( items.first().data( 'code' ), 'mycode-2' ); equal( items.last().data( 'code' ), 'mycode-1' ); equal( items.first().find( '.notice-dismiss' ).length, 1 ); equal( items.last().find( '.notice-dismiss' ).length, 0 ); collection.remove( 'mycode-2' ); collection.render(); items = collection.container.find( 'li' ); equal( items.length, 1 ); equal( items.first().data( 'code' ), 'mycode-1' ); collection.remove( 'mycode-1' ); collection.render(); ok( collection.container.is( ':hidden' ), 'Notifications area is hidden.' ); } ); module( 'Customizer Previewed Device' ); test( 'Previewed device defaults to desktop.', function () { equal( wp.customize.previewedDevice.get(), 'desktop' ); } ); module( 'Customizer Setting in Fixture' ); test( 'Setting has fixture value', function () { equal( wp.customize( 'fixture-setting' )(), 'Lorem Ipsum' ); } ); test( 'Setting has notifications', function () { var setting = wp.customize( 'fixture-setting' ); ok( setting.notifications.extended( wp.customize.Values ) ); equal( wp.customize.Notification, setting.notifications.prototype.constructor.defaultConstructor ); } ); test( 'Setting has findControls method', function() { var controls, setting = wp.customize( 'fixture-setting' ); equal( 'function', typeof setting.findControls ); controls = setting.findControls(); equal( 1, controls.length ); equal( 'fixture-control', controls[0].id ); } ); test( 'Setting constructor object exists', function( assert ) { assert.ok( _.isObject( wp.customize.settingConstructor ) ); } ); test( 'Custom setting constructor is used', function( assert ) { var setting = wp.customize( 'fixture-setting-abbr' ); assert.ok( setting.extended( wp.customize.settingConstructor.abbreviation ) ); setting.set( 'usa' ); assert.equal( 'USA', setting.get() ); } ); module( 'Customizer Control in Fixture' ); test( 'Control exists', function () { ok( wp.customize.control.has( 'fixture-control' ) ); } ); test( 'Control has the fixture setting', function () { var control = wp.customize.control( 'fixture-control' ); equal( control.setting(), 'Lorem Ipsum' ); equal( control.setting.id, 'fixture-setting' ); } ); test( 'Control has the section fixture section ID', function () { var control = wp.customize.control( 'fixture-control' ); equal( control.section(), 'fixture-section' ); } ); test( 'Control has notifications', function ( assert ) { var control = wp.customize.control( 'fixture-control' ), settingNotification, controlOnlyNotification, doneEmbedded; assert.ok( control.notifications.extended( wp.customize.Values ) ); assert.equal( wp.customize.Notification, control.notifications.prototype.constructor.defaultConstructor ); assert.ok( _.isFunction( control.getNotificationsContainerElement ) ); assert.ok( _.isFunction( control.renderNotifications ) ); doneEmbedded = assert.async(); control.deferred.embedded.done( function() { var notificationContainerElement; assert.equal( 0, _.size( control.notifications._value ) ); assert.equal( 0, _.size( control.settings['default'].notifications._value ) ); notificationContainerElement = control.getNotificationsContainerElement(); assert.equal( 1, notificationContainerElement.length ); assert.ok( notificationContainerElement.is( '.customize-control-notifications-container' ) ); assert.equal( 0, notificationContainerElement.find( '> ul > li' ).length ); assert.equal( 0, notificationContainerElement.height() ); settingNotification = new wp.customize.Notification( 'setting_invalidity', 'Invalid setting' ); controlOnlyNotification = new wp.customize.Notification( 'control_invalidity', 'Invalid control' ); control.settings['default'].notifications.add( settingNotification.code, settingNotification ); control.notifications.add( controlOnlyNotification.code, controlOnlyNotification ); // Note that renderNotifications is being called manually here since rendering normally happens asynchronously. control.notifications.render(); assert.equal( 2, notificationContainerElement.find( '> ul > li' ).length ); assert.notEqual( 'none', notificationContainerElement.css( 'display' ) ); assert.equal( 2, _.size( control.notifications._value ) ); assert.equal( 1, _.size( control.settings['default'].notifications._value ) ); control.notifications.remove( controlOnlyNotification.code ); control.notifications.render(); assert.equal( 1, notificationContainerElement.find( '> ul > li' ).length ); assert.notEqual( 'none', notificationContainerElement.css( 'display' ) ); control.settings['default'].notifications.remove( settingNotification.code ); control.notifications.render(); assert.equal( 0, notificationContainerElement.find( '> ul > li' ).length ); notificationContainerElement.stop().hide(); // Clean up. doneEmbedded(); } ); } ); module( 'Customizer control without associated settings' ); test( 'Control can be created without settings', function() { var control = new wp.customize.Control( 'settingless', { params: { content: jQuery( '
  • Hello World
  • ' ), section: 'fixture-section' } } ); wp.customize.control.add( control.id, control ); equal( control.deferred.embedded.state(), 'resolved' ); ok( null === control.setting ); ok( jQuery.isEmptyObject( control.settings ) ); } ); // Begin sections. module( 'Customizer Section in Fixture' ); test( 'Fixture section exists', function () { ok( wp.customize.section.has( 'fixture-section' ) ); } ); test( 'Fixture section has control among controls()', function () { var section = wp.customize.section( 'fixture-section' ); ok( -1 !== _.pluck( section.controls(), 'id' ).indexOf( 'fixture-control' ) ); } ); test( 'Fixture section has has expected panel', function () { var section = wp.customize.section( 'fixture-section' ); equal( section.panel(), 'fixture-panel' ); } ); module( 'Customizer Default Section with Template in Fixture' ); test( 'Fixture section exists', function () { ok( wp.customize.section.has( 'fixture-section-default-templated' ) ); } ); test( 'Fixture section has expected content', function () { var id = 'fixture-section-default-templated', section; section = wp.customize.section( id ); ok( ! section.params.content ); ok( !! section.container ); ok( !! section.headContainer ); ok( !! section.contentContainer ); ok( section.container.has( section.headContainer ) ); ok( section.container.has( section.contentContainer ) ); ok( section.headContainer.is( '.control-section.control-section-default' ) ); ok( 1 === section.headContainer.find( '> .accordion-section-title' ).length ); ok( section.contentContainer.is( '.accordion-section-content' ) ); equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Custom Type (titleless) Section with Template in Fixture' ); test( 'Fixture section exists', function () { ok( wp.customize.section.has( 'fixture-section-titleless-templated' ) ); } ); test( 'Fixture section has expected content', function () { var id = 'fixture-section-titleless-templated', section; section = wp.customize.section( id ); ok( ! section.params.content ); ok( !! section.container ); ok( !! section.headContainer ); ok( !! section.contentContainer ); ok( section.container.has( section.headContainer ) ); ok( section.container.has( section.contentContainer ) ); ok( section.container.is( '.control-section.control-section-titleless' ) ); ok( 0 === section.headContainer.find( '> .accordion-section-title' ).length ); ok( section.contentContainer.is( '.accordion-section-content' ) ); equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Custom Type Section Lacking Specific Template' ); test( 'Fixture section has expected content', function () { var id = 'fixture-section-reusing-default-template', section; section = wp.customize.section( id ); ok( ! section.params.content ); ok( !! section.container ); ok( !! section.headContainer ); ok( !! section.contentContainer ); ok( section.container.has( section.headContainer ) ); ok( section.container.has( section.contentContainer ) ); ok( section.headContainer.is( '.control-section.control-section-' + section.params.type ) ); ok( 1 === section.headContainer.find( '> .accordion-section-title' ).length ); ok( section.contentContainer.is( '.accordion-section-content' ) ); equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Section lacking any params' ); test( 'Fixture section has default params supplied', function () { var id = 'fixture-section-without-params', section, defaultParams; section = wp.customize.section( id ); defaultParams = { title: '', description: '', priority: 100, panel: null, type: 'default', content: null, active: true, instanceNumber: null, customizeAction: '' }; jQuery.each( defaultParams, function ( key, value ) { ok( 'undefined' !== typeof section.params[ key ] ); equal( value, section.params[ key ] ); } ); } ); // Begin panels. module( 'Customizer Panel in Fixture' ); test( 'Fixture panel exists', function () { ok( wp.customize.panel.has( 'fixture-panel' ) ); } ); test( 'Fixture panel has content', function () { var panel = wp.customize.panel( 'fixture-panel' ); ok( !! panel.params.content ); ok( !! panel.container ); ok( !! panel.headContainer ); ok( !! panel.contentContainer ); ok( panel.container.has( panel.headContainer ) ); ok( panel.container.has( panel.contentContainer ) ); } ); test( 'Fixture panel has section among its sections()', function () { var panel = wp.customize.panel( 'fixture-panel' ); ok( -1 !== _.pluck( panel.sections(), 'id' ).indexOf( 'fixture-section' ) ); } ); test( 'Panel is not expanded by default', function () { var panel = wp.customize.panel( 'fixture-panel' ); ok( ! panel.expanded() ); } ); test( 'Panel is not expanded by default', function () { var panel = wp.customize.panel( 'fixture-panel' ); ok( ! panel.expanded() ); } ); test( 'Focusing on a control will expand the panel and section', function () { var panel, section, control; panel = wp.customize.panel( 'fixture-panel' ); section = wp.customize.section( 'fixture-section' ); control = wp.customize.control( 'fixture-control' ); ok( ! panel.expanded() ); ok( ! section.expanded() ); control.focus(); ok( section.expanded() ); ok( panel.expanded() ); } ); module( 'Customizer Default Panel with Template in Fixture' ); test( 'Fixture section exists', function () { ok( wp.customize.panel.has( 'fixture-panel-default-templated' ) ); } ); test( 'Fixture panel has expected content', function () { var id = 'fixture-panel-default-templated', panel; panel = wp.customize.panel( id ); ok( ! panel.params.content ); ok( !! panel.container ); ok( !! panel.headContainer ); ok( !! panel.contentContainer ); ok( panel.container.has( panel.headContainer ) ); ok( panel.container.has( panel.contentContainer ) ); ok( panel.headContainer.is( '.control-panel.control-panel-default' ) ); ok( 1 === panel.headContainer.find( '> .accordion-section-title' ).length ); ok( panel.contentContainer.is( '.control-panel-content' ) ); equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Custom Type Panel (titleless) with Template in Fixture' ); test( 'Fixture panel exists', function () { ok( wp.customize.panel.has( 'fixture-panel-titleless-templated' ) ); } ); test( 'Fixture panel has expected content', function () { var id = 'fixture-panel-titleless-templated', panel; panel = wp.customize.panel( id ); ok( ! panel.params.content ); ok( !! panel.container ); ok( !! panel.headContainer ); ok( !! panel.contentContainer ); ok( panel.container.has( panel.headContainer ) ); ok( panel.container.has( panel.contentContainer ) ); ok( panel.headContainer.is( '.control-panel.control-panel-titleless' ) ); ok( 0 === panel.headContainer.find( '> .accordion-section-title' ).length ); ok( panel.contentContainer.is( '.control-panel-content' ) ); equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Custom Type Panel Lacking Specific Template' ); test( 'Fixture panel has expected content', function () { var id = 'fixture-panel-reusing-default-template', panel; panel = wp.customize.panel( id ); ok( ! panel.params.content ); ok( !! panel.container ); ok( !! panel.headContainer ); ok( !! panel.contentContainer ); ok( panel.container.has( panel.headContainer ) ); ok( panel.container.has( panel.contentContainer ) ); ok( panel.headContainer.is( '.control-panel.control-panel-' + panel.params.type ) ); ok( 1 === panel.headContainer.find( '> .accordion-section-title' ).length ); ok( panel.contentContainer.is( '.control-panel-content' ) ); equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) ); } ); module( 'Customizer Panel lacking any params' ); test( 'Fixture panel has default params supplied', function () { var id = 'fixture-panel-without-params', panel, defaultParams; panel = wp.customize.panel( id ); defaultParams = { title: '', description: '', priority: 100, type: 'default', content: null, active: true, instanceNumber: null }; jQuery.each( defaultParams, function ( key, value ) { ok( 'undefined' !== typeof panel.params[ key ] ); equal( value, panel.params[ key ] ); } ); } ); module( 'Dynamically-created Customizer Setting Model' ); settingId = 'new_blogname'; settingValue = 'Hello World'; test( 'Create a new setting', function () { mockSetting = wp.customize.create( settingId, settingId, settingValue, { transport: 'refresh', previewer: wp.customize.previewer } ); equal( mockSetting(), settingValue ); equal( mockSetting.id, settingId ); } ); module( 'Dynamically-created Customizer Section Model' ); sectionId = 'mock_title_tagline'; sectionContent = '
  • Section Fixture Press return or enter to open

  • '; sectionData = { content: sectionContent, active: true, type: 'default' }; mockSection = new wp.customize.Section( sectionId, { params: sectionData } ); sectionExpectedValues = { type: 'Section', id: sectionId, content: sectionContent, priority: 100, active: true // @todo This should default to true }; testCustomizerModel( mockSection, sectionExpectedValues ); test( 'Section has been embedded', function () { equal( mockSection.deferred.embedded.state(), 'resolved' ); } ); wp.customize.section.add( sectionId, mockSection ); test( 'Section instance added to the wp.customize.section object', function () { ok( wp.customize.section.has( sectionId ) ); }); sectionInstance = wp.customize.section( sectionId ); test( 'Section instance has right content when accessed from wp.customize.section()', function () { equal( sectionInstance.params.content, sectionContent ); }); test( 'Section instance has no children yet', function () { equal( sectionInstance.controls().length, 0 ); }); module( 'Dynamically-created Customizer Control Model' ); controlId = 'new_blogname'; controlLabel = 'Site Title'; controlType = 'text'; controlContent = '
  • '; controlDescription = 'Test control description'; controlData = { content: controlContent, description: controlDescription, label: controlLabel, settings: { 'default': 'new_blogname' }, type: controlType, active: true // @todo This should default to true }; mockControl = new wp.customize.Control( controlId, { params: controlData, previewer: wp.customize.previewer }); controlExpectedValues = { type: 'Control', content: controlContent, description: controlDescription, label: controlLabel, id: controlId, priority: 10 }; testCustomizerModel( mockControl, controlExpectedValues ); test( 'Control instance does not yet belong to a section.', function () { equal( mockControl.section(), undefined ); }); test( 'Control has not been embedded yet', function () { equal( mockControl.deferred.embedded.state(), 'pending' ); } ); test( 'Control instance has the right selector.', function () { equal( mockControl.selector, '#customize-control-new_blogname' ); }); wp.customize.control.add( controlId, mockControl ); test( 'Control instance was added to the control class.', function () { ok( wp.customize.control.has( controlId ) ); }); mockControlInstance = wp.customize.control( controlId ); test( 'Control instance has the right id when accessed from api.control().', function () { equal( mockControlInstance.id, controlId ); }); test( 'Control section can be set as expected', function () { mockControl.section( mockSection.id ); equal( mockControl.section(), mockSection.id ); }); test( 'Associating a control with a section allows it to be embedded', function () { equal( mockControl.deferred.embedded.state(), 'resolved' ); }); test( 'Control is now available on section.controls()', function () { equal( sectionInstance.controls().length, 1 ); equal( sectionInstance.controls()[0], mockControl ); }); module( 'Dynamically-created Customizer Panel Model' ); panelId = 'mockPanelId'; panelTitle = 'Mock Panel Title'; panelDescription = 'Mock panel description'; panelContent = '
  • Fixture Panel Press return or enter to open this panel

  • '; panelData = { content: panelContent, title: panelTitle, description: panelDescription, active: true, // @todo This should default to true type: 'default' }; mockPanel = new wp.customize.Panel( panelId, { params: panelData } ); panelExpectedValues = { type: 'Panel', id: panelId, title: panelTitle, description: panelDescription, content: panelContent, priority: 100, active: true }; testCustomizerModel( mockPanel, panelExpectedValues ); test( 'Panel instance is not contextuallyActive', function () { equal( mockPanel.isContextuallyActive(), false ); }); module( 'Test wp.customize.findControlsForSettings' ); test( 'findControlsForSettings(blogname)', function() { var controlsForSettings, settingId = 'fixture-setting', controlId = 'fixture-control'; ok( wp.customize.control.has( controlId ) ); ok( wp.customize.has( settingId ) ); controlsForSettings = wp.customize.findControlsForSettings( [ settingId ] ); ok( _.isObject( controlsForSettings ), 'Response is object' ); ok( _.isArray( controlsForSettings['fixture-setting'] ), 'Response has a fixture-setting array' ); equal( 1, controlsForSettings['fixture-setting'].length ); equal( wp.customize.control( controlId ), controlsForSettings['fixture-setting'][0] ); } ); module( 'Customize Controls wp.customize.dirtyValues' ); test( 'dirtyValues() returns expected values', function() { wp.customize.state( 'changesetStatus' ).set( 'auto-draft' ); wp.customize.each( function( setting ) { setting._dirty = false; } ); ok( _.isEmpty( wp.customize.dirtyValues() ) ); ok( _.isEmpty( wp.customize.dirtyValues( { unsaved: false } ) ) ); wp.customize( 'fixture-setting' )._dirty = true; ok( ! _.isEmpty( wp.customize.dirtyValues() ) ); ok( _.isEmpty( wp.customize.dirtyValues( { unsaved: true } ) ) ); wp.customize( 'fixture-setting' ).set( 'Modified' ); ok( ! _.isEmpty( wp.customize.dirtyValues() ) ); ok( ! _.isEmpty( wp.customize.dirtyValues( { unsaved: true } ) ) ); equal( 'Modified', wp.customize.dirtyValues()['fixture-setting'] ); // When the changeset does not exist, all dirty settings are necessarily unsaved. wp.customize.state( 'changesetStatus' ).set( '' ); wp.customize( 'fixture-setting' )._dirty = true; ok( ! _.isEmpty( wp.customize.dirtyValues() ) ); ok( ! _.isEmpty( wp.customize.dirtyValues( { unsaved: true } ) ) ); } ); module( 'Customize Controls: wp.customize.requestChangesetUpdate()' ); test( 'requestChangesetUpdate makes request and returns promise', function( assert ) { var request, originalBeforeSetup = jQuery.ajaxSettings.beforeSend; jQuery.ajaxSetup( { beforeSend: function( e, data ) { var queryParams, changesetData; queryParams = wp.customize.utils.parseQueryString( data.data ); assert.equal( 'customize_save', queryParams.action ); assert.ok( ! _.isUndefined( queryParams.customize_changeset_data ) ); assert.ok( ! _.isUndefined( queryParams.nonce ) ); assert.ok( ! _.isUndefined( queryParams.customize_theme ) ); assert.equal( wp.customize.settings.changeset.uuid, queryParams.customize_changeset_uuid ); assert.equal( 'on', queryParams.wp_customize ); changesetData = JSON.parse( queryParams.customize_changeset_data ); assert.ok( ! _.isUndefined( changesetData.additionalSetting ) ); assert.ok( ! _.isUndefined( changesetData['fixture-setting'] ) ); assert.equal( 'additionalValue', changesetData.additionalSetting.value ); assert.equal( 'requestChangesetUpdate', changesetData['fixture-setting'].value ); // Prevent Ajax request from completing. return false; } } ); wp.customize.each( function( setting ) { setting._dirty = false; } ); request = wp.customize.requestChangesetUpdate(); assert.equal( 'resolved', request.state()); request.done( function( data ) { assert.ok( _.isEqual( {}, data ) ); } ); wp.customize( 'fixture-setting' ).set( 'requestChangesetUpdate' ); request = wp.customize.requestChangesetUpdate( { additionalSetting: { value: 'additionalValue' } } ); request.always( function( data ) { assert.equal( 'canceled', data.statusText ); jQuery.ajaxSetup( { beforeSend: originalBeforeSetup } ); } ); } ); });