X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;ds=sidebyside;f=test%2Funit%2Fcore.js;h=196700745adb4a6782de617ca123d1d1388400fc;hb=23d455b4469f2b47363c21867aad271d6930f112;hp=fe2e992a8aa7591b397fe44091840ba76fb96ca0;hpb=8d52c27808a77f51d1cf42c7e738b0b356466c1a;p=jquery.git
diff --git a/test/unit/core.js b/test/unit/core.js
index fe2e992..1967007 100644
--- a/test/unit/core.js
+++ b/test/unit/core.js
@@ -12,21 +12,26 @@ test("Basic requirements", function() {
});
test("jQuery()", function() {
- expect(11);
+ expect(24);
+
+ strictEqual( commonJSDefined, jQuery, "CommonJS registered (Bug #7102)" );
// Basic constructor's behavior
- equals( jQuery().length, 1, "jQuery() === jQuery(document)" );
+ equals( jQuery().length, 0, "jQuery() === jQuery([])" );
equals( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" );
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
+ var obj = jQuery("div")
+ equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );
+
// can actually yield more than one, when iframes are included, the window is an array as well
- equals( 1, jQuery(window).length, "Correct number of elements generated for jQuery(window)" );
+ equals( jQuery(window).length, 1, "Correct number of elements generated for jQuery(window)" );
var main = jQuery("#main");
- isSet( jQuery("div p", main).get(), q("sndp", "en", "sap"), "Basic selector with jQuery object as context" );
+ same( jQuery("div p", main).get(), q("sndp", "en", "sap"), "Basic selector with jQuery object as context" );
/*
// disabled since this test was doing nothing. i tried to fix it but i'm not sure
@@ -48,18 +53,43 @@ test("jQuery()", function() {
var code = jQuery("");
equals( code.length, 1, "Correct number of elements generated for code" );
+ equals( code.parent().length, 0, "Make sure that the generated HTML has no parent." );
var img = jQuery("
");
equals( img.length, 1, "Correct number of elements generated for img" );
+ equals( img.parent().length, 0, "Make sure that the generated HTML has no parent." );
var div = jQuery("
");
equals( div.length, 4, "Correct number of elements generated for div hr code b" );
+ equals( div.parent().length, 0, "Make sure that the generated HTML has no parent." );
equals( jQuery([1,2,3]).get(1), 2, "Test passing an array to the factory" );
equals( jQuery(document.body).get(0), jQuery('body').get(0), "Test passing an html node to the factory" );
+
+ var exec = false;
+
+ var elem = jQuery("", {
+ width: 10,
+ css: { paddingLeft:1, paddingRight:1 },
+ click: function(){ ok(exec, "Click executed."); },
+ text: "test",
+ "class": "test2",
+ id: "test3"
+ });
+
+ equals( elem[0].style.width, '10px', 'jQuery() quick setter width');
+ equals( elem[0].style.paddingLeft, '1px', 'jQuery quick setter css');
+ equals( elem[0].style.paddingRight, '1px', 'jQuery quick setter css');
+ equals( elem[0].childNodes.length, 1, 'jQuery quick setter text');
+ equals( elem[0].firstChild.nodeValue, "test", 'jQuery quick setter text');
+ equals( elem[0].className, "test2", 'jQuery() quick setter class');
+ equals( elem[0].id, "test3", 'jQuery() quick setter id');
+
+ exec = true;
+ elem.click();
});
test("selector state", function() {
- expect(30);
+ expect(31);
var test;
@@ -123,46 +153,39 @@ test("selector state", function() {
test = jQuery("#main").eq(0);
equals( test.selector, "#main.slice(0,1)", "#main eq Selector" );
equals( test.context, document, "#main eq Context" );
+
+ var d = "";
+ equals(
+ jQuery(d).appendTo(jQuery(d)).selector,
+ jQuery(d).appendTo(d).selector,
+ "manipulation methods make same selector for jQuery objects"
+ );
});
+if ( !isLocal ) {
test("browser", function() {
- expect(13);
- var browsers = {
- //Internet Explorer
- "Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)": "6.0",
- "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727)": "7.0",
- /** Failing #1876
- * "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30)": "7.0",
- */
- //Browsers with Gecko engine
- //Mozilla
- "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915" : "1.7.12",
- //Firefox
- "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3": "1.8.1.3",
- //Netscape
- "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3" : "1.7.5",
- //Flock
- "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070321 Firefox/1.5.0.11 Flock/0.7.12" : "1.8.0.11",
- //Opera browser
- "Opera/9.20 (X11; Linux x86_64; U; en)": "9.20",
- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.20" : "9.20",
- "Mozilla/5.0 (Windows NT 5.1; U; pl; rv:1.8.0) Gecko/20060728 Firefox/1.5.0 Opera 9.20": "9.20",
- //WebKit engine
- "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/418.9 (KHTML, like Gecko) Safari/419.3": "418.9",
- "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3" : "418.8",
- "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/312.8 (KHTML, like Gecko) Safari/312.5": "312.8",
- //Other user agent string
- "Other browser's user agent 1.0":null
- };
- for (var i in browsers) {
- var v = i.toLowerCase().match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ); // RegEx from Core jQuery.browser.version check
- var version = v ? v[1] : null;
- equals( version, browsers[i], "Checking UA string" );
- }
+ stop();
+
+ jQuery.get("data/ua.txt", function(data){
+ var uas = data.split("\n");
+ expect( (uas.length - 1) * 2 );
+
+ jQuery.each(uas, function(){
+ var parts = this.split("\t");
+ if ( parts[2] ) {
+ var ua = jQuery.uaMatch( parts[2] );
+ equals( ua.browser, parts[0], "Checking browser for " + parts[2] );
+ equals( ua.version, parts[1], "Checking version string for " + parts[2] );
+ }
+ });
+
+ start();
+ });
});
+}
test("noConflict", function() {
- expect(6);
+ expect(7);
var $$ = jQuery;
@@ -175,10 +198,121 @@ test("noConflict", function() {
equals( jQuery.noConflict(true), $$, "noConflict returned the jQuery object" );
equals( jQuery, originaljQuery, "Make sure jQuery was reverted." );
equals( $, original$, "Make sure $ was reverted." );
+ ok( $$("#main").html("test"), "Make sure that jQuery still works." );
jQuery = $$;
});
+test("trim", function() {
+ expect(9);
+
+ var nbsp = String.fromCharCode(160);
+
+ equals( jQuery.trim("hello "), "hello", "trailing space" );
+ equals( jQuery.trim(" hello"), "hello", "leading space" );
+ equals( jQuery.trim(" hello "), "hello", "space on both sides" );
+ equals( jQuery.trim(" " + nbsp + "hello " + nbsp + " "), "hello", " " );
+
+ equals( jQuery.trim(), "", "Nothing in." );
+ equals( jQuery.trim( undefined ), "", "Undefined" );
+ equals( jQuery.trim( null ), "", "Null" );
+ equals( jQuery.trim( 5 ), "5", "Number" );
+ equals( jQuery.trim( false ), "false", "Boolean" );
+});
+
+test("type", function() {
+ expect(23);
+
+ equals( jQuery.type(null), "null", "null" );
+ equals( jQuery.type(undefined), "undefined", "undefined" );
+ equals( jQuery.type(true), "boolean", "Boolean" );
+ equals( jQuery.type(false), "boolean", "Boolean" );
+ equals( jQuery.type(Boolean(true)), "boolean", "Boolean" );
+ equals( jQuery.type(0), "number", "Number" );
+ equals( jQuery.type(1), "number", "Number" );
+ equals( jQuery.type(Number(1)), "number", "Number" );
+ equals( jQuery.type(""), "string", "String" );
+ equals( jQuery.type("a"), "string", "String" );
+ equals( jQuery.type(String("a")), "string", "String" );
+ equals( jQuery.type({}), "object", "Object" );
+ equals( jQuery.type(/foo/), "regexp", "RegExp" );
+ equals( jQuery.type(new RegExp("asdf")), "regexp", "RegExp" );
+ equals( jQuery.type([1]), "array", "Array" );
+ equals( jQuery.type(new Date()), "date", "Date" );
+ equals( jQuery.type(new Function("return;")), "function", "Function" );
+ equals( jQuery.type(function(){}), "function", "Function" );
+ equals( jQuery.type(window), "object", "Window" );
+ equals( jQuery.type(document), "object", "Document" );
+ equals( jQuery.type(document.body), "object", "Element" );
+ equals( jQuery.type(document.createTextNode("foo")), "object", "TextNode" );
+ equals( jQuery.type(document.getElementsByTagName("*")), "object", "NodeList" );
+});
+
+test("isPlainObject", function() {
+ expect(14);
+
+ stop();
+
+ // The use case that we want to match
+ ok(jQuery.isPlainObject({}), "{}");
+
+ // Not objects shouldn't be matched
+ ok(!jQuery.isPlainObject(""), "string");
+ ok(!jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number");
+ ok(!jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean");
+ ok(!jQuery.isPlainObject(null), "null");
+ ok(!jQuery.isPlainObject(undefined), "undefined");
+
+ // Arrays shouldn't be matched
+ ok(!jQuery.isPlainObject([]), "array");
+
+ // Instantiated objects shouldn't be matched
+ ok(!jQuery.isPlainObject(new Date), "new Date");
+
+ var fn = function(){};
+
+ // Functions shouldn't be matched
+ ok(!jQuery.isPlainObject(fn), "fn");
+
+ // Again, instantiated objects shouldn't be matched
+ ok(!jQuery.isPlainObject(new fn), "new fn (no methods)");
+
+ // Makes the function a little more realistic
+ // (and harder to detect, incidentally)
+ fn.prototype = {someMethod: function(){}};
+
+ // Again, instantiated objects shouldn't be matched
+ ok(!jQuery.isPlainObject(new fn), "new fn");
+
+ // DOM Element
+ ok(!jQuery.isPlainObject(document.createElement("div")), "DOM Element");
+
+ // Window
+ ok(!jQuery.isPlainObject(window), "window");
+
+ try {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+
+ window.iframeDone = function(otherObject){
+ // Objects from other windows should be matched
+ ok(jQuery.isPlainObject(new otherObject), "new otherObject");
+ document.body.removeChild( iframe );
+ start();
+ };
+
+ var doc = iframe.contentDocument || iframe.contentWindow.document;
+ doc.open();
+ doc.write("");
+ doc.close();
+ } catch(e) {
+ document.body.removeChild( iframe );
+
+ ok(true, "new otherObject - iframes not supported");
+ start();
+ }
+});
+
test("isFunction", function() {
expect(19);
@@ -266,10 +400,68 @@ test("isFunction", function() {
});
});
+test("isXMLDoc - HTML", function() {
+ expect(4);
+
+ ok( !jQuery.isXMLDoc( document ), "HTML document" );
+ ok( !jQuery.isXMLDoc( document.documentElement ), "HTML documentElement" );
+ ok( !jQuery.isXMLDoc( document.body ), "HTML Body Element" );
+
+ var iframe = document.createElement("iframe");
+ document.body.appendChild( iframe );
+
+ try {
+ var body = jQuery(iframe).contents()[0];
+
+ try {
+ ok( !jQuery.isXMLDoc( body ), "Iframe body element" );
+ } catch(e) {
+ ok( false, "Iframe body element exception" );
+ }
+
+ } catch(e) {
+ ok( true, "Iframe body element - iframe not working correctly" );
+ }
+
+ document.body.removeChild( iframe );
+});
+
+if ( !isLocal ) {
+test("isXMLDoc - XML", function() {
+ expect(3);
+ stop();
+ jQuery.get('data/dashboard.xml', function(xml) {
+ ok( jQuery.isXMLDoc( xml ), "XML document" );
+ ok( jQuery.isXMLDoc( xml.documentElement ), "XML documentElement" );
+ ok( jQuery.isXMLDoc( jQuery("tab", xml)[0] ), "XML Tab Element" );
+ start();
+ });
+});
+}
+
+test("isWindow", function() {
+ expect( 12 );
+
+ ok( jQuery.isWindow(window), "window" );
+ ok( !jQuery.isWindow(), "empty" );
+ ok( !jQuery.isWindow(null), "null" );
+ ok( !jQuery.isWindow(undefined), "undefined" );
+ ok( !jQuery.isWindow(document), "document" );
+ ok( !jQuery.isWindow(document.documentElement), "documentElement" );
+ ok( !jQuery.isWindow(""), "string" );
+ ok( !jQuery.isWindow(1), "number" );
+ ok( !jQuery.isWindow(true), "boolean" );
+ ok( !jQuery.isWindow({}), "object" );
+ // HMMM
+ // ok( !jQuery.isWindow({ setInterval: function(){} }), "fake window" );
+ ok( !jQuery.isWindow(/window/), "regexp" );
+ ok( !jQuery.isWindow(function(){}), "function" );
+});
+
test("jQuery('html')", function() {
- expect(8);
+ expect(15);
- reset();
+ QUnit.reset();
jQuery.foo = false;
var s = jQuery("")[0];
ok( s, "Creating a script" );
@@ -277,7 +469,15 @@ test("jQuery('html')", function() {
jQuery("body").append("");
ok( jQuery.foo, "Executing a scripts contents in the right context" );
- reset();
+ // Test multi-line HTML
+ var div = jQuery("some p
\nmore text\r\nxxx
")).add(jQuery("xxx
")); - equals( x[0].id, "x1", "Check on-the-fly element1" ); - equals( x[1].id, "x2", "Check on-the-fly element2" ); - - var x = jQuery([]).add("xxx
").add("xxx
"); - equals( x[0].id, "x1", "Check on-the-fly element1" ); - equals( x[1].id, "x2", "Check on-the-fly element2" ); - - var notDefined; - equals( jQuery([]).add(notDefined).length, 0, "Check that undefined adds nothing" ); - - // Added after #2811 - equals( jQuery([]).add([window,document,document.body,document]).length, 3, "Pass an array" ); - equals( jQuery(document).add(document).length, 1, "Check duplicated elements" ); - equals( jQuery(window).add(window).length, 1, "Check duplicated elements using the window" ); - ok( jQuery([]).add( document.getElementById('form') ).length >= 13, "Add a form (adds the elements)" ); -}); - test("each(Function)", function() { expect(1); var div = jQuery("div"); @@ -386,39 +571,83 @@ test("each(Function)", function() { ok( pass, "Execute a function, Relative" ); }); -test("index(Object|String|undefined)", function() { - expect(16); +test("slice()", function() { + expect(7); + + var $links = jQuery("#ap a"); - var elements = jQuery([window, document]), - inputElements = jQuery('#radio1,#radio2,#check1,#check2'); + same( $links.slice(1,2).get(), q("groups"), "slice(1,2)" ); + same( $links.slice(1).get(), q("groups", "anchor1", "mark"), "slice(1)" ); + same( $links.slice(0,3).get(), q("google", "groups", "anchor1"), "slice(0,3)" ); + same( $links.slice(-1).get(), q("mark"), "slice(-1)" ); - // Passing a node - equals( elements.index(window), 0, "Check for index of elements" ); - equals( elements.index(document), 1, "Check for index of elements" ); - equals( inputElements.index(document.getElementById('radio1')), 0, "Check for index of elements" ); - equals( inputElements.index(document.getElementById('radio2')), 1, "Check for index of elements" ); - equals( inputElements.index(document.getElementById('check1')), 2, "Check for index of elements" ); - equals( inputElements.index(document.getElementById('check2')), 3, "Check for index of elements" ); - equals( inputElements.index(window), -1, "Check for not found index" ); - equals( inputElements.index(document), -1, "Check for not found index" ); + same( $links.eq(1).get(), q("groups"), "eq(1)" ); + same( $links.eq('2').get(), q("anchor1"), "eq('2')" ); + same( $links.eq(-1).get(), q("mark"), "eq(-1)" ); +}); + +test("first()/last()", function() { + expect(4); + + var $links = jQuery("#ap a"), $none = jQuery("asdf"); - // Passing a jQuery object - // enabled since [5500] - equals( elements.index( elements ), 0, "Pass in a jQuery object" ); - equals( elements.index( elements.eq(1) ), 1, "Pass in a jQuery object" ); - equals( jQuery("#form :radio").index( jQuery("#radio2") ), 1, "Pass in a jQuery object" ); + same( $links.first().get(), q("google"), "first()" ); + same( $links.last().get(), q("mark"), "last()" ); - // Passing a selector or nothing - // enabled since [6330] - equals( jQuery('#text2').index(), 2, "Check for index amongst siblings" ); - equals( jQuery('#form').children().eq(4).index(), 4, "Check for index amongst siblings" ); - equals( jQuery('#radio2').index('#form :radio') , 1, "Check for index within a selector" ); - equals( jQuery('#form :radio').index( jQuery('#radio2') ), 1, "Check for index within a selector" ); - equals( jQuery('#radio2').index('#form :text') , -1, "Check for index not found within a selector" ); + same( $none.first().get(), [], "first() none" ); + same( $none.last().get(), [], "last() none" ); +}); + +test("map()", function() { + expect(2);//expect(6); + + same( + jQuery("#ap").map(function(){ + return jQuery(this).find("a").get(); + }).get(), + q("google", "groups", "anchor1", "mark"), + "Array Map" + ); + + same( + jQuery("#ap > a").map(function(){ + return this.parentNode; + }).get(), + q("ap","ap","ap"), + "Single Map" + ); + + return;//these haven't been accepted yet + + //for #2616 + var keys = jQuery.map( {a:1,b:2}, function( v, k ){ + return k; + }, [ ] ); + + equals( keys.join(""), "ab", "Map the keys from a hash to an array" ); + + var values = jQuery.map( {a:1,b:2}, function( v, k ){ + return v; + }, [ ] ); + + equals( values.join(""), "12", "Map the values from a hash to an array" ); + + var scripts = document.getElementsByTagName("script"); + var mapped = jQuery.map( scripts, function( v, k ){ + return v; + }, {length:0} ); + + equals( mapped.length, scripts.length, "Map an array(-like) to a hash" ); + + var flat = jQuery.map( Array(4), function( v, k ){ + return k % 2 ? k : [k,k,k];//try mixing array and regular returns + }); + + equals( flat.join(""), "00012223", "try the new flatten technique(#2616)" ); }); test("jQuery.merge()", function() { - expect(6); + expect(8); var parse = jQuery.merge; @@ -432,10 +661,14 @@ test("jQuery.merge()", function() { // Fixed at [5998], #3641 same( parse([-2,-1], [0,1,2]), [-2,-1,0,1,2], "Second array including a zero (falsy)"); + + // After fixing #5527 + same( parse([], [null, undefined]), [null, undefined], "Second array including null and undefined values"); + same( parse({length:0}, [1,2]), {length:2, 0:1, 1:2}, "First array like"); }); test("jQuery.extend(Object, Object)", function() { - expect(21); + expect(28); var settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" }, options = { xnumber2: 1, xstring2: "x", xxx: "newstring" }, @@ -445,26 +678,54 @@ test("jQuery.extend(Object, Object)", function() { deep1copy = { foo: { bar: true } }, deep2 = { foo: { baz: true }, foo2: document }, deep2copy = { foo: { baz: true }, foo2: document }, - deepmerged = { foo: { bar: true, baz: true }, foo2: document }; + deepmerged = { foo: { bar: true, baz: true }, foo2: document }, + arr = [1, 2, 3], + nestedarray = { arr: arr }; jQuery.extend(settings, options); - isObj( settings, merged, "Check if extended: settings must be extended" ); - isObj( options, optionsCopy, "Check if not modified: options must not be modified" ); + same( settings, merged, "Check if extended: settings must be extended" ); + same( options, optionsCopy, "Check if not modified: options must not be modified" ); jQuery.extend(settings, null, options); - isObj( settings, merged, "Check if extended: settings must be extended" ); - isObj( options, optionsCopy, "Check if not modified: options must not be modified" ); + same( settings, merged, "Check if extended: settings must be extended" ); + same( options, optionsCopy, "Check if not modified: options must not be modified" ); jQuery.extend(true, deep1, deep2); - isObj( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" ); - isObj( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" ); + same( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" ); + same( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" ); equals( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" ); + ok( jQuery.extend(true, {}, nestedarray).arr !== arr, "Deep extend of object must clone child array" ); + + // #5991 + ok( jQuery.isArray( jQuery.extend(true, { arr: {} }, nestedarray).arr ), "Cloned array heve to be an Array" ); + ok( jQuery.isPlainObject( jQuery.extend(true, { arr: arr }, { arr: {} }).arr ), "Cloned object heve to be an plain object" ); + var empty = {}; var optionsWithLength = { foo: { length: -1 } }; jQuery.extend(true, empty, optionsWithLength); + same( empty.foo, optionsWithLength.foo, "The length property must copy correctly" ); + + empty = {}; + var optionsWithDate = { foo: { date: new Date } }; + jQuery.extend(true, empty, optionsWithDate); + same( empty.foo, optionsWithDate.foo, "Dates copy correctly" ); + + var myKlass = function() {}; + var customObject = new myKlass(); + var optionsWithCustomObject = { foo: { date: customObject } }; + empty = {}; + jQuery.extend(true, empty, optionsWithCustomObject); + ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" ); - isObj( empty.foo, optionsWithLength.foo, "The length property must copy correctly" ); + // Makes the class a little more realistic + myKlass.prototype = { someMethod: function(){} }; + empty = {}; + jQuery.extend(true, empty, optionsWithCustomObject); + ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" ); + + var ret = jQuery.extend(true, { foo: 4 }, { foo: new Number(5) } ); + ok( ret.foo == 5, "Wrapped numbers copy correctly" ); var nullUndef; nullUndef = jQuery.extend({}, options, { xnumber2: null }); @@ -479,7 +740,7 @@ test("jQuery.extend(Object, Object)", function() { var target = {}; var recursive = { foo:target, bar:5 }; jQuery.extend(true, target, recursive); - isObj( target, { bar:5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" ); + same( target, { bar:5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" ); var ret = jQuery.extend(true, { foo: [] }, { foo: [0] } ); // 1907 equals( ret.foo.length, 1, "Check to make sure a value with coersion 'false' copies over when necessary to fix #1907" ); @@ -507,10 +768,10 @@ test("jQuery.extend(Object, Object)", function() { merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" }; var settings = jQuery.extend({}, defaults, options1, options2); - isObj( settings, merged2, "Check if extended: settings must be extended" ); - isObj( defaults, defaultsCopy, "Check if not modified: options1 must not be modified" ); - isObj( options1, options1Copy, "Check if not modified: options1 must not be modified" ); - isObj( options2, options2Copy, "Check if not modified: options2 must not be modified" ); + same( settings, merged2, "Check if extended: settings must be extended" ); + same( defaults, defaultsCopy, "Check if not modified: options1 must not be modified" ); + same( options1, options1Copy, "Check if not modified: options1 must not be modified" ); + same( options2, options2Copy, "Check if not modified: options2 must not be modified" ); }); test("jQuery.each(Object,Function)", function() { @@ -549,7 +810,7 @@ test("jQuery.each(Object,Function)", function() { }); test("jQuery.makeArray", function(){ - expect(15); + expect(17); equals( jQuery.makeArray(jQuery('html>*'))[0].nodeName.toUpperCase(), "HEAD", "Pass makeArray a jQuery object" ); @@ -582,4 +843,247 @@ test("jQuery.makeArray", function(){ equals( jQuery.makeArray(/a/)[0].constructor, RegExp, "Pass makeArray a regex" ); ok( jQuery.makeArray(document.getElementById('form')).length >= 13, "Pass makeArray a form (treat as elements)" ); + + // For #5610 + same( jQuery.makeArray({'length': '0'}), [], "Make sure object is coerced properly."); + same( jQuery.makeArray({'length': '5'}), [], "Make sure object is coerced properly."); +}); + +test("jQuery.isEmptyObject", function(){ + expect(2); + + equals(true, jQuery.isEmptyObject({}), "isEmptyObject on empty object literal" ); + equals(false, jQuery.isEmptyObject({a:1}), "isEmptyObject on non-empty object literal" ); + + // What about this ? + // equals(true, jQuery.isEmptyObject(null), "isEmptyObject on null" ); +}); + +test("jQuery.proxy", function(){ + expect(4); + + var test = function(){ equals( this, thisObject, "Make sure that scope is set properly." ); }; + var thisObject = { foo: "bar", method: test }; + + // Make sure normal works + test.call( thisObject ); + + // Basic scoping + jQuery.proxy( test, thisObject )(); + + // Make sure it doesn't freak out + equals( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." ); + + // Use the string shortcut + jQuery.proxy( thisObject, "method" )(); +}); + +test("jQuery.parseJSON", function(){ + expect(8); + + equals( jQuery.parseJSON(), null, "Nothing in, null out." ); + equals( jQuery.parseJSON( null ), null, "Nothing in, null out." ); + equals( jQuery.parseJSON( "" ), null, "Nothing in, null out." ); + + same( jQuery.parseJSON("{}"), {}, "Plain object parsing." ); + same( jQuery.parseJSON('{"test":1}'), {"test":1}, "Plain object parsing." ); + + same( jQuery.parseJSON('\n{"test":1}'), {"test":1}, "Make sure leading whitespaces are handled." ); + + try { + jQuery.parseJSON("{a:1}"); + ok( false, "Test malformed JSON string." ); + } catch( e ) { + ok( true, "Test malformed JSON string." ); + } + + try { + jQuery.parseJSON("{'a':1}"); + ok( false, "Test malformed JSON string." ); + } catch( e ) { + ok( true, "Test malformed JSON string." ); + } +}); + +test("jQuery._Deferred()", function() { + + expect( 10 ); + + var deferred, + object, + test; + + deferred = jQuery._Deferred(); + + test = false; + + deferred.then( function( value ) { + equals( value , "value" , "Test pre-resolve callback" ); + test = true; + } ); + + deferred.resolve( "value" ); + + ok( test , "Test pre-resolve callbacks called right away" ); + + test = false; + + deferred.then( function( value ) { + equals( value , "value" , "Test post-resolve callback" ); + test = true; + } ); + + ok( test , "Test post-resolve callbacks called right away" ); + + deferred.cancel(); + + test = true; + + deferred.then( function() { + ok( false , "Cancel was ignored" ); + test = false; + } ); + + ok( test , "Test cancel" ); + + deferred = jQuery._Deferred().resolve(); + + try { + deferred.then( function() { + throw "Error"; + } , function() { + ok( true , "Test deferred do not cancel on exception" ); + } ); + } catch( e ) { + strictEqual( e , "Error" , "Test deferred propagates exceptions"); + deferred.then(); + } + + test = ""; + deferred = jQuery._Deferred().then( function() { + + test += "A"; + + }, function() { + + test += "B"; + + } ).resolve(); + + strictEqual( test , "AB" , "Test multiple then parameters" ); + + test = ""; + + deferred.then( function() { + + deferred.then( function() { + + test += "C"; + + } ); + + test += "A"; + + }, function() { + + test += "B"; + } ); + + strictEqual( test , "ABC" , "Test then callbacks order" ); + + deferred = jQuery._Deferred(); + + deferred.fire( jQuery , [ document ] ).then( function( doc ) { + ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); + }); +}); + +test("jQuery.Deferred()", function() { + + expect( 4 ); + + jQuery.Deferred( function( defer ) { + strictEqual( this , defer , "Defer passed as this & first argument" ); + this.resolve( "done" ); + }).then( function( value ) { + strictEqual( value , "done" , "Passed function executed" ); + }); + + jQuery.Deferred().resolve().then( function() { + ok( true , "Success on resolve" ); + }).fail( function() { + ok( false , "Error on resolve" ); + }); + + jQuery.Deferred().reject().then( function() { + ok( false , "Success on reject" ); + }).fail( function() { + ok( true , "Error on reject" ); + }); +}); + +test("jQuery.isDeferred()", function() { + + expect( 11 ); + + var object1 = { then: function() { return this; } }, + object2 = { then: function() { return this; } }; + + object2.then._ = []; + + // The use case that we want to match + ok(jQuery.isDeferred(jQuery._Deferred()), "Simple deferred"); + ok(jQuery.isDeferred(jQuery.Deferred()), "Failable deferred"); + + // Some other objects + ok(!jQuery.isDeferred(object1), "Object with then & no marker"); + ok(!jQuery.isDeferred(object2), "Object with then & marker"); + + // Not objects shouldn't be matched + ok(!jQuery.isDeferred(""), "string"); + ok(!jQuery.isDeferred(0) && !jQuery.isDeferred(1), "number"); + ok(!jQuery.isDeferred(true) && !jQuery.isDeferred(false), "boolean"); + ok(!jQuery.isDeferred(null), "null"); + ok(!jQuery.isDeferred(undefined), "undefined"); + + object1 = {custom: jQuery._Deferred().then}; + + ok(!jQuery.isDeferred(object1) , "custom method name not found automagically"); + ok(jQuery.isDeferred(object1,"custom") , "custom method name"); +}); + +test("jQuery.when()", function() { + + expect( 5 ); + + var cache, i, deferred = { done: jQuery.Deferred().resolve( 1 ).then }; + + for( i = 1 ; i < 3 ; i++ ) { + jQuery.when( cache || jQuery.Deferred( function() { + this.resolve( i ); + }) ).then( function( value ) { + strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) ); + cache = value; + }).fail( function() { + ok( false , "Fail called" ); + }); + } + + cache = 0; + + for( i = 1 ; i < 3 ; i++ ) { + jQuery.when( cache || deferred , "done" ).done( function( value ) { + strictEqual( value , 1 , "Custom method: resolved" + ( i > 1 ? " only once" : "" ) ); + cache = value; + }).fail( function() { + ok( false , "Custom method: fail called" ); + }); + } + + stop(); + + jQuery.when( jQuery( document ) , "ready" ).then( function( test ) { + strictEqual( test , jQuery , "jQuery.fn.ready recognized as a deferred" ); + start(); + }); });