Ticket #28709: 28709.14.diff
File 28709.14.diff, 29.8 KB (added by , 10 years ago) |
---|
-
src/wp-admin/js/customize-controls.js
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js index 7b9f7b1..0a7e4f4 100644
1 1 /* globals _wpCustomizeHeader, _wpMediaViewsL10n */ 2 2 (function( exports, $ ){ 3 var bubbleChildValueChanges, Container, focus, isKeydownButNotEnterEvent, areElementListsEqual, prioritySort, api = wp.customize; 4 5 // @todo Move private helper functions to wp.customize.utils so they can be unit tested 3 var Container, focus, containerRootElement, api = wp.customize; 6 4 7 5 /** 8 6 * @class … … 33 31 }); 34 32 35 33 /** 34 * Utility function namespace 35 */ 36 api.utils = {}; 37 38 /** 36 39 * Watch all changes to Value properties, and bubble changes to parent Values instance 37 40 * 38 41 * @param {wp.customize.Class} instance 39 42 * @param {Array} properties The names of the Value instances to watch. 40 43 */ 41 bubbleChildValueChanges = function ( instance, properties ) {44 api.utils.bubbleChildValueChanges = function ( instance, properties ) { 42 45 $.each( properties, function ( i, key ) { 43 46 instance[ key ].bind( function ( to, from ) { 44 47 if ( instance.parent && to !== from ) { … … 49 52 }; 50 53 51 54 /** 55 * Set the element which serves as the root container for the Customizer UI. 56 * 57 * @param {Element|jQuery} rootElement 58 */ 59 api.utils.setContainerRootElement = function( rootElement ) { 60 containerRootElement = $( rootElement ); 61 }; 62 63 /** 64 * Get the element which serves as the root container for the Customizer UI. 65 * 66 * @returns {jQuery} 67 */ 68 api.utils.getContainerRootElement = function() { 69 return containerRootElement; 70 }; 71 72 /** 52 73 * Expand a panel, section, or control and focus on the first focusable element. 53 74 * 54 75 * @param {Object} [params] … … 86 107 * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b 87 108 * @returns {Number} 88 109 */ 89 prioritySort = function ( a, b ) {110 api.utils.prioritySort = function ( a, b ) { 90 111 if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) { 91 112 return a.params.instanceNumber - b.params.instanceNumber; 92 113 } else { … … 100 121 * @param {jQuery.Event} event 101 122 * @returns {boolean} 102 123 */ 103 isKeydownButNotEnterEvent = function ( event ) {124 api.utils.isKeydownButNotEnterEvent = function ( event ) { 104 125 return ( 'keydown' === event.type && 13 !== event.which ); 105 126 }; 106 127 … … 111 132 * @param {Array|jQuery} listB 112 133 * @returns {boolean} 113 134 */ 114 a reElementListsEqual = function ( listA, listB ) {135 api.utils.areElementListsEqual = function ( listA, listB ) { 115 136 var equal = ( 116 137 listA.length === listB.length && // if lists are different lengths, then naturally they are not equal 117 138 -1 === _.map( // are there any false values in the list returned by map? … … 142 163 container.container = $( container.params.content ); 143 164 144 165 container.deferred = { 145 ready: new $.Deferred()166 embedded: new $.Deferred() 146 167 }; 147 168 container.priority = new api.Value(); 148 169 container.active = new api.Value(); … … 155 176 args = $.extend( {}, container.defaultActiveArguments, args ); 156 177 active = ( active && container.isContextuallyActive() ); 157 178 container.onChangeActive( active, args ); 158 // @todo trigger 'activated' and 'deactivated' events based on the expanded param?159 179 }); 160 180 container.expanded.bind( function ( expanded ) { 161 181 var args = container.expandedArgumentsQueue.shift(); 162 182 args = $.extend( {}, container.defaultExpandedArguments, args ); 163 183 container.onChangeExpanded( expanded, args ); 164 // @todo trigger 'expanded' and 'collapsed' events based on the expanded param?165 184 }); 166 185 167 186 container.attachEvents(); 168 187 169 bubbleChildValueChanges( container, [ 'priority', 'active' ] );188 api.utils.bubbleChildValueChanges( container, [ 'priority', 'active' ] ); 170 189 171 190 container.priority.set( isNaN( container.params.priority ) ? 100 : container.params.priority ); 172 191 container.active.set( container.params.active ); 173 container.expanded.set( false ); // @todo True if deeplinking?192 container.expanded.set( false ); 174 193 }, 175 194 176 195 /** … … 193 212 children.push( child ); 194 213 } 195 214 } ); 196 children.sort( prioritySort );215 children.sort( api.utils.prioritySort ); 197 216 return children; 198 217 }, 199 218 … … 335 354 $( section.container ).toggleClass( 'control-subsection', !! id ); 336 355 }); 337 356 section.panel.set( section.params.panel || '' ); 338 bubbleChildValueChanges( section, [ 'panel' ] );357 api.utils.bubbleChildValueChanges( section, [ 'panel' ] ); 339 358 340 359 section.embed(); 341 section.deferred. ready.done( function () {360 section.deferred.embedded.done( function () { 342 361 section.ready(); 343 362 }); 344 363 }, … … 356 375 // The panel has been supplied, so wait until the panel object is registered 357 376 api.panel( panelId, function ( panel ) { 358 377 // The panel has been registered, wait for it to become ready/initialized 359 panel.deferred. ready.done( function () {378 panel.deferred.embedded.done( function () { 360 379 parentContainer = panel.container.find( 'ul:first' ); 361 380 if ( ! section.container.parent().is( parentContainer ) ) { 362 381 parentContainer.append( section.container ); 363 382 } 364 section.deferred. ready.resolve(); // @todo Better to use `embedded` instead of `ready`383 section.deferred.embedded.resolve(); 365 384 }); 366 385 } ); 367 386 } else { 368 387 // There is no panel, so embed the section in the root of the customizer 369 parentContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todoThis should be defined elsewhere, and to be configurable388 parentContainer = api.utils.getContainerRootElement(); // implements todo: This should be defined elsewhere, and to be configurable 370 389 if ( ! section.container.parent().is( parentContainer ) ) { 371 390 parentContainer.append( section.container ); 372 391 } 373 section.deferred. ready.resolve();392 section.deferred.embedded.resolve(); 374 393 } 375 394 }; 376 395 section.panel.bind( inject ); … … 385 404 386 405 // Expand/Collapse accordion sections on click. 387 406 section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { 388 if ( isKeydownButNotEnterEvent( event ) ) {407 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 389 408 return; 390 409 } 391 410 event.preventDefault(); // Keep this AFTER the key filter above … … 479 498 var panel = this; 480 499 Container.prototype.initialize.call( panel, id, options ); 481 500 panel.embed(); 482 panel.deferred. ready.done( function () {501 panel.deferred.embedded.done( function () { 483 502 panel.ready(); 484 503 }); 485 504 }, … … 489 508 */ 490 509 embed: function () { 491 510 var panel = this, 492 parentContainer = $( '#customize-theme-controls > ul' ); // @todoThis should be defined elsewhere, and to be configurable511 parentContainer = api.utils.getContainerRootElement(); // implements todo: This should be defined elsewhere, and to be configurable 493 512 494 513 if ( ! panel.container.parent().is( parentContainer ) ) { 495 514 parentContainer.append( panel.container ); 496 515 } 497 panel.deferred. ready.resolve();516 panel.deferred.embedded.resolve(); 498 517 }, 499 518 500 519 /** … … 505 524 506 525 // Expand/Collapse accordion sections on click. 507 526 panel.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { 508 if ( isKeydownButNotEnterEvent( event ) ) {527 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 509 528 return; 510 529 } 511 530 event.preventDefault(); // Keep this AFTER the key filter above … … 518 537 meta = panel.container.find( '.panel-meta:first' ); 519 538 520 539 meta.find( '> .accordion-section-title' ).on( 'click keydown', function( event ) { 521 if ( isKeydownButNotEnterEvent( event ) ) {540 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 522 541 return; 523 542 } 524 543 event.preventDefault(); // Keep this AFTER the key filter above … … 588 607 overlay = section.closest( '.wp-full-overlay' ), 589 608 container = section.closest( '.accordion-container' ), 590 609 siblings = container.find( '.open' ), 591 topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ), 610 $ContainerRootElement = api.utils.getContainerRootElement(), 611 topPanel = overlay.find( $ContainerRootElement ).find( '> .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ), 592 612 backBtn = overlay.find( '.control-panel-back' ), 593 613 panelTitle = section.find( '.accordion-section-title' ).first(), 594 614 content = section.find( '.control-panel-content' ); … … 676 696 control.container = control.params.content ? $( control.params.content ) : $( control.selector ); 677 697 678 698 control.deferred = { 679 ready: new $.Deferred()699 embedded: new $.Deferred() 680 700 }; 681 701 control.section = new api.Value(); 682 702 control.priority = new api.Value(); … … 720 740 control.priority.set( isNaN( control.params.priority ) ? 10 : control.params.priority ); 721 741 control.active.set( control.params.active ); 722 742 723 bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] );743 api.utils.bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] ); 724 744 725 745 // Associate this control with its settings when they are created 726 746 settings = $.map( control.params.settings, function( value ) { … … 739 759 control.embed(); 740 760 }) ); 741 761 742 control.deferred. ready.done( function () {762 control.deferred.embedded.done( function () { 743 763 control.ready(); 744 764 }); 745 765 }, … … 760 780 // Wait for the section to be registered 761 781 api.section( sectionId, function ( section ) { 762 782 // Wait for the section to be ready/initialized 763 section.deferred. ready.done( function () {783 section.deferred.embedded.done( function () { 764 784 parentContainer = section.container.find( 'ul:first' ); 765 785 if ( ! control.container.parent().is( parentContainer ) ) { 766 786 parentContainer.append( control.container ); 767 787 control.renderContent(); 768 788 } 769 control.deferred. ready.resolve(); // @todo Better to use `embedded` instead of `ready`789 control.deferred.embedded.resolve(); 770 790 }); 771 791 }); 772 792 }; … … 852 872 853 873 // Support the .dropdown class to open/close complex elements 854 874 this.container.on( 'click keydown', '.dropdown', function( event ) { 855 if ( isKeydownButNotEnterEvent( event ) ) {875 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 856 876 return; 857 877 } 858 878 … … 935 955 * When the control's DOM structure is ready, 936 956 * set up internal event bindings. 937 957 */ 938 958 ready: function() { 939 959 var control = this; 940 960 // Shortcut so that we don't have to use _.bind every time we add a callback. 941 961 _.bindAll( control, 'restoreDefault', 'removeFile', 'openFrame', 'select' ); … … 956 976 openFrame: function( event ) { 957 977 if ( event.type === 'keydown' && 13 !== event.which ) { // enter 958 978 return; 959 979 } 960 980 961 981 event.preventDefault(); 962 982 … … 984 1004 text: this.params.button_labels.frame_button 985 1005 }, 986 1006 multiple: false 987 1007 }); 988 1008 989 1009 // When a file is selected, run a callback. 990 1010 this.frame.on( 'select', this.select ); 991 1011 }, 992 1012 993 1013 /** 994 1014 * Callback handler for when an attachment is selected in the media modal. … … 1008 1028 * Reset the setting to the default value. 1009 1029 */ 1010 1030 restoreDefault: function( event ) { 1011 if ( event.type === 'keydown' && 13 !== event.which ) { // enter1031 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1012 1032 return; 1013 1033 } 1014 1034 event.preventDefault(); 1015 1035 1016 1036 this.params.attachment = this.params.defaultAttachment; 1017 1037 this.setting( this.params.defaultAttachment.url ); 1018 1038 }, 1019 1039 1020 1040 /** 1021 1041 * Called when the "Remove" link is clicked. Empties the setting. … … 1025 1045 removeFile: function( event ) { 1026 1046 if ( event.type === 'keydown' && 13 !== event.which ) { // enter 1027 1047 return; 1028 1048 } 1029 1049 event.preventDefault(); 1030 1050 1031 1051 this.params.attachment = {}; 1032 1052 this.setting( '' ); 1033 1053 this.renderContent(); // Not bound to setting change when emptying. 1034 1054 }, 1035 1055 1036 1056 // @deprecated 1037 1057 success: function() {}, 1038 1058 1039 1059 // @deprecated 1040 1060 removerVisibility: function() {} 1041 1061 }); 1042 1062 1043 1063 /** 1044 1064 * A control for uploading images. … … 1740 1760 $( function() { 1741 1761 api.settings = window._wpCustomizeSettings; 1742 1762 api.l10n = window._wpCustomizeControlsL10n; 1763 api.utils.setContainerRootElement( $( '#customize-theme-controls' ).children( 'ul:first' ) ); 1743 1764 1744 1765 // Check if we can run the Customizer. 1745 if ( ! api.settings ) 1766 if ( ! api.settings ) { 1746 1767 return; 1768 } 1747 1769 1748 1770 // Redirect to the fallback preview if any incompatibilities are found. 1749 1771 if ( ! $.support.postMessage || ( ! $.support.cors && api.settings.isCrossDomain ) ) … … 1768 1790 1769 1791 // Expand/Collapse the main customizer customize info 1770 1792 $( '#customize-info' ).find( '> .accordion-section-title' ).on( 'click keydown', function( event ) { 1771 if ( isKeydownButNotEnterEvent( event ) ) {1793 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1772 1794 return; 1773 1795 } 1774 1796 event.preventDefault(); // Keep this AFTER the key filter above … … 1930 1952 if ( id && api[ type ]( id ) ) { 1931 1953 instance = api[ type ]( id ); 1932 1954 // Wait until the element is embedded in the DOM 1933 instance.deferred. ready.done( function () {1955 instance.deferred.embedded.done( function () { 1934 1956 // Wait until the preview has activated and so active panels, sections, controls have been set 1935 1957 api.previewer.deferred.active.done( function () { 1936 1958 instance.focus(); … … 1956 1978 sectionContainers = _.pluck( sections, 'container' ); 1957 1979 rootNodes.push( panel ); 1958 1980 appendContainer = panel.container.find( 'ul:first' ); 1959 if ( ! a reElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) {1981 if ( ! api.utils.areElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) { 1960 1982 _( sections ).each( function ( section ) { 1961 1983 appendContainer.append( section.container ); 1962 1984 } ); … … 1972 1994 rootNodes.push( section ); 1973 1995 } 1974 1996 appendContainer = section.container.find( 'ul:first' ); 1975 if ( ! a reElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) {1997 if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) { 1976 1998 _( controls ).each( function ( control ) { 1977 1999 appendContainer.append( control.container ); 1978 2000 } ); … … 1981 2003 } ); 1982 2004 1983 2005 // Sort the root panels and sections 1984 rootNodes.sort( prioritySort );2006 rootNodes.sort( api.utils.prioritySort ); 1985 2007 rootContainers = _.pluck( rootNodes, 'container' ); 1986 appendContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todoThis should be defined elsewhere, and to be configurable1987 if ( ! a reElementListsEqual( rootContainers, appendContainer.children() ) ) {2008 appendContainer = api.utils.getContainerRootElement(); // implements todo: This should be defined elsewhere, and to be configurable 2009 if ( ! api.utils.areElementListsEqual( rootContainers, appendContainer.children() ) ) { 1988 2010 _( rootNodes ).each( function ( rootNode ) { 1989 2011 appendContainer.append( rootNode.container ); 1990 2012 } ); … … 2080 2102 2081 2103 // Go back to the top-level Customizer accordion. 2082 2104 $( '#customize-header-actions' ).on( 'click keydown', '.control-panel-back', function( event ) { 2083 if ( isKeydownButNotEnterEvent( event ) ) {2105 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 2084 2106 return; 2085 2107 } 2086 2108 … … 2104 2126 }); 2105 2127 2106 2128 $('.collapse-sidebar').on( 'click keydown', function( event ) { 2107 if ( isKeydownButNotEnterEvent( event ) ) {2129 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 2108 2130 return; 2109 2131 } 2110 2132 -
tests/qunit/index.html
diff --git tests/qunit/index.html tests/qunit/index.html index ce11144..df51b7a 100644
31 31 <script src="../../src/wp-includes/js/customize-base.js"></script> 32 32 <script src="../../src/wp-includes/js/customize-models.js"></script> 33 33 <script src="../../src/wp-includes/js/shortcode.js"></script> 34 <script src="../../src/wp-admin/js/customize-controls.js"></script> 34 35 35 36 <!-- Unit tests --> 36 37 <script src="wp-admin/js/password-strength-meter.js"></script> 37 38 <script src="wp-admin/js/customize-base.js"></script> 38 39 <script src="wp-admin/js/customize-header.js"></script> 39 40 <script src="wp-includes/js/shortcode.js"></script> 41 <script src="wp-admin/js/customize-controls.js"></script> 42 <script src="wp-admin/js/customize-controls-utils.js"></script> 40 43 </div> 41 44 </body> 42 45 </html> -
tests/qunit/wp-admin/js/customize-base.js
diff --git tests/qunit/wp-admin/js/customize-base.js tests/qunit/wp-admin/js/customize-base.js index 422111f..56357c9 100644
1 1 /* global wp */ 2 2 3 3 jQuery( function( $ ) { 4 var FooSuperClass, BarSubClass, foo, bar; 4 var FooSuperClass, BarSubClass, foo, bar, ConstructorTestClass, newConstructor, constructorTest, $mockElement, mockString, 5 firstInitialValue, firstValueInstance, wasCallbackFired, mockValueCallback; 5 6 6 7 module( 'Customize Base: Class' ); 7 8 … … jQuery( function( $ ) { 46 47 equal( foo.instanceProp, 'instancePropValue' ); 47 48 }); 48 49 49 // @todo Test Class.constructor() manipulation50 50 // @todo Test Class.applicator? 51 51 // @todo do we test object.instance? 52 52 53 54 53 module( 'Customize Base: Subclass' ); 55 54 56 55 BarSubClass = FooSuperClass.extend( … … jQuery( function( $ ) { 82 81 equal( bar.extended( FooSuperClass ), true ); 83 82 }); 84 83 84 85 // Implements todo : Test Class.constructor() manipulation 86 module( 'Customize Base: Constructor Manipulation' ); 87 88 newConstructor = function ( instanceProps ) { 89 $.extend( this , instanceProps || {} ); 90 }; 91 92 ConstructorTestClass = wp.customize.Class.extend( 93 { 94 constructor : newConstructor, 95 protoProp: 'protoPropValue' 96 }, 97 { 98 staticProp: 'staticPropValue' 99 } 100 ); 101 102 test( 'New constructor added to class' , function () { 103 equal( ConstructorTestClass.prototype.constructor , newConstructor ); 104 }); 105 test( 'Class with new constructor has protoPropValue' , function () { 106 equal( ConstructorTestClass.prototype.protoProp , 'protoPropValue' ); 107 }); 108 109 constructorTest = new ConstructorTestClass( { instanceProp: 'instancePropValue' } ); 110 test( 'ConstructorTestClass instance constructorTest has the new constructor', function () { 111 equal( constructorTest.constructor, newConstructor ); 112 }); 113 114 test( 'ConstructorTestClass instance constructorTest extended Class', function () { 115 equal( constructorTest.extended( wp.customize.Class ), true ); 116 }); 117 118 test( 'ConstructorTestClass instance constructorTest has the added instance property', function () { 119 equal( constructorTest.instanceProp , 'instancePropValue' ); 120 }); 121 122 123 module( 'Customize Base: wp.customizer.ensure' ); 124 125 $mockElement = $( '<div id="mockElement"></div>' ); 126 127 test( 'Handles jQuery argument' , function() { 128 equal( wp.customize.ensure( $mockElement ) , $mockElement ); 129 }); 130 131 mockString = '<div class="mockString"></div>'; 132 133 test( 'Handles string argument' , function() { 134 ok( wp.customize.ensure( mockString ) instanceof jQuery ); 135 }); 136 137 138 module( 'Customize Base: Value Class' ); 139 140 firstInitialValue = true; 141 firstValueInstance = new wp.customize.Value( firstInitialValue ); 142 143 test( 'Initialized with the right value' , function() { 144 equal( firstValueInstance.get() , firstInitialValue ); 145 }); 146 147 test( '.set() works' , function() { 148 firstValueInstance.set( false ); 149 equal( firstValueInstance.get() , false ); 150 }); 151 152 test( '.bind() adds new callback that fires on set()' , function() { 153 wasCallbackFired = false; 154 mockValueCallback = function() { 155 wasCallbackFired = true; 156 }; 157 firstValueInstance.bind( mockValueCallback ); 158 firstValueInstance.set( 'newValue' ); 159 ok( wasCallbackFired ); 160 }); 161 85 162 }); -
new file tests/qunit/wp-admin/js/customize-controls-utils.js
diff --git tests/qunit/wp-admin/js/customize-controls-utils.js tests/qunit/wp-admin/js/customize-controls-utils.js new file mode 100644 index 0000000..8c82a3c
- + 1 /* global wp */ 2 3 jQuery( function( $ ) { 4 var trueMockEvent, falseMockEvent, mockElementLists, $firstMockElement, $secondMockElement, $thirdMockElement, 5 BubbleTester, BubbleTesterTwoValues, bubbleTesterParent, firstBubbleTester, secondBubbleTester, $newRoot; 6 7 module( 'Customizer Model Utility functions' ); 8 9 trueMockEvent = { 10 type : 'keydown', 11 which : 14 12 }; 13 14 falseMockEvent = { 15 type : 'keydown', 16 which : 13 17 }; 18 19 test( 'isKeydownButNotEnterEvent returns true' , function () { 20 ok( wp.customize.utils.isKeydownButNotEnterEvent( trueMockEvent ) ); 21 }); 22 23 test( 'isKeydownButNotEnterEvent returns false' , function () { 24 equal( wp.customize.utils.isKeydownButNotEnterEvent( falseMockEvent ) , false ); 25 }); 26 27 $firstMockElement = $( '<div id="foo"></div>' ); 28 $secondMockElement = $( '<li id="bar"></li>' ); 29 $thirdMockElement = $( '<div id="thirdElement"></div>' ); 30 31 mockElementLists = { 32 first : [ $firstMockElement , $secondMockElement ], 33 second : [ $secondMockElement ], 34 firstInReverseOrder : [ $secondMockElement , $firstMockElement ], 35 third : [ $firstMockElement, $secondMockElement ], 36 thirdButLonger : [ $firstMockElement, $secondMockElement, $thirdMockElement ] 37 }; 38 39 test( 'areElementListsEqual returns true' , function () { 40 ok( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.first ) ); 41 }); 42 43 test( 'areElementListsEqual returns false' , function () { 44 equal( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.second ) , false ); 45 }); 46 47 test( 'areElementListsEqual: lists have same values, but in reverse order' , function () { 48 equal( wp.customize.utils.areElementListsEqual( mockElementLists.first , mockElementLists.firstInReverseOrder ) , false ); 49 }); 50 51 test( 'areElementListsEqual: lists have same values, but one is longer' , function () { 52 equal( wp.customize.utils.areElementListsEqual( mockElementLists.third , mockElementLists.thirdButLonger ) , false ); 53 }); 54 55 56 bubbleTesterParent = function() { 57 this.trigger = function( event , instance ) { 58 this.wasChangeTriggered = true; 59 this.instancePassedInTrigger = instance; 60 }; 61 this.wasChangeTriggered = false; 62 this.instancePassedInTrigger = {}; 63 }; 64 65 BubbleTester = wp.customize.Class.extend( 66 { 67 parent : new bubbleTesterParent(), 68 fooValue : new wp.customize.Value() 69 }, 70 { 71 staticProperty : 'propertyValue' 72 } 73 ); 74 75 test( 'bubbleChildValueChanges notifies parent of change' , function() { 76 firstBubbleTester = new BubbleTester(); 77 wp.customize.utils.bubbleChildValueChanges( firstBubbleTester , [ 'fooValue' ] ); 78 firstBubbleTester.fooValue.set( 'new value' ); 79 ok( firstBubbleTester.parent.wasChangeTriggered ); 80 }); 81 82 test( 'bubbleChildValueChanges passes a reference to its instance' , function() { 83 ok( firstBubbleTester.parent.instancePassedInTrigger instanceof BubbleTester ); 84 }); 85 86 BubbleTesterTwoValues = wp.customize.Class.extend( 87 { 88 parent : new bubbleTesterParent(), 89 exampleValue : new wp.customize.Value(), 90 barValue : new wp.customize.Value() 91 }, 92 { 93 staticProperty : 'propertyValue' 94 } 95 ); 96 97 secondBubbleTester = new BubbleTesterTwoValues(); 98 wp.customize.utils.bubbleChildValueChanges( secondBubbleTester , [ 'exampleValue' , 'barValue' ] ); 99 secondBubbleTester.barValue.set( 'new value' ); 100 101 test( 'bubbleChildValueChanges notifies parent of change when two values are bound' , function() { 102 ok( secondBubbleTester.parent.wasChangeTriggered ); 103 }); 104 105 test( 'bubbleChildValueChanges passes a reference to its instance when two values are bound' , function() { 106 ok( secondBubbleTester.parent.instancePassedInTrigger instanceof BubbleTesterTwoValues ); 107 }); 108 109 $newRoot = $( '<div id="#new-theme-controls"></div>' ); 110 wp.customize.utils.setContainerRootElement( $newRoot ); 111 112 test( 'setContainerRootElement sets the new root' , function() { 113 ok( wp.customize.utils.getContainerRootElement().is( $newRoot ) ); 114 }); 115 116 }); -
new file 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 new file mode 100644 index 0000000..05fa161
- + 1 /* global wp */ 2 3 jQuery( function( $ ) { 4 5 var controlId, controlLabel, controlType, controlContent, controlDescription, controlData, mockControl, 6 mockControlInstance, controlExpectedValues, sectionId, sectionContent, sectionData, mockSection, 7 sectionInstance, sectionExpectedValues, panelId, panelTitle, panelDescription, panelContent, panelData, 8 mockPanel, panelExpectedValues, testCustomizerModel; 9 10 testCustomizerModel = function( model, expectedValues ) { 11 var type = expectedValues.type || ""; 12 13 if ( expectedValues.hasOwnProperty( 'id' ) ) { 14 test( type + ' instance has the right id' , function () { 15 equal( model.id , expectedValues.id ); 16 }); 17 } 18 if ( expectedValues.hasOwnProperty( 'title') ) { 19 test( type + ' instance has the right title.', function () { 20 equal( model.params.title , expectedValues.title ); 21 }); 22 } 23 if ( expectedValues.hasOwnProperty( 'description' ) ) { 24 test( type + ' instance has the right description.', function () { 25 equal( model.params.description , expectedValues.description ); 26 }); 27 } 28 if ( expectedValues.hasOwnProperty( 'content' ) ) { 29 test( type + ' instance has the right content.', function () { 30 equal( model.params.content , expectedValues.content ); 31 }); 32 } 33 if ( expectedValues.hasOwnProperty( 'priority' ) ) { 34 test( type + ' instance has the right priority.', function () { 35 equal( model.priority() , expectedValues.priority ); 36 }); 37 } 38 if ( expectedValues.textExpanded ) { 39 test( type + ' instance is not expanded', function () { 40 equal( model.expanded() , false ); 41 }); 42 43 test( type + ' instance is expanded after calling .expanded()', function () { 44 model.expand(); 45 ok( model.expanded() ); 46 }); 47 48 test( type + ' instance is collapsed after calling .collapse()', function () { 49 model.collapse(); 50 equal( model.expanded() , false ); 51 }); 52 } 53 54 }; 55 56 57 module( 'Customizer Control Model' ); 58 59 controlId = 'new_blogname'; 60 controlLabel = 'Site Title'; 61 controlType = 'text'; 62 controlContent = '<li id="customize-control-blogname" class="customize-control customize-control-text"></li>'; 63 controlDescription = 'Test control description'; 64 65 controlData = { 66 content : controlContent, 67 description : controlDescription, 68 label : controlLabel, 69 settings : { default : 'blogname' }, 70 type : controlType 71 }; 72 73 mockControl = new wp.customize.Control( controlId , 74 { params : controlData, 75 previewer : wp.customize.previewer 76 } 77 ); 78 79 controlExpectedValues = { 80 type : 'Control', 81 content : controlContent, 82 descrption : controlDescription, 83 label : controlLabel, 84 id : controlId, 85 priority : 10, 86 textExpanded : false 87 }; 88 89 testCustomizerModel( mockControl , controlExpectedValues ); 90 91 test( 'Control instance does not yet belong to a section.', function () { 92 equal( mockControl.section() , undefined ); 93 }); 94 95 test( 'Control instance has the right selector.', function () { 96 equal( mockControl.selector , '#customize-control-new_blogname' ); 97 }); 98 99 wp.customize.control.add( controlId , mockControl ); 100 101 test( 'Control instance was added to the control class.', function () { 102 ok( wp.customize.control.has( controlId ) ); 103 }); 104 105 mockControlInstance = wp.customize.control( controlId ); 106 107 test( 'Control instance has the right id when accessed from api.control().', function () { 108 equal( mockControlInstance.id , controlId ); 109 }); 110 111 112 module( 'Customizer Section Model' ); 113 114 sectionId = 'mock_title_tagline'; 115 sectionContent = '<li id="accordion-section-title_tagline" class="control-section accordion-section"></li>'; 116 sectionData = { 117 content : sectionContent 118 }; 119 120 mockSection = new wp.customize.Section( sectionId , { params : sectionData } ); 121 122 sectionExpectedValues = { 123 type : 'Section', 124 id : sectionId, 125 content : sectionContent, 126 priority : 100, 127 testExpanded : true 128 }; 129 130 testCustomizerModel( mockSection , sectionExpectedValues ); 131 132 wp.customize.section.add( sectionId , mockSection ); 133 134 test( 'Section instance added to the wp.customize.section object', function () { 135 ok( wp.customize.section.has( sectionId ) ); 136 }); 137 138 sectionInstance = wp.customize.section( sectionId ); 139 140 test( 'Section instance has right content when accessed from wp.customize.section()', function () { 141 equal( sectionInstance.params.content , sectionContent ); 142 }); 143 144 145 module( 'Customizer Panel Model' ); 146 147 panelId = 'mockPanelId'; 148 panelTitle = 'Mock Panel Title'; 149 panelDescription = 'Mock panel description'; 150 panelContent = '<li id="accordion-panel-widgets" class="control-section control-panel accordion-section">'; 151 panelData = { 152 content : panelContent, 153 title : panelTitle, 154 description : panelDescription 155 }; 156 157 mockPanel = new wp.customize.Panel( panelId , { params : panelData } ); 158 159 panelExpectedValues = { 160 type : 'Panel', 161 id : panelId, 162 title : panelTitle , 163 description : panelDescription, 164 content : panelContent, 165 priority : 100, 166 testExpanded : true 167 }; 168 169 testCustomizerModel( mockPanel , panelExpectedValues ); 170 171 test( 'Panel instance is not contextuallyActive', function () { 172 equal( mockPanel.isContextuallyActive() , false ); 173 }); 174 175 }); -
tests/qunit/wp-admin/js/customize-header.js
diff --git tests/qunit/wp-admin/js/customize-header.js tests/qunit/wp-admin/js/customize-header.js index d5f0110..31fa14f 100644
jQuery( function() { 128 128 129 129 equal(this.model.shouldBeCropped(), false); 130 130 }); 131 131 132 });