diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js index 7d41d213ba..d53d951d92 100644 --- a/src/wp-admin/js/customize-controls.js +++ b/src/wp-admin/js/customize-controls.js @@ -1,8 +1,6 @@ /* globals _wpCustomizeHeader, _wpMediaViewsL10n */ (function( exports, $ ){ - var bubbleChildValueChanges, Container, focus, isKeydownButNotEnterEvent, areElementListsEqual, prioritySort, api = wp.customize; - - // @todo Move private helper functions to wp.customize.utils so they can be unit tested + var Container, focus, api = wp.customize; /** * @class @@ -32,13 +30,18 @@ } }); + /** + * Utility function namespace + */ + api.utils = {}; + /** * Watch all changes to Value properties, and bubble changes to parent Values instance * * @param {wp.customize.Class} instance * @param {Array} properties The names of the Value instances to watch. */ - bubbleChildValueChanges = function ( instance, properties ) { + api.utils.bubbleChildValueChanges = function ( instance, properties ) { $.each( properties, function ( i, key ) { instance[ key ].bind( function ( to, from ) { if ( instance.parent && to !== from ) { @@ -86,7 +89,7 @@ * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b * @returns {Number} */ - prioritySort = function ( a, b ) { + api.utils.prioritySort = function ( a, b ) { if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) { return a.params.instanceNumber - b.params.instanceNumber; } else { @@ -100,7 +103,7 @@ * @param {jQuery.Event} event * @returns {boolean} */ - isKeydownButNotEnterEvent = function ( event ) { + api.utils.isKeydownButNotEnterEvent = function ( event ) { return ( 'keydown' === event.type && 13 !== event.which ); }; @@ -111,7 +114,7 @@ * @param {Array|jQuery} listB * @returns {boolean} */ - areElementListsEqual = function ( listA, listB ) { + api.utils.areElementListsEqual = function ( listA, listB ) { var equal = ( listA.length === listB.length && // if lists are different lengths, then naturally they are not equal -1 === _.map( // are there any false values in the list returned by map? @@ -142,7 +145,7 @@ container.container = $( container.params.content ); container.deferred = { - ready: new $.Deferred() + embedded: new $.Deferred() }; container.priority = new api.Value(); container.active = new api.Value(); @@ -155,22 +158,20 @@ args = $.extend( {}, container.defaultActiveArguments, args ); active = ( active && container.isContextuallyActive() ); container.onChangeActive( active, args ); - // @todo trigger 'activated' and 'deactivated' events based on the expanded param? }); container.expanded.bind( function ( expanded ) { var args = container.expandedArgumentsQueue.shift(); args = $.extend( {}, container.defaultExpandedArguments, args ); container.onChangeExpanded( expanded, args ); - // @todo trigger 'expanded' and 'collapsed' events based on the expanded param? }); container.attachEvents(); - bubbleChildValueChanges( container, [ 'priority', 'active' ] ); + api.utils.bubbleChildValueChanges( container, [ 'priority', 'active' ] ); container.priority.set( isNaN( container.params.priority ) ? 100 : container.params.priority ); container.active.set( container.params.active ); - container.expanded.set( false ); // @todo True if deeplinking? + container.expanded.set( false ); }, /** @@ -193,7 +194,7 @@ children.push( child ); } } ); - children.sort( prioritySort ); + children.sort( api.utils.prioritySort ); return children; }, @@ -202,7 +203,7 @@ * @abstract */ isContextuallyActive: function () { - throw new Error( 'Must override with subclass.' ); + throw new Error( 'Container.isContextuallyActive() must be overridden in a subclass.' ); }, /** @@ -335,10 +336,10 @@ $( section.container ).toggleClass( 'control-subsection', !! id ); }); section.panel.set( section.params.panel || '' ); - bubbleChildValueChanges( section, [ 'panel' ] ); + api.utils.bubbleChildValueChanges( section, [ 'panel' ] ); section.embed(); - section.deferred.ready.done( function () { + section.deferred.embedded.done( function () { section.ready(); }); }, @@ -356,12 +357,12 @@ // The panel has been supplied, so wait until the panel object is registered api.panel( panelId, function ( panel ) { // The panel has been registered, wait for it to become ready/initialized - panel.deferred.ready.done( function () { + panel.deferred.embedded.done( function () { parentContainer = panel.container.find( 'ul:first' ); if ( ! section.container.parent().is( parentContainer ) ) { parentContainer.append( section.container ); } - section.deferred.ready.resolve(); // @todo Better to use `embedded` instead of `ready` + section.deferred.embedded.resolve(); }); } ); } else { @@ -370,7 +371,7 @@ if ( ! section.container.parent().is( parentContainer ) ) { parentContainer.append( section.container ); } - section.deferred.ready.resolve(); + section.deferred.embedded.resolve(); } }; section.panel.bind( inject ); @@ -385,7 +386,7 @@ // Expand/Collapse accordion sections on click. section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); // Keep this AFTER the key filter above @@ -479,7 +480,7 @@ var panel = this; Container.prototype.initialize.call( panel, id, options ); panel.embed(); - panel.deferred.ready.done( function () { + panel.deferred.embedded.done( function () { panel.ready(); }); }, @@ -494,7 +495,7 @@ if ( ! panel.container.parent().is( parentContainer ) ) { parentContainer.append( panel.container ); } - panel.deferred.ready.resolve(); + panel.deferred.embedded.resolve(); }, /** @@ -505,7 +506,7 @@ // Expand/Collapse accordion sections on click. panel.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); // Keep this AFTER the key filter above @@ -518,7 +519,7 @@ meta = panel.container.find( '.panel-meta:first' ); meta.find( '> .accordion-section-title' ).on( 'click keydown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); // Keep this AFTER the key filter above @@ -676,7 +677,7 @@ control.container = control.params.content ? $( control.params.content ) : $( control.selector ); control.deferred = { - ready: new $.Deferred() + embedded: new $.Deferred() }; control.section = new api.Value(); control.priority = new api.Value(); @@ -720,7 +721,7 @@ control.priority.set( isNaN( control.params.priority ) ? 10 : control.params.priority ); control.active.set( control.params.active ); - bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] ); + api.utils.bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] ); // Associate this control with its settings when they are created settings = $.map( control.params.settings, function( value ) { @@ -739,7 +740,7 @@ control.embed(); }) ); - control.deferred.ready.done( function () { + control.deferred.embedded.done( function () { control.ready(); }); }, @@ -760,13 +761,13 @@ // Wait for the section to be registered api.section( sectionId, function ( section ) { // Wait for the section to be ready/initialized - section.deferred.ready.done( function () { + section.deferred.embedded.done( function () { parentContainer = section.container.find( 'ul:first' ); if ( ! control.container.parent().is( parentContainer ) ) { parentContainer.append( control.container ); control.renderContent(); } - control.deferred.ready.resolve(); // @todo Better to use `embedded` instead of `ready` + control.deferred.embedded.resolve(); }); }); }; @@ -852,7 +853,7 @@ // Support the .dropdown class to open/close complex elements this.container.on( 'click keydown', '.dropdown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } @@ -935,7 +936,7 @@ * When the control's DOM structure is ready, * set up internal event bindings. */ - ready: function() { + ready: function() { var control = this; // Shortcut so that we don't have to use _.bind every time we add a callback. _.bindAll( control, 'restoreDefault', 'removeFile', 'openFrame', 'select' ); @@ -954,9 +955,9 @@ * Open the media modal. */ openFrame: function( event ) { - if ( event.type === 'keydown' && 13 !== event.which ) { // enter + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; - } + } event.preventDefault(); @@ -984,11 +985,11 @@ text: this.params.button_labels.frame_button }, multiple: false - }); + }); // When a file is selected, run a callback. this.frame.on( 'select', this.select ); - }, + }, /** * Callback handler for when an attachment is selected in the media modal. @@ -1008,7 +1009,7 @@ * Reset the setting to the default value. */ restoreDefault: function( event ) { - if ( event.type === 'keydown' && 13 !== event.which ) { // enter + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); @@ -1023,22 +1024,22 @@ * @param {object} event jQuery Event object */ removeFile: function( event ) { - if ( event.type === 'keydown' && 13 !== event.which ) { // enter + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; - } + } event.preventDefault(); this.params.attachment = {}; this.setting( '' ); this.renderContent(); // Not bound to setting change when emptying. - }, + }, // @deprecated success: function() {}, // @deprecated removerVisibility: function() {} - }); + }); /** * A control for uploading images. @@ -1742,8 +1743,9 @@ api.l10n = window._wpCustomizeControlsL10n; // Check if we can run the Customizer. - if ( ! api.settings ) + if ( ! api.settings ) { return; + } // Redirect to the fallback preview if any incompatibilities are found. if ( ! $.support.postMessage || ( ! $.support.cors && api.settings.isCrossDomain ) ) @@ -1768,7 +1770,7 @@ // Expand/Collapse the main customizer customize info $( '#customize-info' ).find( '> .accordion-section-title' ).on( 'click keydown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); // Keep this AFTER the key filter above @@ -1930,7 +1932,7 @@ if ( id && api[ type ]( id ) ) { instance = api[ type ]( id ); // Wait until the element is embedded in the DOM - instance.deferred.ready.done( function () { + instance.deferred.embedded.done( function () { // Wait until the preview has activated and so active panels, sections, controls have been set api.previewer.deferred.active.done( function () { instance.focus(); @@ -1956,7 +1958,7 @@ sectionContainers = _.pluck( sections, 'container' ); rootNodes.push( panel ); appendContainer = panel.container.find( 'ul:first' ); - if ( ! areElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) { + if ( ! api.utils.areElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) { _( sections ).each( function ( section ) { appendContainer.append( section.container ); } ); @@ -1972,7 +1974,7 @@ rootNodes.push( section ); } appendContainer = section.container.find( 'ul:first' ); - if ( ! areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) { + if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) { _( controls ).each( function ( control ) { appendContainer.append( control.container ); } ); @@ -1981,10 +1983,10 @@ } ); // Sort the root panels and sections - rootNodes.sort( prioritySort ); + rootNodes.sort( api.utils.prioritySort ); rootContainers = _.pluck( rootNodes, 'container' ); appendContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todo This should be defined elsewhere, and to be configurable - if ( ! areElementListsEqual( rootContainers, appendContainer.children() ) ) { + if ( ! api.utils.areElementListsEqual( rootContainers, appendContainer.children() ) ) { _( rootNodes ).each( function ( rootNode ) { appendContainer.append( rootNode.container ); } ); @@ -2080,7 +2082,7 @@ // Go back to the top-level Customizer accordion. $( '#customize-header-actions' ).on( 'click keydown', '.control-panel-back', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } @@ -2099,7 +2101,7 @@ }); $('.collapse-sidebar').on( 'click keydown', function( event ) { - if ( isKeydownButNotEnterEvent( event ) ) { + if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } diff --git a/tests/qunit/index.html b/tests/qunit/index.html index ce11144e62..df51b7a2e7 100644 --- a/tests/qunit/index.html +++ b/tests/qunit/index.html @@ -31,12 +31,15 @@ + + + diff --git a/tests/qunit/wp-admin/js/customize-base.js b/tests/qunit/wp-admin/js/customize-base.js index 422111fd58..c19ea807d2 100644 --- a/tests/qunit/wp-admin/js/customize-base.js +++ b/tests/qunit/wp-admin/js/customize-base.js @@ -1,7 +1,8 @@ /* global wp */ jQuery( function( $ ) { - var FooSuperClass, BarSubClass, foo, bar; + var FooSuperClass, BarSubClass, foo, bar, ConstructorTestClass, newConstructor, constructorTest, $mockElement, mockString, + firstInitialValue, firstValueInstance, wasCallbackFired, mockValueCallback; module( 'Customize Base: Class' ); @@ -46,11 +47,9 @@ jQuery( function( $ ) { equal( foo.instanceProp, 'instancePropValue' ); }); - // @todo Test Class.constructor() manipulation // @todo Test Class.applicator? // @todo do we test object.instance? - module( 'Customize Base: Subclass' ); BarSubClass = FooSuperClass.extend( @@ -82,4 +81,81 @@ jQuery( function( $ ) { equal( bar.extended( FooSuperClass ), true ); }); + + // Implements todo : Test Class.constructor() manipulation + module( 'Customize Base: Constructor Manipulation' ); + + newConstructor = function ( instanceProps ) { + $.extend( this , instanceProps || {} ); + }; + + ConstructorTestClass = wp.customize.Class.extend( + { + constructor : newConstructor, + protoProp: 'protoPropValue' + }, + { + staticProp: 'staticPropValue' + } + ); + + test( 'New constructor added to class' , function () { + equal( ConstructorTestClass.prototype.constructor , newConstructor ); + }); + test( 'Class with new constructor has protoPropValue' , function () { + equal( ConstructorTestClass.prototype.protoProp , 'protoPropValue' ); + }); + + constructorTest = new ConstructorTestClass( { instanceProp: 'instancePropValue' } ); + test( 'ConstructorTestClass instance constructorTest has the new constructor', function () { + equal( constructorTest.constructor, newConstructor ); + }); + + test( 'ConstructorTestClass instance constructorTest extended Class', function () { + equal( constructorTest.extended( wp.customize.Class ), true ); + }); + + test( 'ConstructorTestClass instance constructorTest has the added instance property', function () { + equal( constructorTest.instanceProp , 'instancePropValue' ); + }); + + + module( 'Customize Base: wp.customizer.ensure' ); + + $mockElement = $( '
' ); + + test( 'Handles jQuery argument' , function() { + equal( wp.customize.ensure( $mockElement ) , $mockElement ); + }); + + mockString = '
'; + + test( 'Handles string argument' , function() { + ok( wp.customize.ensure( mockString ) instanceof jQuery ); + }); + + + module( 'Customize Base: Value Class' ); + + firstInitialValue = true; + firstValueInstance = new wp.customize.Value( firstInitialValue ); + + test( 'Initialized with the right value' , function() { + equal( firstValueInstance.get() , firstInitialValue ); + }); + + test( '.set() works' , function() { + firstValueInstance.set( false ); + equal( firstValueInstance.get() , false ); + }); + + test( '.bind() adds new callback that fires on set()' , function() { + wasCallbackFired = false; + mockValueCallback = function() { + wasCallbackFired = true; + }; + firstValueInstance.bind( mockValueCallback ); + firstValueInstance.set( 'newValue' ); + ok( wasCallbackFired ); + }); }); diff --git a/tests/qunit/wp-admin/js/customize-controls-utils.js b/tests/qunit/wp-admin/js/customize-controls-utils.js new file mode 100644 index 0000000000..5216ad1026 --- /dev/null +++ b/tests/qunit/wp-admin/js/customize-controls-utils.js @@ -0,0 +1,108 @@ +/* global wp */ + +jQuery( function( $ ) { + var trueMockEvent, falseMockEvent, mockElementLists, $firstMockElement, $secondMockElement, $thirdMockElement, + BubbleTester, BubbleTesterTwoValues, bubbleTesterParent, firstBubbleTester, secondBubbleTester; + + module( 'Customizer Model Utility functions' ); + + trueMockEvent = { + type : 'keydown', + which : 14 + }; + + falseMockEvent = { + type : 'keydown', + which : 13 + }; + + test( 'isKeydownButNotEnterEvent returns true' , function () { + ok( wp.customize.utils.isKeydownButNotEnterEvent( trueMockEvent ) ); + }); + + test( 'isKeydownButNotEnterEvent returns false' , function () { + equal( wp.customize.utils.isKeydownButNotEnterEvent( falseMockEvent ) , false ); + }); + + $firstMockElement = $( '
' ); + $secondMockElement = $( '
  • ' ); + $thirdMockElement = $( '
    ' ); + + mockElementLists = { + first : [ $firstMockElement , $secondMockElement ], + second : [ $secondMockElement ], + firstInReverseOrder : [ $secondMockElement , $firstMockElement ], + third : [ $firstMockElement, $secondMockElement ], + thirdButLonger : [ $firstMockElement, $secondMockElement, $thirdMockElement ] + }; + + test( 'areElementListsEqual returns true' , function () { + ok( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.first ) ); + }); + + test( 'areElementListsEqual returns false' , function () { + equal( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.second ) , false ); + }); + + test( 'areElementListsEqual: lists have same values, but in reverse order' , function () { + equal( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.firstInReverseOrder ) , false ); + }); + + test( 'areElementListsEqual: lists have same values, but one is longer' , function () { + equal( wp.customize.utils.areElementListsEqual( mockElementLists.third , mockElementLists.thirdButLonger ) , false ); + }); + + + bubbleTesterParent = function() { + this.trigger = function( event , instance ) { + this.wasChangeTriggered = true; + this.instancePassedInTrigger = instance; + }; + this.wasChangeTriggered = false; + this.instancePassedInTrigger = {}; + }; + + BubbleTester = wp.customize.Class.extend( + { + parent : new bubbleTesterParent(), + fooValue : new wp.customize.Value() + }, + { + staticProperty : 'propertyValue' + } + ); + + test( 'bubbleChildValueChanges notifies parent of change' , function() { + firstBubbleTester = new BubbleTester(); + wp.customize.utils.bubbleChildValueChanges( firstBubbleTester , [ 'fooValue' ] ); + firstBubbleTester.fooValue.set( 'new value' ); + ok( firstBubbleTester.parent.wasChangeTriggered ); + }); + + test( 'bubbleChildValueChanges passes a reference to its instance' , function() { + ok( firstBubbleTester.parent.instancePassedInTrigger instanceof BubbleTester ); + }); + + BubbleTesterTwoValues = wp.customize.Class.extend( + { + parent : new bubbleTesterParent(), + exampleValue : new wp.customize.Value(), + barValue : new wp.customize.Value() + }, + { + staticProperty : 'propertyValue' + } + ); + + secondBubbleTester = new BubbleTesterTwoValues(); + wp.customize.utils.bubbleChildValueChanges( secondBubbleTester , [ 'exampleValue' , 'barValue' ] ); + secondBubbleTester.barValue.set( 'new value' ); + + test( 'bubbleChildValueChanges notifies parent of change when two values are bound' , function() { + ok( secondBubbleTester.parent.wasChangeTriggered ); + }); + + test( 'bubbleChildValueChanges passes a reference to its instance when two values are bound' , function() { + ok( secondBubbleTester.parent.instancePassedInTrigger instanceof BubbleTesterTwoValues ); + }); +}); diff --git a/tests/qunit/wp-admin/js/customize-controls.js b/tests/qunit/wp-admin/js/customize-controls.js new file mode 100644 index 0000000000..3a58a141da --- /dev/null +++ b/tests/qunit/wp-admin/js/customize-controls.js @@ -0,0 +1,173 @@ +/* global wp */ + +jQuery( function() { + + var controlId, controlLabel, controlType, controlContent, controlDescription, controlData, mockControl, + mockControlInstance, controlExpectedValues, sectionId, sectionContent, sectionData, mockSection, + sectionInstance, sectionExpectedValues, panelId, panelTitle, panelDescription, panelContent, panelData, + mockPanel, panelExpectedValues, testCustomizerModel; + + testCustomizerModel = function( model, expectedValues ) { + var type = expectedValues.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.textExpanded ) { + test( type + ' instance is not expanded', function () { + equal( model.expanded() , false ); + }); + + test( type + ' instance is expanded after calling .expanded()', function () { + model.expand(); + ok( model.expanded() ); + }); + + test( type + ' instance is collapsed after calling .collapse()', function () { + model.collapse(); + equal( model.expanded() , false ); + }); + } + + }; + + + module( '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' : 'blogname' }, + type : controlType + }; + + mockControl = new wp.customize.Control( controlId , { + params : controlData, + previewer : wp.customize.previewer + }); + + controlExpectedValues = { + type : 'Control', + content : controlContent, + descrption : controlDescription, + label : controlLabel, + id : controlId, + priority : 10, + textExpanded : false + }; + + testCustomizerModel( mockControl , controlExpectedValues ); + + test( 'Control instance does not yet belong to a section.', function () { + equal( mockControl.section() , undefined ); + }); + + 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 ); + }); + + + module( 'Customizer Section Model' ); + + sectionId = 'mock_title_tagline'; + sectionContent = '
  • '; + sectionData = { + content : sectionContent + }; + + mockSection = new wp.customize.Section( sectionId , { params : sectionData } ); + + sectionExpectedValues = { + type : 'Section', + id : sectionId, + content : sectionContent, + priority : 100, + testExpanded : true + }; + + testCustomizerModel( mockSection , sectionExpectedValues ); + + 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 ); + }); + + + module( 'Customizer Panel Model' ); + + panelId = 'mockPanelId'; + panelTitle = 'Mock Panel Title'; + panelDescription = 'Mock panel description'; + panelContent = '
  • '; + panelData = { + content : panelContent, + title : panelTitle, + description : panelDescription + }; + + mockPanel = new wp.customize.Panel( panelId , { params : panelData } ); + + panelExpectedValues = { + type : 'Panel', + id : panelId, + title : panelTitle , + description : panelDescription, + content : panelContent, + priority : 100, + testExpanded : true + }; + + testCustomizerModel( mockPanel , panelExpectedValues ); + + test( 'Panel instance is not contextuallyActive', function () { + equal( mockPanel.isContextuallyActive() , false ); + }); +});