diff options
author | Scott González <scott.gonzalez@gmail.com> | 2015-04-07 10:55:52 -0400 |
---|---|---|
committer | Scott González <scott.gonzalez@gmail.com> | 2015-04-09 09:27:00 -0400 |
commit | bde431bb449b1d957d4e0b736111ff342f2a919d (patch) | |
tree | 27fd40037c30dbff8ef3b6113e90817ab96b53bf /tests/unit/widget/core.js | |
parent | dc4b015a8b9acdb5bff2d5dd89737b3d8b64097f (diff) | |
download | jquery-ui-bde431bb449b1d957d4e0b736111ff342f2a919d.tar.gz jquery-ui-bde431bb449b1d957d4e0b736111ff342f2a919d.zip |
Tests: Rename files
Ref gh-1528
Diffstat (limited to 'tests/unit/widget/core.js')
-rw-r--r-- | tests/unit/widget/core.js | 1514 |
1 files changed, 1514 insertions, 0 deletions
diff --git a/tests/unit/widget/core.js b/tests/unit/widget/core.js new file mode 100644 index 000000000..22832765b --- /dev/null +++ b/tests/unit/widget/core.js @@ -0,0 +1,1514 @@ +define( [ + "jquery", + "lib/common", + "ui/widget" +], function( $, common ) { + +module( "widget factory", { + teardown: function() { + if ( $.ui ) { + delete $.ui.testWidget; + delete $.fn.testWidget; + } + } +}); + +common.testJshint( "widget" ); + +test( "widget creation", function() { + expect( 5 ); + var method, + myPrototype = { + _create: function() { + equal( method, "_create", "create function is copied over" ); + }, + creationTest: function() { + equal( method, "creationTest", "random function is copied over" ); + } + }; + + $.widget( "ui.testWidget", myPrototype ); + ok( $.isFunction( $.ui.testWidget ), "constructor was created" ); + equal( typeof $.ui.testWidget.prototype, "object", "prototype was created" ); + method = "_create"; + $.ui.testWidget.prototype._create(); + method = "creationTest"; + $.ui.testWidget.prototype.creationTest(); + equal( $.ui.testWidget.prototype.option, $.Widget.prototype.option, + "option method copied over from base widget" ); +}); + +test( "element normalization", function() { + expect( 11 ); + var elem; + $.widget( "ui.testWidget", {} ); + + $.ui.testWidget.prototype._create = function() { + // workaround for core ticket #8381 + this.element.appendTo( "#qunit-fixture" ); + ok( this.element.is( "div" ), "generated div" ); + deepEqual( this.element.testWidget( "instance" ), this, "instance stored in .data()" ); + }; + $.ui.testWidget(); + + $.ui.testWidget.prototype.defaultElement = "<span data-test='pass'></span>"; + $.ui.testWidget.prototype._create = function() { + ok( this.element.is( "span[data-test=pass]" ), "generated span with properties" ); + deepEqual( this.element.testWidget( "instance" ), this, "instance stored in .data()" ); + }; + $.ui.testWidget(); + + elem = $( "<input>" ); + $.ui.testWidget.prototype._create = function() { + deepEqual( this.element[ 0 ], elem[ 0 ], "from element" ); + deepEqual( elem.testWidget( "instance" ), this, "instance stored in .data()" ); + }; + $.ui.testWidget( {}, elem[ 0 ] ); + + elem = $( "<div>" ); + $.ui.testWidget.prototype._create = function() { + deepEqual( this.element[ 0 ], elem[ 0 ], "from jQuery object" ); + deepEqual( elem.testWidget( "instance" ), this, "instance stored in .data()" ); + }; + $.ui.testWidget( {}, elem ); + + elem = $( "<div id='element-normalization-selector'></div>" ) + .appendTo( "#qunit-fixture" ); + $.ui.testWidget.prototype._create = function() { + deepEqual( this.element[ 0 ], elem[ 0 ], "from selector" ); + deepEqual( elem.testWidget( "instance" ), this, "instance stored in .data()" ); + }; + $.ui.testWidget( {}, "#element-normalization-selector" ); + + $.ui.testWidget.prototype.defaultElement = null; + $.ui.testWidget.prototype._create = function() { + // using strictEqual throws an error (Maximum call stack size exceeded) + ok( this.element[ 0 ] === this, "instance as element" ); + }; + $.ui.testWidget(); +}); + +test( "custom selector expression", function() { + expect( 1 ); + var elem = $( "<div>" ).appendTo( "#qunit-fixture" ); + $.widget( "ui.testWidget", {} ); + elem.testWidget(); + deepEqual( $( ":ui-testwidget" )[0], elem[0] ); + elem.testWidget( "destroy" ); +}); + +test( "jQuery usage", function() { + expect( 14 ); + + var elem, instance, ret, + shouldCreate = false; + + $.widget( "ui.testWidget", { + getterSetterVal: 5, + _create: function() { + ok( shouldCreate, "create called on instantiation" ); + }, + methodWithParams: function( param1, param2 ) { + ok( true, "method called via .pluginName(methodName)" ); + equal( param1, "value1", + "parameter passed via .pluginName(methodName, param)" ); + equal( param2, "value2", + "multiple parameters passed via .pluginName(methodName, param, param)" ); + + return this; + }, + getterSetterMethod: function( val ) { + if ( val ) { + this.getterSetterVal = val; + } else { + return this.getterSetterVal; + } + }, + jQueryObject: function() { + return $( "body" ); + } + }); + + shouldCreate = true; + elem = $( "<div>" ) + .bind( "testwidgetcreate", function() { + ok( shouldCreate, "create event triggered on instantiation" ); + }) + .testWidget(); + shouldCreate = false; + + instance = elem.testWidget( "instance" ); + equal( typeof instance, "object", "instance stored in .data(pluginName)" ); + equal( instance.element[0], elem[0], "element stored on widget" ); + ret = elem.testWidget( "methodWithParams", "value1", "value2" ); + equal( ret, elem, "jQuery object returned from method call" ); + + ret = elem.testWidget( "getterSetterMethod" ); + equal( ret, 5, "getter/setter can act as getter" ); + ret = elem.testWidget( "getterSetterMethod", 30 ); + equal( ret, elem, "getter/setter method can be chainable" ); + equal( instance.getterSetterVal, 30, "getter/setter can act as setter" ); + ret = elem.testWidget( "jQueryObject" ); + equal( ret[ 0 ], document.body, "returned jQuery object" ); + equal( ret.end(), elem, "stack preserved" ); + + elem.testWidget( "destroy" ); + equal( elem.testWidget( "instance" ), null ); +}); + +test( "direct usage", function() { + expect( 9 ); + + var elem, instance, ret, + shouldCreate = false; + + $.widget( "ui.testWidget", { + getterSetterVal: 5, + _create: function() { + ok( shouldCreate, "create called on instantiation" ); + }, + methodWithParams: function( param1, param2 ) { + ok( true, "method called dirctly" ); + equal( param1, "value1", "parameter passed via direct call" ); + equal( param2, "value2", "multiple parameters passed via direct call" ); + + return this; + }, + getterSetterMethod: function( val ) { + if ( val ) { + this.getterSetterVal = val; + } else { + return this.getterSetterVal; + } + } + }); + + elem = $( "<div>" )[ 0 ]; + + shouldCreate = true; + instance = new $.ui.testWidget( {}, elem ); + shouldCreate = false; + + equal( $( elem ).testWidget( "instance" ), instance, + "instance stored in .data(pluginName)" ); + equal( instance.element[ 0 ], elem, "element stored on widget" ); + + ret = instance.methodWithParams( "value1", "value2" ); + equal( ret, instance, "plugin returned from method call" ); + + ret = instance.getterSetterMethod(); + equal( ret, 5, "getter/setter can act as getter" ); + instance.getterSetterMethod( 30 ); + equal( instance.getterSetterVal, 30, "getter/setter can act as setter" ); +}); + +test( "error handling", function() { + expect( 3 ); + var error = $.error; + $.widget( "ui.testWidget", { + _privateMethod: function () {} + }); + $.error = function( msg ) { + equal( msg, "cannot call methods on testWidget prior to initialization; " + + "attempted to call method 'missing'", "method call before init" ); + }; + $( "<div>" ).testWidget( "missing" ); + $.error = function( msg ) { + equal( msg, "no such method 'missing' for testWidget widget instance", + "invalid method call on widget instance" ); + }; + $( "<div>" ).testWidget().testWidget( "missing" ); + $.error = function ( msg ) { + equal( msg, "no such method '_privateMethod' for testWidget widget instance", + "invalid method call on widget instance" ); + }; + $( "<div>" ).testWidget().testWidget( "_privateMethod" ); + $.error = error; +}); + +test( "merge multiple option arguments", function() { + expect( 1 ); + $.widget( "ui.testWidget", { + _create: function() { + deepEqual( this.options, { + classes: {}, + create: null, + disabled: false, + option1: "value1", + option2: "value2", + option3: "value3", + option4: { + option4a: "valuea", + option4b: "valueb" + } + }); + } + }); + $( "<div>" ).testWidget({ + option1: "valuex", + option2: "valuex", + option3: "value3", + option4: { + option4a: "valuex" + } + }, { + option1: "value1", + option2: "value2", + option4: { + option4b: "valueb" + } + }, { + option4: { + option4a: "valuea" + } + }); +}); + +test( "._getCreateOptions()", function() { + expect( 3 ); + $.widget( "ui.testWidget", { + options: { + option1: "valuex", + option2: "valuex", + option3: "value3" + }, + _getCreateOptions: function() { + + // Support: IE8 + // Strict equality fails when comparing this.window in ie8 + equal( this.window[ 0 ], window, "this.window is properly defined" ); + strictEqual( this.document[ 0 ], document, "this.document is properly defined" ); + + return { + option1: "override1", + option2: "overideX" + }; + }, + _create: function() { + deepEqual( this.options, { + classes: {}, + create: null, + disabled: false, + option1: "override1", + option2: "value2", + option3: "value3" + }); + } + }); + $( "<div>" ).testWidget({ option2: "value2" }); +}); + +test( "._getCreateEventData()", function() { + expect( 1 ); + var data = { foo: "bar" }; + $.widget( "ui.testWidget", { + _getCreateEventData: function() { + return data; + } + }); + $( "<div>" ).testWidget({ + create: function( event, ui ) { + strictEqual( ui, data, "event data" ); + } + }); +}); + +test( "re-init", function() { + expect( 3 ); + var div = $( "<div>" ), + actions = []; + + $.widget( "ui.testWidget", { + _create: function() { + actions.push( "create" ); + }, + _init: function() { + actions.push( "init" ); + }, + _setOption: function( key ) { + actions.push( "option" + key ); + } + }); + + actions = []; + div.testWidget({ foo: "bar" }); + deepEqual( actions, [ "create", "init" ], "correct methods called on init" ); + + actions = []; + div.testWidget(); + deepEqual( actions, [ "init" ], "correct methods call on re-init" ); + + actions = []; + div.testWidget({ foo: "bar" }); + deepEqual( actions, [ "optionfoo", "init" ], "correct methods called on re-init with options" ); +}); + +test( "redeclare", function() { + expect( 2 ); + + $.widget( "ui.testWidget", {} ); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "testWidget" ); + + $.widget( "ui.testWidget", {} ); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "testWidget" ); +}); + +test( "inheritance", function() { + expect( 6 ); + // #5830 - Widget: Using inheritance overwrites the base classes options + $.widget( "ui.testWidgetBase", { + options: { + obj: { + key1: "foo", + key2: "bar" + }, + arr: [ "testing" ] + } + }); + + $.widget( "ui.testWidgetExtension", $.ui.testWidgetBase, { + options: { + obj: { + key1: "baz" + }, + arr: [ "alpha", "beta" ] + } + }); + + equal( $.ui.testWidgetBase.prototype.widgetEventPrefix, "testWidgetBase", + "base class event prefix" ); + deepEqual( $.ui.testWidgetBase.prototype.options.obj, { + key1: "foo", + key2: "bar" + }, "base class option object not overridden"); + deepEqual( $.ui.testWidgetBase.prototype.options.arr, [ "testing" ], + "base class option array not overridden"); + + equal( $.ui.testWidgetExtension.prototype.widgetEventPrefix, "testWidgetExtension", + "extension class event prefix" ); + deepEqual( $.ui.testWidgetExtension.prototype.options.obj, { + key1: "baz", + key2: "bar" + }, "extension class option object extends base"); + deepEqual( $.ui.testWidgetExtension.prototype.options.arr, [ "alpha", "beta" ], + "extension class option array overwrites base"); + + delete $.ui.testWidgetBase; + delete $.ui.testWidgetExtension; +}); + +test( "._super()", function() { + expect( 9 ); + var instance; + $.widget( "ui.testWidget", { + method: function( a, b ) { + deepEqual( this, instance, "this is correct in testWidget" ); + deepEqual( a, 5, "parameter passed to testWidget" ); + deepEqual( b, 20, "second parameter passed to testWidget" ); + return a + b; + } + }); + + $.widget( "ui.testWidget2", $.ui.testWidget, { + method: function( a, b ) { + deepEqual( this, instance, "this is correct in testWidget2" ); + deepEqual( a, 5, "parameter passed to testWidget2" ); + deepEqual( b, 10, "parameter passed to testWidget2" ); + return this._super( a, b*2 ); + } + }); + + $.widget( "ui.testWidget3", $.ui.testWidget2, { + method: function( a ) { + deepEqual( this, instance, "this is correct in testWidget3" ); + deepEqual( a, 5, "parameter passed to testWidget3" ); + var ret = this._super( a, a*2 ); + deepEqual( ret, 25, "super returned value" ); + } + }); + + instance = $( "<div>" ).testWidget3().testWidget3( "instance" ); + instance.method( 5 ); + delete $.ui.testWidget3; + delete $.ui.testWidget2; +}); + +test( "._superApply()", function() { + expect( 10 ); + var instance; + $.widget( "ui.testWidget", { + method: function( a, b ) { + deepEqual( this, instance, "this is correct in testWidget" ); + deepEqual( a, 5, "parameter passed to testWidget" ); + deepEqual( b, 10, "second parameter passed to testWidget" ); + return a + b; + } + }); + + $.widget( "ui.testWidget2", $.ui.testWidget, { + method: function( a, b ) { + deepEqual( this, instance, "this is correct in testWidget2" ); + deepEqual( a, 5, "parameter passed to testWidget2" ); + deepEqual( b, 10, "second parameter passed to testWidget2" ); + return this._superApply( arguments ); + } + }); + + $.widget( "ui.testWidget3", $.ui.testWidget2, { + method: function( a, b ) { + deepEqual( this, instance, "this is correct in testWidget3" ); + deepEqual( a, 5, "parameter passed to testWidget3" ); + deepEqual( b, 10, "second parameter passed to testWidget3" ); + var ret = this._superApply( arguments ); + deepEqual( ret, 15, "super returned value" ); + } + }); + + instance = $( "<div>" ).testWidget3().testWidget3( "instance" ); + instance.method( 5, 10 ); + delete $.ui.testWidget3; + delete $.ui.testWidget2; +}); + +test( ".option() - getter", function() { + expect( 6 ); + $.widget( "ui.testWidget", { + _create: function() {} + }); + + var options, + div = $( "<div>" ).testWidget({ + foo: "bar", + baz: 5, + qux: [ "quux", "quuux" ] + }); + + deepEqual( div.testWidget( "option", "x" ), null, "non-existent option" ); + deepEqual( div.testWidget( "option", "foo"), "bar", "single option - string" ); + deepEqual( div.testWidget( "option", "baz"), 5, "single option - number" ); + deepEqual( div.testWidget( "option", "qux"), [ "quux", "quuux" ], + "single option - array" ); + + options = div.testWidget( "option" ); + deepEqual( options, { + baz: 5, + classes: {}, + create: null, + disabled: false, + foo: "bar", + qux: [ "quux", "quuux" ] + }, "full options hash returned" ); + options.foo = "notbar"; + deepEqual( div.testWidget( "option", "foo"), "bar", + "modifying returned options hash does not modify plugin instance" ); +}); + +test( ".option() - deep option getter", function() { + expect( 5 ); + $.widget( "ui.testWidget", {} ); + var div = $( "<div>" ).testWidget({ + foo: { + bar: "baz", + qux: { + quux: "xyzzy" + } + } + }); + equal( div.testWidget( "option", "foo.bar" ), "baz", "one level deep - string" ); + deepEqual( div.testWidget( "option", "foo.qux" ), { quux: "xyzzy" }, + "one level deep - object" ); + equal( div.testWidget( "option", "foo.qux.quux" ), "xyzzy", "two levels deep - string" ); + equal( div.testWidget( "option", "x.y" ), null, "top level non-existent" ); + equal( div.testWidget( "option", "foo.x.y" ), null, "one level deep - non-existent" ); +}); + +test( ".option() - delegate to ._setOptions()", function() { + expect( 2 ); + var div, + calls = []; + $.widget( "ui.testWidget", { + _create: function() {}, + _setOptions: function( options ) { + calls.push( options ); + } + }); + div = $( "<div>" ).testWidget(); + + calls = []; + div.testWidget( "option", "foo", "bar" ); + deepEqual( calls, [{ foo: "bar" }], "_setOptions called for single option" ); + + calls = []; + div.testWidget( "option", { + bar: "qux", + quux: "quuux" + }); + deepEqual( calls, [{ bar: "qux", quux: "quuux" }], + "_setOptions called with multiple options" ); +}); + +test( ".option() - delegate to ._setOption()", function() { + expect( 3 ); + var div, + calls = []; + $.widget( "ui.testWidget", { + _create: function() {}, + _setOption: function( key, val ) { + calls.push({ + key: key, + val: val + }); + } + }); + div = $( "<div>" ).testWidget(); + + calls = []; + div.testWidget( "option", "foo", "bar" ); + deepEqual( calls, [{ key: "foo", val: "bar" }], + "_setOption called for single option" ); + + calls = []; + div.testWidget( "option", "foo", undefined ); + deepEqual( calls, [{ key: "foo", val: undefined }], + "_setOption called for single option where value is undefined" ); + + calls = []; + div.testWidget( "option", { + bar: "qux", + quux: "quuux" + }); + deepEqual( calls, [ + { key: "bar", val: "qux" }, + { key: "quux", val: "quuux" } + ], "_setOption called with multiple options" ); +}); + +test( ".option() - deep option setter", function() { + expect( 9 ); + $.widget( "ui.testWidget", {} ); + var result, div = $( "<div>" ).testWidget(); + function deepOption( from, to, msg ) { + div.testWidget( "instance" ).options.foo = from; + $.ui.testWidget.prototype._setOption = function( key, value ) { + deepEqual( key, "foo", msg + ": key" ); + deepEqual( value, to, msg + ": value" ); + }; + } + + deepOption( { bar: "baz" }, { bar: "qux" }, "one deep" ); + div.testWidget( "option", "foo.bar", "qux" ); + + deepOption( { bar: "baz" }, { bar: undefined }, "one deep - value = undefined" ); + + result = div.testWidget( "option", "foo.bar", undefined ); + + deepEqual ( result, div, "option should return widget on successful set operation" ); + + deepOption( null, { bar: "baz" }, "null" ); + div.testWidget( "option", "foo.bar", "baz" ); + + deepOption( + { bar: "baz", qux: { quux: "quuux" } }, + { bar: "baz", qux: { quux: "quuux", newOpt: "newVal" } }, + "add property" ); + div.testWidget( "option", "foo.qux.newOpt", "newVal" ); +}); + +test( ".enable()", function() { + expect( 2 ); + $.widget( "ui.testWidget", { + _create: function() {}, + _setOption: function( key, val ) { + deepEqual( key, "disabled", "_setOption called with disabled option" ); + deepEqual( val, false, "disabled set to false" ); + } + }); + $( "<div>" ).testWidget().testWidget( "enable" ); +}); + +test( ".disable()", function() { + expect( 2 ); + $.widget( "ui.testWidget", { + _create: function() {}, + _setOption: function( key, val ) { + deepEqual( key, "disabled", "_setOption called with disabled option" ); + deepEqual( val, true, "disabled set to true" ); + } + }); + $( "<div>" ).testWidget().testWidget( "disable" ); +}); + +test( ".widget() - base", function() { + expect( 2 ); + var constructor = $.widget( "ui.testWidget", { + _create: function() {} + }), + div = $( "<div>" ).testWidget(); + deepEqual( div[0], div.testWidget( "widget" )[0]); + deepEqual( constructor, $.ui.testWidget, "$.widget returns the constructor" ); +}); + +test( ".widget() - overriden", function() { + expect( 1 ); + var wrapper = $( "<div>" ); + $.widget( "ui.testWidget", { + _create: function() {}, + widget: function() { + return wrapper; + } + }); + deepEqual( wrapper[0], $( "<div>" ).testWidget().testWidget( "widget" )[0] ); +}); + +test( ".instance()", function() { + expect( 2 ); + var div; + + $.widget( "ui.testWidget", { + _create: function() {} + }); + + div = $( "<div>" ); + equal( div.testWidget( "instance" ), undefined ); + div.testWidget(); + equal( div.testWidget( "instance" ), div.testWidget( "instance" ) ); +}); + +test( "._on() to element (default)", function() { + expect( 12 ); + var that, widget; + $.widget( "ui.testWidget", { + _create: function() { + that = this; + this._on({ + keyup: this.keyup, + keydown: "keydown" + }); + }, + keyup: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keyup", event.type ); + }, + keydown: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keydown", event.type ); + } + }); + widget = $( "<div></div>" ) + .testWidget() + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "disable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "enable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "destroy" ) + .trigger( "keyup" ) + .trigger( "keydown" ); +}); + +test( "._on() to element with suppressDisabledCheck", function() { + expect( 18 ); + var that, widget; + $.widget( "ui.testWidget", { + _create: function() { + that = this; + this._on( true, { + keyup: this.keyup, + keydown: "keydown" + }); + }, + keyup: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keyup", event.type ); + }, + keydown: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keydown", event.type ); + } + }); + widget = $( "<div></div>" ) + .testWidget() + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "disable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "enable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "destroy" ) + .trigger( "keyup" ) + .trigger( "keydown" ); +}); + +test( "._on() to descendent", function() { + expect( 12 ); + var that, widget, descendant; + $.widget( "ui.testWidget", { + _create: function() { + that = this; + this._on( this.element.find( "strong" ), { + keyup: this.keyup, + keydown: "keydown" + }); + }, + keyup: function( event ) { + equal( that, this ); + equal( that.element.find( "strong" )[0], event.currentTarget ); + equal( "keyup", event.type ); + }, + keydown: function(event) { + equal( that, this ); + equal( that.element.find( "strong" )[0], event.currentTarget ); + equal( "keydown", event.type ); + } + }); + // trigger events on both widget and descendent to ensure that only descendent receives them + widget = $( "<div><p><strong>hello</strong> world</p></div>" ) + .testWidget() + .trigger( "keyup" ) + .trigger( "keydown" ); + descendant = widget.find( "strong" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "disable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + descendant + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "enable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + descendant + .trigger( "keyup" ) + .trigger( "keydown" ); + descendant + .addClass( "ui-state-disabled" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "destroy" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + descendant + .trigger( "keyup" ) + .trigger( "keydown" ); +}); + +test( "_on() with delegate", function() { + expect( 8 ); + $.widget( "ui.testWidget", { + _create: function() { + var uuid = this.uuid; + this.element = { + bind: function( event, handler ) { + equal( event, "click.testWidget" + uuid ); + ok( $.isFunction(handler) ); + }, + trigger: $.noop + }; + this.widget = function() { + return { + delegate: function( selector, event, handler ) { + equal( selector, "a" ); + equal( event, "click.testWidget" + uuid ); + ok( $.isFunction(handler) ); + } + }; + }; + this._on({ + "click": "handler", + "click a": "handler" + }); + this.widget = function() { + return { + delegate: function( selector, event, handler ) { + equal( selector, "form fieldset > input" ); + equal( event, "change.testWidget" + uuid ); + ok( $.isFunction(handler) ); + } + }; + }; + this._on({ + "change form fieldset > input": "handler" + }); + } + }); + $.ui.testWidget(); +}); + +test( "_on() with delegate to descendent", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + _create: function() { + this.target = $( "<p><strong>hello</strong> world</p>" ); + this.child = this.target.children(); + this._on( this.target, { + "keyup": "handlerDirect", + "keyup strong": "handlerDelegated" + }); + this.child.trigger( "keyup" ); + }, + handlerDirect: function( event ) { + deepEqual( event.currentTarget, this.target[ 0 ] ); + deepEqual( event.target, this.child[ 0 ] ); + }, + handlerDelegated: function( event ) { + deepEqual( event.currentTarget, this.child[ 0 ] ); + deepEqual( event.target, this.child[ 0 ] ); + } + }); + $.ui.testWidget(); +}); + +test( "_on() to common element", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + _create: function() { + this._on( this.document, { + "customevent": "_handler", + "with:colons": "_colonHandler", + "with-dashes": "_dashHandler", + "with-dashes:and-colons": "_commbinedHandler" + }); + }, + _handler: function() { + ok( true, "handler triggered" ); + }, + _colonHandler: function() { + ok( true, "colon handler triggered" ); + }, + _dashHandler: function() { + ok( true, "dash handler triggered" ); + }, + _commbinedHandler: function() { + ok( true, "combined handler triggered" ); + } + }); + var widget = $( "#widget" ).testWidget().testWidget( "instance" ); + $( "#widget-wrapper" ).testWidget(); + widget.destroy(); + $( document ).trigger( "customevent" ); + $( document ).trigger( "with:colons" ); + $( document ).trigger( "with-dashes" ); + $( document ).trigger( "with-dashes:and-colons" ); +}); + +test( "_off() - single event", function() { + expect( 3 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().testWidget( "instance" ); + widget._on( element, { foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }}); + element.bind( "foo", function() { + ok( shouldTriggerOther, "foo called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + shouldTriggerWidget = false; + widget._off( element, "foo" ); + element.trigger( "foo" ); +}); + +test( "_off() - multiple events", function() { + expect( 6 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().testWidget( "instance" ); + widget._on( element, { + foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }, + bar: function() { + ok( shouldTriggerWidget, "bar called from _on" ); + } + }); + element.bind( "foo bar", function( event ) { + ok( shouldTriggerOther, event.type + " called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + element.trigger( "bar" ); + shouldTriggerWidget = false; + widget._off( element, "foo bar" ); + element.trigger( "foo" ); + element.trigger( "bar" ); +}); + +test( "_off() - all events", function() { + expect( 6 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().testWidget( "instance" ); + widget._on( element, { + foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }, + bar: function() { + ok( shouldTriggerWidget, "bar called from _on" ); + } + }); + element.bind( "foo bar", function( event ) { + ok( shouldTriggerOther, event.type + " called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + element.trigger( "bar" ); + shouldTriggerWidget = false; + widget._off( element ); + element.trigger( "foo" ); + element.trigger( "bar" ); +}); + +test( "._hoverable()", function( assert ) { + expect( 10 ); + $.widget( "ui.testWidget", { + _create: function() { + this._hoverable( this.element.children() ); + } + }); + + var div = $( "#widget" ).testWidget().children(); + assert.lacksClasses( div, "ui-state-hover", "not hovered on init" ); + div.trigger( "mouseenter" ); + assert.hasClasses( div, "ui-state-hover", "hovered after mouseenter" ); + div.trigger( "mouseleave" ); + assert.lacksClasses( div, "ui-state-hover", "not hovered after mouseleave" ); + + div.trigger( "mouseenter" ); + assert.hasClasses( div, "ui-state-hover", "hovered after mouseenter" ); + $( "#widget" ).testWidget( "disable" ); + assert.lacksClasses( div, "ui-state-hover", "not hovered while disabled" ); + div.trigger( "mouseenter" ); + assert.lacksClasses( div, "ui-state-hover", "can't hover while disabled" ); + $( "#widget" ).testWidget( "enable" ); + assert.lacksClasses( div, "ui-state-hover", "enabling doesn't reset hover" ); + + div.trigger( "mouseenter" ); + assert.hasClasses( div, "ui-state-hover", "hovered after mouseenter" ); + $( "#widget" ).testWidget( "destroy" ); + assert.lacksClasses( div, "ui-state-hover", "not hovered after destroy" ); + div.trigger( "mouseenter" ); + assert.lacksClasses( div, "ui-state-hover", "event handler removed on destroy" ); +}); + +test( "._focusable()", function( assert ) { + expect( 10 ); + $.widget( "ui.testWidget", { + _create: function() { + this._focusable( this.element.children() ); + } + }); + + var div = $( "#widget" ).testWidget().children(); + assert.lacksClasses( div, "ui-state-focus", "not focused on init" ); + div.trigger( "focusin" ); + assert.hasClasses( div, "ui-state-focus", "focused after explicit focus" ); + div.trigger( "focusout" ); + assert.lacksClasses( div, "ui-state-focus", "not focused after blur" ); + + div.trigger( "focusin" ); + assert.hasClasses( div, "ui-state-focus", "focused after explicit focus" ); + $( "#widget" ).testWidget( "disable" ); + assert.lacksClasses( div, "ui-state-focus", "not focused while disabled" ); + div.trigger( "focusin" ); + assert.lacksClasses( div, "ui-state-focus", "can't focus while disabled" ); + $( "#widget" ).testWidget( "enable" ); + assert.lacksClasses( div, "ui-state-focus", "enabling doesn't reset focus" ); + + div.trigger( "focusin" ); + assert.hasClasses( div, "ui-state-focus", "focused after explicit focus" ); + $( "#widget" ).testWidget( "destroy" ); + assert.lacksClasses( div, "ui-state-focus", "not focused after destroy" ); + div.trigger( "focusin" ); + assert.lacksClasses( div, "ui-state-focus", "event handler removed on destroy" ); +}); + +test( "._trigger() - no event, no ui", function() { + expect( 7 ); + var handlers = []; + + $.widget( "ui.testWidget", { + _create: function() {} + }); + + $( "#widget" ).testWidget({ + foo: function( event, ui ) { + deepEqual( event.type, "testwidgetfoo", "correct event type in callback" ); + deepEqual( ui, {}, "empty ui hash passed" ); + handlers.push( "callback" ); + } + }); + $( document ).add( "#widget-wrapper" ).add( "#widget" ) + .bind( "testwidgetfoo", function( event, ui ) { + deepEqual( ui, {}, "empty ui hash passed" ); + handlers.push( this ); + }); + deepEqual( $( "#widget" ).testWidget( "instance" )._trigger( "foo" ), true, + "_trigger returns true when event is not cancelled" ); + deepEqual( handlers, [ + $( "#widget" )[ 0 ], + $( "#widget-wrapper" )[ 0 ], + document, + "callback" + ], "event bubbles and then invokes callback" ); + + $( document ).unbind( "testwidgetfoo" ); +}); + +test( "._trigger() - cancelled event", function() { + expect( 3 ); + + $.widget( "ui.testWidget", { + _create: function() {} + }); + + $( "#widget" ).testWidget({ + foo: function() { + ok( true, "callback invoked even if event is cancelled" ); + } + }) + .bind( "testwidgetfoo", function() { + ok( true, "event was triggered" ); + return false; + }); + deepEqual( $( "#widget" ).testWidget( "instance" )._trigger( "foo" ), false, + "_trigger returns false when event is cancelled" ); +}); + +test( "._trigger() - cancelled callback", function() { + expect( 1 ); + $.widget( "ui.testWidget", { + _create: function() {} + }); + + $( "#widget" ).testWidget({ + foo: function() { + return false; + } + }); + deepEqual( $( "#widget" ).testWidget( "instance" )._trigger( "foo" ), false, + "_trigger returns false when callback returns false" ); +}); + +test( "._trigger() - provide event and ui", function() { + expect( 7 ); + + var originalEvent = $.Event( "originalTest" ); + $.widget( "ui.testWidget", { + _create: function() {}, + testEvent: function() { + var ui = { + foo: "bar", + baz: { + qux: 5, + quux: 20 + } + }; + this._trigger( "foo", originalEvent, ui ); + deepEqual( ui, { + foo: "notbar", + baz: { + qux: 10, + quux: "jQuery" + } + }, "ui object modified" ); + } + }); + $( "#widget" ).bind( "testwidgetfoo", function( event, ui ) { + equal( event.originalEvent, originalEvent, "original event object passed" ); + deepEqual( ui, { + foo: "bar", + baz: { + qux: 5, + quux: 20 + } + }, "ui hash passed" ); + ui.foo = "notbar"; + }); + $( "#widget-wrapper" ).bind( "testwidgetfoo", function( event, ui ) { + equal( event.originalEvent, originalEvent, "original event object passed" ); + deepEqual( ui, { + foo: "notbar", + baz: { + qux: 5, + quux: 20 + } + }, "modified ui hash passed" ); + ui.baz.qux = 10; + }); + $( "#widget" ).testWidget({ + foo: function( event, ui ) { + equal( event.originalEvent, originalEvent, "original event object passed" ); + deepEqual( ui, { + foo: "notbar", + baz: { + qux: 10, + quux: 20 + } + }, "modified ui hash passed" ); + ui.baz.quux = "jQuery"; + } + }) + .testWidget( "testEvent" ); +}); + +test( "._trigger() - array as ui", function() { + // #6795 - Widget: handle array arguments to _trigger consistently + expect( 4 ); + + $.widget( "ui.testWidget", { + _create: function() {}, + testEvent: function() { + var ui = { + foo: "bar", + baz: { + qux: 5, + quux: 20 + } + }, + extra = { + bar: 5 + }; + this._trigger( "foo", null, [ ui, extra ] ); + } + }); + $( "#widget" ).bind( "testwidgetfoo", function( event, ui, extra ) { + deepEqual( ui, { + foo: "bar", + baz: { + qux: 5, + quux: 20 + } + }, "event: ui hash passed" ); + deepEqual( extra, { + bar: 5 + }, "event: extra argument passed" ); + }); + $( "#widget" ).testWidget({ + foo: function( event, ui, extra ) { + deepEqual( ui, { + foo: "bar", + baz: { + qux: 5, + quux: 20 + } + }, "callback: ui hash passed" ); + deepEqual( extra, { + bar: 5 + }, "callback: extra argument passed" ); + } + }) + .testWidget( "testEvent" ); +}); + +test( "._trigger() - instance as element", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + defaultElement: null, + testEvent: function() { + this._trigger( "foo", null, { foo: "bar" } ); + } + }); + var instance = $.ui.testWidget({ + foo: function( event, ui ) { + equal( event.type, "testwidgetfoo", "event object passed to callback" ); + deepEqual( ui, { foo: "bar" }, "ui object passed to callback" ); + } + }); + $( instance ).bind( "testwidgetfoo", function( event, ui ) { + equal( event.type, "testwidgetfoo", "event object passed to event handler" ); + deepEqual( ui, { foo: "bar" }, "ui object passed to event handler" ); + }); + instance.testEvent(); +}); + +(function() { + function shouldDestroy( expected, callback ) { + expect( 1 ); + var destroyed = false; + $.widget( "ui.testWidget", { + _create: function() {}, + destroy: function() { + destroyed = true; + } + }); + callback(); + equal( destroyed, expected ); + } + + test( "auto-destroy - .remove()", function() { + shouldDestroy( true, function() { + $( "#widget" ).testWidget().remove(); + }); + }); + + test( "auto-destroy - .remove() when disabled", function() { + shouldDestroy( true, function() { + $( "#widget" ).testWidget({ disabled: true }).remove(); + }); + }); + + test( "auto-destroy - .remove() on parent", function() { + shouldDestroy( true, function() { + $( "#widget" ).testWidget().parent().remove(); + }); + }); + + test( "auto-destroy - .remove() on child", function() { + shouldDestroy( false, function() { + $( "#widget" ).testWidget().children().remove(); + }); + }); + + test( "auto-destroy - .empty()", function() { + shouldDestroy( false, function() { + $( "#widget" ).testWidget().empty(); + }); + }); + + test( "auto-destroy - .empty() on parent", function() { + shouldDestroy( true, function() { + $( "#widget" ).testWidget().parent().empty(); + }); + }); + + test( "auto-destroy - .detach()", function() { + shouldDestroy( false, function() { + $( "#widget" ).testWidget().detach(); + }); + }); + + test( "destroy - remove event bubbling", function() { + shouldDestroy( false, function() { + $( "<div>child</div>" ).appendTo( $( "#widget" ).testWidget() ) + .trigger( "remove" ); + }); + }); +}()); + +test( "redefine", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + method: function( str ) { + strictEqual( this, instance, "original invoked with correct this" ); + equal( str, "bar", "original invoked with correct parameter" ); + } + }); + $.ui.testWidget.foo = "bar"; + $.widget( "ui.testWidget", $.ui.testWidget, { + method: function( str ) { + equal( str, "foo", "new invoked with correct parameter" ); + this._super( "bar" ); + } + }); + + var instance = new $.ui.testWidget({}); + instance.method( "foo" ); + equal( $.ui.testWidget.foo, "bar", "static properties remain" ); +}); + +test( "redefine deep prototype chain", function() { + expect( 8 ); + $.widget( "ui.testWidget", { + method: function( str ) { + strictEqual( this, instance, "original invoked with correct this" ); + equal( str, "level 4", "original invoked with correct parameter" ); + } + }); + $.widget( "ui.testWidget2", $.ui.testWidget, { + method: function( str ) { + strictEqual( this, instance, "testWidget2 invoked with correct this" ); + equal( str, "level 2", "testWidget2 invoked with correct parameter" ); + this._super( "level 3" ); + } + }); + $.widget( "ui.testWidget3", $.ui.testWidget2, { + method: function( str ) { + strictEqual( this, instance, "testWidget3 invoked with correct this" ); + equal( str, "level 1", "testWidget3 invoked with correct parameter" ); + this._super( "level 2" ); + } + }); + // redefine testWidget after other widgets have inherited from it + // this tests whether the inheriting widgets get updated prototype chains + $.widget( "ui.testWidget", $.ui.testWidget, { + method: function( str ) { + strictEqual( this, instance, "new invoked with correct this" ); + equal( str, "level 3", "new invoked with correct parameter" ); + this._super( "level 4" ); + } + }); + // redefine testWidget3 after it has been automatically redefined + // this tests whether we properly handle _super() when the topmost prototype + // doesn't have the method defined + $.widget( "ui.testWidget3", $.ui.testWidget3, {} ); + + var instance = new $.ui.testWidget3({}); + instance.method( "level 1" ); + + delete $.ui.testWidget3; + delete $.ui.testWidget2; +}); + +test( "redefine - widgetEventPrefix", function() { + expect( 2 ); + + $.widget( "ui.testWidget", { + widgetEventPrefix: "test" + }); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "test", + "cusotm prefix in original" ); + + $.widget( "ui.testWidget", $.ui.testWidget, {} ); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "test", + "cusotm prefix in extension" ); + +}); + +test( "mixins", function() { + expect( 2 ); + + var mixin = { + method: function() { + return "mixed " + this._super(); + } + }; + + $.widget( "ui.testWidget1", { + method: function() { + return "testWidget1"; + } + }); + $.widget( "ui.testWidget2", { + method: function() { + return "testWidget2"; + } + }); + $.widget( "ui.testWidget1", $.ui.testWidget1, mixin ); + $.widget( "ui.testWidget2", $.ui.testWidget2, mixin ); + + equal( $( "<div>" ).testWidget1().testWidget1( "method" ), + "mixed testWidget1", "testWidget1 mixin successful" ); + equal( $( "<div>" ).testWidget2().testWidget2( "method" ), + "mixed testWidget2", "testWidget2 mixin successful" ); +}); + +asyncTest( "_delay", function() { + expect( 6 ); + var order = 0, + that; + $.widget( "ui.testWidget", { + defaultElement: null, + _create: function() { + that = this; + var timer = this._delay(function() { + strictEqual( this, that ); + equal( order, 1 ); + start(); + }, 500); + ok( timer !== undefined ); + timer = this._delay("callback"); + ok( timer !== undefined ); + }, + callback: function() { + strictEqual( this, that ); + equal( order, 0 ); + order += 1; + } + }); + $( "#widget" ).testWidget(); +}); + +test( "$.widget.bridge()", function() { + expect( 14 ); + + var instance, ret, + elem = $( "<div>" ); + + function TestWidget( options, element ) { + deepEqual( options, { foo: "bar" }, "options passed" ); + strictEqual( element, elem[ 0 ], "element passed" ); + } + + $.extend( TestWidget.prototype, { + method: function( param ) { + ok( true, "method called via .pluginName(methodName)" ); + equal( param, "value1", + "parameter passed via .pluginName(methodName, param)" ); + }, + getter: function() { + return "qux"; + }, + option: function( options ) { + deepEqual( options, {} ); + } + }); + + $.widget.bridge( "testWidget", TestWidget ); + + ok( $.isFunction( $.fn.testWidget ), "jQuery plugin was created" ); + + strictEqual( elem.testWidget({ foo: "bar" }), elem, "plugin returns original jQuery object" ); + instance = elem.data( "testWidget" ); + equal( typeof instance, "object", "instance stored in .data(pluginName)" ); + equal( typeof elem.testWidget( "instance" ), "object", "also retrievable via instance method" ); + + ret = elem.testWidget( "method", "value1" ); + equal( ret, elem, "jQuery object returned from method call" ); + + ret = elem.testWidget( "getter" ); + equal( ret, "qux", "getter returns value" ); + + elem.testWidget(); + ok( true, "_init is optional" ); + + TestWidget.prototype._init = function() { + ok( "_init", "_init now exists, so its called" ); + }; + elem.testWidget(); +}); + +test( "$.widget.bridge() - widgetFullName", function() { + expect( 1 ); + + var instance, + elem = $( "<div>" ); + + function TestWidget() {} + TestWidget.prototype.widgetFullName = "custom-widget"; + $.widget.bridge( "testWidget", TestWidget ); + + elem.testWidget(); + instance = elem.data( "custom-widget" ); + equal( typeof instance, "object", "instance stored in .data(widgetFullName)" ); +}); + +} ); |