rob@77: var testCase = require('nodeunit').testCase, rob@77: jsdom = require('jsdom').jsdom, rob@77: static_document = require('fs').readFileSync('test/fixtures/core.html', 'utf8'); rob@77: rob@77: // need to be global as helpers access these variables rob@77: window = document = jQuery = $ = null; rob@77: rob@77: var helpers = require('./helpers/helper'), rob@77: q = helpers.query_ids; rob@77: rob@77: module.exports = testCase({ rob@77: setUp: function (callback) { rob@77: jQuery = $ = helpers.recreate_doc(static_document); rob@77: callback(); rob@77: }, rob@77: tearDown: function (callback) { rob@77: // clean up rob@77: callback(); rob@77: }, rob@77: "Basic requirements": function(test) { rob@77: test.expect(7); rob@77: test.ok( Array.prototype.push, "Array.push()" ); rob@77: test.ok( Function.prototype.apply, "Function.apply()" ); rob@77: test.ok( document.getElementById, "getElementById" ); rob@77: test.ok( document.getElementsByTagName, "getElementsByTagName" ); rob@77: test.ok( RegExp, "RegExp" ); rob@77: test.ok( jQuery, "jQuery" ); rob@77: test.ok( $, "$" ); rob@77: test.done(); rob@77: }, rob@77: "jQuery()": function(test) { rob@77: test.expect(24); rob@77: // Basic constructor's behavior rob@77: rob@77: test.equals( jQuery().length, 0, "jQuery() === jQuery([])" ); rob@77: test.equals( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" ); rob@77: test.equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" ); rob@77: test.equals( jQuery("").length, 0, "jQuery('') === jQuery([])" ); rob@77: rob@77: var obj = jQuery("div"); rob@77: test.equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" ); rob@77: rob@77: // can actually yield more than one, when iframes are included, the window is an array as well rob@77: test.equals( jQuery(window).length, 1, "Correct number of elements generated for jQuery(window)" ); rob@77: rob@77: rob@77: var main = jQuery("#main"); rob@77: test.same( jQuery("div p", main).get(), q("sndp", "en", "sap"), "Basic selector with jQuery object as context" ); rob@77: rob@77: /* rob@77: // disabled since this test was doing nothing. i tried to fix it but i'm not sure rob@77: // what the expected behavior should even be. FF returns "\n" for the text node rob@77: // make sure this is handled rob@77: var crlfContainer = jQuery('

\r\n

'); rob@77: var x = crlfContainer.contents().get(0).nodeValue; rob@77: equals( x, what???, "Check for \\r and \\n in jQuery()" ); rob@77: */ rob@77: rob@77: /* // Disabled until we add this functionality in rob@77: var pass = true; rob@77: try { rob@77: jQuery("
Testing
").appendTo(document.getElementById("iframe").contentDocument.body); rob@77: } catch(e){ rob@77: pass = false; rob@77: } rob@77: ok( pass, "jQuery('<tag>') needs optional document parameter to ease cross-frame DOM wrangling, see #968" );*/ rob@77: rob@77: var code = jQuery(""); rob@77: test.equals( code.length, 1, "Correct number of elements generated for code" ); rob@77: test.equals( code.parent().length, 0, "Make sure that the generated HTML has no parent." ); rob@77: var img = jQuery(""); rob@77: test.equals( img.length, 1, "Correct number of elements generated for img" ); rob@77: test.equals( img.parent().length, 0, "Make sure that the generated HTML has no parent." ); rob@77: var div = jQuery("

"); rob@77: test.equals( div.length, 4, "Correct number of elements generated for div hr code b" ); rob@77: test.equals( div.parent().length, 0, "Make sure that the generated HTML has no parent." ); rob@77: rob@77: test.equals( jQuery([1,2,3]).get(1), 2, "Test passing an array to the factory" ); rob@77: rob@77: test.equals( jQuery(document.body).get(0), jQuery('body').get(0), "Test passing an html node to the factory" ); rob@77: rob@77: var exec = false; rob@77: rob@77: var elem = jQuery("
", { rob@77: width: 10, rob@77: css: { paddingLeft:1, paddingRight:1 }, rob@77: click: function(){ test.ok(exec, "Click executed."); }, rob@77: text: "test", rob@77: "class": "test2", rob@77: id: "test3" rob@77: }); rob@77: rob@77: test.equals( elem[0].style.width, '10px', 'jQuery() quick setter width'); rob@77: test.equals( elem[0].style.paddingLeft, '1px', 'jQuery quick setter css'); rob@77: test.equals( elem[0].style.paddingRight, '1px', 'jQuery quick setter css'); rob@77: test.equals( elem[0].childNodes.length, 1, 'jQuery quick setter text'); rob@77: test.equals( elem[0].firstChild.nodeValue, "test", 'jQuery quick setter text'); rob@77: test.equals( elem[0].className, "test2", 'jQuery() quick setter class'); rob@77: test.equals( elem[0].id, "test3", 'jQuery() quick setter id'); rob@77: rob@77: exec = true; rob@77: elem.click(); rob@77: rob@77: // manually clean up detached elements rob@77: elem.remove(); rob@77: rob@77: for ( var i = 0; i < 3; ++i ) { rob@77: elem = jQuery(""); rob@77: } rob@77: test.equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); rob@77: rob@77: // manually clean up detached elements rob@77: elem.remove(); rob@77: test.done(); rob@77: }, rob@77: "selector state": function(test) { rob@77: test.expect(31); rob@77: rob@77: var elem; rob@77: rob@77: elem = jQuery(undefined); rob@77: test.equals( elem.selector, "", "Empty jQuery Selector" ); rob@77: test.equals( elem.context, undefined, "Empty jQuery Context" ); rob@77: rob@77: elem = jQuery(document); rob@77: test.equals( elem.selector, "", "Document Selector" ); rob@77: test.equals( elem.context, document, "Document Context" ); rob@77: rob@77: elem = jQuery(document.body); rob@77: test.equals( elem.selector, "", "Body Selector" ); rob@77: test.equals( elem.context, document.body, "Body Context" ); rob@77: rob@77: elem = jQuery("#main"); rob@77: test.equals( elem.selector, "#main", "#main Selector" ); rob@77: test.equals( elem.context, document, "#main Context" ); rob@77: rob@77: elem = jQuery("#notfoundnono"); rob@77: test.equals( elem.selector, "#notfoundnono", "#notfoundnono Selector" ); rob@77: test.equals( elem.context, document, "#notfoundnono Context" ); rob@77: rob@77: elem = jQuery("#main", document); rob@77: test.equals( elem.selector, "#main", "#main Selector" ); rob@77: test.equals( elem.context, document, "#main Context" ); rob@77: rob@77: elem = jQuery("#main", document.body); rob@77: test.equals( elem.selector, "#main", "#main Selector" ); rob@77: test.equals( elem.context, document.body, "#main Context" ); rob@77: rob@77: // Test cloning rob@77: elem = jQuery(elem); rob@77: test.equals( elem.selector, "#main", "#main Selector" ); rob@77: test.equals( elem.context, document.body, "#main Context" ); rob@77: rob@77: elem = jQuery(document.body).find("#main"); rob@77: test.equals( elem.selector, "#main", "#main find Selector" ); rob@77: test.equals( elem.context, document.body, "#main find Context" ); rob@77: rob@77: elem = jQuery("#main").filter("div"); rob@77: test.equals( elem.selector, "#main.filter(div)", "#main filter Selector" ); rob@77: test.equals( elem.context, document, "#main filter Context" ); rob@77: rob@77: elem = jQuery("#main").not("div"); rob@77: test.equals( elem.selector, "#main.not(div)", "#main not Selector" ); rob@77: test.equals( elem.context, document, "#main not Context" ); rob@77: rob@77: elem = jQuery("#main").filter("div").not("div"); rob@77: test.equals( elem.selector, "#main.filter(div).not(div)", "#main filter, not Selector" ); rob@77: test.equals( elem.context, document, "#main filter, not Context" ); rob@77: rob@77: elem = jQuery("#main").filter("div").not("div").end(); rob@77: test.equals( elem.selector, "#main.filter(div)", "#main filter, not, end Selector" ); rob@77: test.equals( elem.context, document, "#main filter, not, end Context" ); rob@77: rob@77: elem = jQuery("#main").parent("body"); rob@77: test.equals( elem.selector, "#main.parent(body)", "#main parent Selector" ); rob@77: test.equals( elem.context, document, "#main parent Context" ); rob@77: rob@77: elem = jQuery("#main").eq(0); rob@77: test.equals( elem.selector, "#main.slice(0,1)", "#main eq Selector" ); rob@77: test.equals( elem.context, document, "#main eq Context" ); rob@77: rob@77: var d = "
"; rob@77: test.equals( rob@77: jQuery(d).appendTo(jQuery(d)).selector, rob@77: jQuery(d).appendTo(d).selector, rob@77: "manipulation methods make same selector for jQuery objects" rob@77: ); rob@77: test.done(); rob@77: }, rob@77: "noConflict": function(test) { rob@77: test.expect(7); rob@77: rob@77: var originaljQuery = jQuery, rob@77: original$ = $, rob@77: $$ = jQuery; rob@77: rob@77: test.equals( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" ); rob@77: test.equals( jQuery, $$, "Make sure jQuery wasn't touched." ); rob@77: test.equals( $, original$, "Make sure $ was reverted." ); rob@77: rob@77: jQuery = $ = $$; rob@77: rob@77: test.equals( jQuery.noConflict(true), $$, "noConflict returned the jQuery object" ); rob@77: test.equals( jQuery, originaljQuery, "Make sure jQuery was reverted." ); rob@77: test.equals( $, original$, "Make sure $ was reverted." ); rob@77: test.ok( $$("#main").html("test"), "Make sure that jQuery still works." ); rob@77: rob@77: jQuery = $$; rob@77: test.done(); rob@77: }, rob@77: rob@77: "trim": function(test) { rob@77: test.expect(9); rob@77: rob@77: var nbsp = String.fromCharCode(160); rob@77: rob@77: test.equals( jQuery.trim("hello "), "hello", "trailing space" ); rob@77: test.equals( jQuery.trim(" hello"), "hello", "leading space" ); rob@77: test.equals( jQuery.trim(" hello "), "hello", "space on both sides" ); rob@77: test.equals( jQuery.trim(" " + nbsp + "hello " + nbsp + " "), "hello", " " ); rob@77: rob@77: test.equals( jQuery.trim(), "", "Nothing in." ); rob@77: test.equals( jQuery.trim( undefined ), "", "Undefined" ); rob@77: test.equals( jQuery.trim( null ), "", "Null" ); rob@77: test.equals( jQuery.trim( 5 ), "5", "Number" ); rob@77: test.equals( jQuery.trim( false ), "false", "Boolean" ); rob@77: test.done(); rob@77: }, rob@77: "type": function(test) { rob@77: test.expect(23); rob@77: rob@77: test.equals( jQuery.type(null), "null", "null" ); rob@77: test.equals( jQuery.type(undefined), "undefined", "undefined" ); rob@77: test.equals( jQuery.type(true), "boolean", "Boolean" ); rob@77: test.equals( jQuery.type(false), "boolean", "Boolean" ); rob@77: test.equals( jQuery.type(Boolean(true)), "boolean", "Boolean" ); rob@77: test.equals( jQuery.type(0), "number", "Number" ); rob@77: test.equals( jQuery.type(1), "number", "Number" ); rob@77: test.equals( jQuery.type(Number(1)), "number", "Number" ); rob@77: test.equals( jQuery.type(""), "string", "String" ); rob@77: test.equals( jQuery.type("a"), "string", "String" ); rob@77: test.equals( jQuery.type(String("a")), "string", "String" ); rob@77: test.equals( jQuery.type({}), "object", "Object" ); rob@77: test.equals( jQuery.type(/foo/), "regexp", "RegExp" ); rob@77: test.equals( jQuery.type(new RegExp("asdf")), "regexp", "RegExp" ); rob@77: test.equals( jQuery.type([1]), "array", "Array" ); rob@77: test.equals( jQuery.type(new Date()), "date", "Date" ); rob@77: test.equals( jQuery.type(new Function("return;")), "function", "Function" ); rob@77: test.equals( jQuery.type(function(){}), "function", "Function" ); rob@77: test.equals( jQuery.type(window), "object", "Window" ); rob@77: test.equals( jQuery.type(document), "object", "Document" ); rob@77: test.equals( jQuery.type(document.body), "object", "Element" ); rob@77: test.equals( jQuery.type(document.createTextNode("foo")), "object", "TextNode" ); rob@77: test.equals( jQuery.type(document.getElementsByTagName("*")), "object", "NodeList" ); rob@77: test.done(); rob@77: }, rob@77: "isPlainObject": function(test) { rob@77: test.expect(13); rob@77: rob@77: // The use case that we want to match rob@77: test.ok(jQuery.isPlainObject({}), "{}"); rob@77: rob@77: // Not objects shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject(""), "string"); rob@77: test.ok(!jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number"); rob@77: test.ok(!jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean"); rob@77: test.ok(!jQuery.isPlainObject(null), "null"); rob@77: test.ok(!jQuery.isPlainObject(undefined), "undefined"); rob@77: rob@77: // Arrays shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject([]), "array"); rob@77: rob@77: // Instantiated objects shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject(new Date), "new Date"); rob@77: rob@77: var fn = function(){}; rob@77: rob@77: // Functions shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject(fn), "fn"); rob@77: rob@77: // Again, instantiated objects shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject(new fn), "new fn (no methods)"); rob@77: rob@77: // Makes the function a little more realistic rob@77: // (and harder to detect, incidentally) rob@77: fn.prototype = {someMethod: function(){}}; rob@77: rob@77: // Again, instantiated objects shouldn't be matched rob@77: test.ok(!jQuery.isPlainObject(new fn), "new fn"); rob@77: rob@77: // DOM Element rob@77: test.ok(!jQuery.isPlainObject(document.createElement("div")), "DOM Element"); rob@77: rob@77: // Window rob@77: test.ok(!jQuery.isPlainObject(window), "window"); rob@77: rob@77: /* XXX removed iframe test */ rob@77: test.done(); rob@77: }, rob@77: "isFunction": function(test) { rob@77: test.expect(19); rob@77: rob@77: // Make sure that false values return false rob@77: test.ok( !jQuery.isFunction(), "No Value" ); rob@77: test.ok( !jQuery.isFunction( null ), "null Value" ); rob@77: test.ok( !jQuery.isFunction( undefined ), "undefined Value" ); rob@77: test.ok( !jQuery.isFunction( "" ), "Empty String Value" ); rob@77: test.ok( !jQuery.isFunction( 0 ), "0 Value" ); rob@77: rob@77: // Check built-ins rob@77: // Safari uses "(Internal Function)" rob@77: test.ok( jQuery.isFunction(String), "String Function("+String+")" ); rob@77: test.ok( jQuery.isFunction(Array), "Array Function("+Array+")" ); rob@77: test.ok( jQuery.isFunction(Object), "Object Function("+Object+")" ); rob@77: test.ok( jQuery.isFunction(Function), "Function Function("+Function+")" ); rob@77: rob@77: // When stringified, this could be misinterpreted rob@77: var mystr = "function"; rob@77: test.ok( !jQuery.isFunction(mystr), "Function String" ); rob@77: rob@77: // When stringified, this could be misinterpreted rob@77: var myarr = [ "function" ]; rob@77: test.ok( !jQuery.isFunction(myarr), "Function Array" ); rob@77: rob@77: // When stringified, this could be misinterpreted rob@77: var myfunction = { "function": "test" }; rob@77: test.ok( !jQuery.isFunction(myfunction), "Function Object" ); rob@77: rob@77: // Make sure normal functions still work rob@77: var fn = function(){}; rob@77: test.ok( jQuery.isFunction(fn), "Normal Function" ); rob@77: rob@77: var obj = document.createElement("object"); rob@77: rob@77: // Firefox says this is a function rob@77: test.ok( !jQuery.isFunction(obj), "Object Element" ); rob@77: rob@77: // IE says this is an object rob@77: // Since 1.3, this isn't supported (#2968) rob@77: //test.ok( jQuery.isFunction(obj.getAttribute), "getAttribute Function" ); rob@77: rob@77: var nodes = document.body.childNodes; rob@77: rob@77: // Safari says this is a function rob@77: test.ok( !jQuery.isFunction(nodes), "childNodes Property" ); rob@77: rob@77: var first = document.body.firstChild; rob@77: rob@77: // Normal elements are reported test.ok everywhere rob@77: test.ok( !jQuery.isFunction(first), "A normal DOM Element" ); rob@77: rob@77: var input = document.createElement("input"); rob@77: input.type = "text"; rob@77: document.body.appendChild( input ); rob@77: rob@77: // IE says this is an object rob@77: // Since 1.3, this isn't supported (#2968) rob@77: //test.ok( jQuery.isFunction(input.focus), "A default function property" ); rob@77: rob@77: document.body.removeChild( input ); rob@77: rob@77: var a = document.createElement("a"); rob@77: a.href = "some-function"; rob@77: document.body.appendChild( a ); rob@77: rob@77: // This serializes with the word 'function' in it rob@77: test.ok( !jQuery.isFunction(a), "Anchor Element" ); rob@77: rob@77: document.body.removeChild( a ); rob@77: rob@77: // Recursive function calls have lengths and array-like properties rob@77: function callme(callback){ rob@77: function fn(response){ rob@77: callback(response); rob@77: } rob@77: rob@77: test.ok( jQuery.isFunction(fn), "Recursive Function Call" ); rob@77: rob@77: fn({ some: "data" }); rob@77: }; rob@77: rob@77: callme(function(){ rob@77: callme(function(){}); rob@77: }); rob@77: test.done(); rob@77: }, rob@77: "isXMLDoc - HTML": function(test) { rob@77: test.expect(4); rob@77: rob@77: test.ok( !jQuery.isXMLDoc( document ), "HTML document" ); rob@77: test.ok( !jQuery.isXMLDoc( document.documentElement ), "HTML documentElement" ); rob@77: test.ok( !jQuery.isXMLDoc( document.body ), "HTML Body Element" ); rob@77: rob@77: var iframe = document.createElement("iframe"); rob@77: document.body.appendChild( iframe ); rob@77: rob@77: try { rob@77: var body = jQuery(iframe).contents()[0]; rob@77: rob@77: try { rob@77: test.ok( !jQuery.isXMLDoc( body ), "Iframe body element" ); rob@77: } catch(e) { rob@77: test.ok( false, "Iframe body element exception" ); rob@77: } rob@77: rob@77: } catch(e) { rob@77: test.ok( true, "Iframe body element - iframe not working correctly" ); rob@77: } rob@77: rob@77: test.done(); rob@77: }, rob@77: "jQuery('html')": function(test) { rob@77: test.expect(15); rob@77: rob@77: jQuery.foo = false; rob@77: var s = jQuery("")[0]; rob@77: test.ok( s, "Creating a script" ); rob@77: test.ok( !jQuery.foo, "Make sure the script wasn't executed prematurely" ); rob@77: jQuery("body").append(""); rob@77: test.ok( jQuery.foo, "Executing a scripts contents in the right context" ); rob@77: rob@77: // Test multi-line HTML rob@77: var div = jQuery("
\r\nsome text\n

some p

\nmore text\r\n
")[0]; rob@77: test.equals( div.nodeName.toUpperCase(), "DIV", "Make sure we're getting a div." ); rob@77: test.equals( div.firstChild.nodeType, 3, "Text node." ); rob@77: test.equals( div.lastChild.nodeType, 3, "Text node." ); rob@77: test.equals( div.childNodes[1].nodeType, 1, "Paragraph." ); rob@77: test.equals( div.childNodes[1].firstChild.nodeType, 3, "Paragraph text." ); rob@77: rob@77: test.ok( jQuery("")[0], "Creating a link" ); rob@77: rob@77: test.ok( !jQuery("'); rob@77: src = jQuery('script', dom).attr('src'); rob@77: test.equals(src, 'none.js', 'script should return proper src attribute'); rob@77: test.done(); rob@77: }, rob@77: "jQuery('html', context)": function(test) { rob@77: test.expect(1); rob@77: rob@77: var $div = jQuery("
")[0]; rob@77: var $span = jQuery("", $div); rob@77: test.equals($span.length, 1, "Verify a span created with a div context works, #1763"); rob@77: test.done(); rob@77: }, rob@77: "text()": function(test) { rob@77: test.expect(2); rob@77: test.equals("Yahoo", jQuery("#yahoo").text(), "check for text in anchor"); rob@77: test.equals("Everything inside the red border is inside a div with id=\"foo\".", jQuery("#sndp").text(), "check for text in complex paragraph"); rob@77: test.done(); rob@77: }, rob@77: "end()": function(test) { rob@77: test.expect(3); rob@77: test.equals( 'Yahoo', jQuery('#yahoo').parent().end().text(), 'Check for end' ); rob@77: test.ok( jQuery('#yahoo').end(), 'Check for end with nothing to end' ); rob@77: rob@77: var x = jQuery('#yahoo'); rob@77: x.parent(); rob@77: test.equals( 'Yahoo', jQuery('#yahoo').text(), 'Check for non-destructive behaviour' ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "length": function(test) { rob@77: test.expect(1); rob@77: test.equals( jQuery("#main p").length, 6, "Get Number of Elements Found" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "size()": function(test) { rob@77: test.expect(1); rob@77: test.equals( jQuery("#main p").size(), 6, "Get Number of Elements Found" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "get()": function(test) { rob@77: test.expect(1); rob@77: test.same( jQuery("#main p").get(), q("firstp","ap","sndp","en","sap","first"), "Get All Elements" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "toArray()": function(test) { rob@77: test.expect(1); rob@77: test.same( jQuery("#main p").toArray(), rob@77: q("firstp","ap","sndp","en","sap","first"), rob@77: "Convert jQuery object to an Array" ) rob@77: test.done(); rob@77: }, rob@77: rob@77: "get(Number)": function(test) { rob@77: test.expect(2); rob@77: test.equals( jQuery("#main p").get(0), document.getElementById("firstp"), "Get A Single Element" ); rob@77: test.strictEqual( jQuery("#firstp").get(1), undefined, "Try get with index larger elements count" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "get(-Number)": function(test) { rob@77: test.expect(2); rob@77: test.equals( jQuery("p").get(-1), document.getElementById("first"), "Get a single element with negative index" ); rob@77: test.strictEqual( jQuery("#firstp").get(-2), undefined, "Try get with index negative index larger then elements count" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "attr()": function(test) { rob@77: var e = null; rob@77: test.expect(4); rob@77: test.equals( jQuery('#input1').attr('name'), 'PWD', "Get form element name attribute" ); rob@77: test.equals( jQuery('#input2').attr('name'), 'T1', "Get form element name attribute" ); rob@77: test.equals( jQuery('item').attr('name'), 'test val', "Get name attribute from element" ); rob@77: e = jsdom('content'); rob@77: test.equals( jQuery('element', e).attr('name'), 'dude', "Get name attribute from element" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "each(Function)": function(test) { rob@77: test.expect(1); rob@77: var div = jQuery("div"); rob@77: div.each(function(){this.foo = 'zoo';}); rob@77: var pass = true; rob@77: for ( var i = 0; i < div.size(); i++ ) { rob@77: if ( div.get(i).foo != "zoo" ) pass = false; rob@77: } rob@77: test.ok( pass, "Execute a function, Relative" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "slice()": function(test) { rob@77: test.expect(7); rob@77: rob@77: var $links = jQuery("#ap a"); rob@77: rob@77: test.same( $links.slice(1,2).get(), q("groups"), "slice(1,2)" ); rob@77: test.same( $links.slice(1).get(), q("groups", "anchor1", "mark"), "slice(1)" ); rob@77: test.same( $links.slice(0,3).get(), q("google", "groups", "anchor1"), "slice(0,3)" ); rob@77: test.same( $links.slice(-1).get(), q("mark"), "slice(-1)" ); rob@77: rob@77: test.same( $links.eq(1).get(), q("groups"), "eq(1)" ); rob@77: test.same( $links.eq('2').get(), q("anchor1"), "eq('2')" ); rob@77: test.same( $links.eq(-1).get(), q("mark"), "eq(-1)" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "first()/last()": function(test) { rob@77: test.expect(4); rob@77: rob@77: var $links = jQuery("#ap a"), $none = jQuery("asdf"); rob@77: rob@77: test.same( $links.first().get(), q("google"), "first()" ); rob@77: test.same( $links.last().get(), q("mark"), "last()" ); rob@77: rob@77: test.same( $none.first().get(), [], "first() none" ); rob@77: test.same( $none.last().get(), [], "last() none" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "map()": function(test) { rob@77: test.expect(2);//test.expect(6); rob@77: rob@77: test.same( rob@77: jQuery("#ap").map(function(){ rob@77: return jQuery(this).find("a").get(); rob@77: }).get(), rob@77: q("google", "groups", "anchor1", "mark"), rob@77: "Array Map" rob@77: ); rob@77: rob@77: test.same( rob@77: jQuery("#ap > a").map(function(){ rob@77: return this.parentNode; rob@77: }).get(), rob@77: q("ap","ap","ap"), rob@77: "Single Map" rob@77: ); rob@77: test.done(); rob@77: rob@77: return;//these haven't been accepted yet rob@77: rob@77: //for #2616 rob@77: var keys = jQuery.map( {a:1,b:2}, function( v, k ){ rob@77: return k; rob@77: }, [ ] ); rob@77: rob@77: test.equals( keys.join(""), "ab", "Map the keys from a hash to an array" ); rob@77: rob@77: var values = jQuery.map( {a:1,b:2}, function( v, k ){ rob@77: return v; rob@77: }, [ ] ); rob@77: rob@77: test.equals( values.join(""), "12", "Map the values from a hash to an array" ); rob@77: rob@77: var scripts = document.getElementsByTagName("script"); rob@77: var mapped = jQuery.map( scripts, function( v, k ){ rob@77: return v; rob@77: }, {length:0} ); rob@77: rob@77: test.equals( mapped.length, scripts.length, "Map an array(-like) to a hash" ); rob@77: rob@77: var flat = jQuery.map( Array(4), function( v, k ){ rob@77: return k % 2 ? k : [k,k,k];//try mixing array and regular returns rob@77: }); rob@77: rob@77: test.equals( flat.join(""), "00012223", "try the new flatten technique(#2616)" ); rob@77: }, rob@77: rob@77: "jQuery.merge()": function(test) { rob@77: test.expect(8); rob@77: rob@77: var parse = jQuery.merge; rob@77: rob@77: test.same( parse([],[]), [], "Empty arrays" ); rob@77: rob@77: test.same( parse([1],[2]), [1,2], "Basic" ); rob@77: test.same( parse([1,2],[3,4]), [1,2,3,4], "Basic" ); rob@77: rob@77: test.same( parse([1,2],[]), [1,2], "Second empty" ); rob@77: test.same( parse([],[1,2]), [1,2], "First empty" ); rob@77: rob@77: // Fixed at [5998], #3641 rob@77: test.same( parse([-2,-1], [0,1,2]), [-2,-1,0,1,2], "Second array including a zero (falsy)"); rob@77: rob@77: // After fixing #5527 rob@77: test.same( parse([], [null, undefined]), [null, undefined], "Second array including null and undefined values"); rob@77: test.same( parse({length:0}, [1,2]), {length:2, 0:1, 1:2}, "First array like"); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.extend(Object, Object)": function(test) { rob@77: test.expect(28); rob@77: rob@77: var settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" }, rob@77: options = { xnumber2: 1, xstring2: "x", xxx: "newstring" }, rob@77: optionsCopy = { xnumber2: 1, xstring2: "x", xxx: "newstring" }, rob@77: merged = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "x", xxx: "newstring" }, rob@77: deep1 = { foo: { bar: true } }, rob@77: deep1copy = { foo: { bar: true } }, rob@77: deep2 = { foo: { baz: true }, foo2: document }, rob@77: deep2copy = { foo: { baz: true }, foo2: document }, rob@77: deepmerged = { foo: { bar: true, baz: true }, foo2: document }, rob@77: arr = [1, 2, 3], rob@77: nestedarray = { arr: arr }; rob@77: rob@77: jQuery.extend(settings, options); rob@77: test.same( settings, merged, "Check if extended: settings must be extended" ); rob@77: test.same( options, optionsCopy, "Check if not modified: options must not be modified" ); rob@77: rob@77: jQuery.extend(settings, null, options); rob@77: test.same( settings, merged, "Check if extended: settings must be extended" ); rob@77: test.same( options, optionsCopy, "Check if not modified: options must not be modified" ); rob@77: rob@77: jQuery.extend(true, deep1, deep2); rob@77: test.same( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" ); rob@77: test.same( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" ); rob@77: test.equals( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" ); rob@77: rob@77: test.ok( jQuery.extend(true, {}, nestedarray).arr !== arr, "Deep extend of object must clone child array" ); rob@77: rob@77: // #5991 rob@77: test.ok( jQuery.isArray( jQuery.extend(true, { arr: {} }, nestedarray).arr ), "Cloned array heve to be an Array" ); rob@77: test.ok( jQuery.isPlainObject( jQuery.extend(true, { arr: arr }, { arr: {} }).arr ), "Cloned object heve to be an plain object" ); rob@77: rob@77: var empty = {}; rob@77: var optionsWithLength = { foo: { length: -1 } }; rob@77: jQuery.extend(true, empty, optionsWithLength); rob@77: test.same( empty.foo, optionsWithLength.foo, "The length property must copy correctly" ); rob@77: rob@77: empty = {}; rob@77: var optionsWithDate = { foo: { date: new Date } }; rob@77: jQuery.extend(true, empty, optionsWithDate); rob@77: test.same( empty.foo, optionsWithDate.foo, "Dates copy correctly" ); rob@77: rob@77: var myKlass = function() {}; rob@77: var customObject = new myKlass(); rob@77: var optionsWithCustomObject = { foo: { date: customObject } }; rob@77: empty = {}; rob@77: jQuery.extend(true, empty, optionsWithCustomObject); rob@77: test.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" ); rob@77: rob@77: // Makes the class a little more realistic rob@77: myKlass.prototype = { someMethod: function(){} }; rob@77: empty = {}; rob@77: jQuery.extend(true, empty, optionsWithCustomObject); rob@77: test.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" ); rob@77: rob@77: var ret = jQuery.extend(true, { foo: 4 }, { foo: new Number(5) } ); rob@77: test.ok( ret.foo == 5, "Wrapped numbers copy correctly" ); rob@77: rob@77: var nullUndef; rob@77: nullUndef = jQuery.extend({}, options, { xnumber2: null }); rob@77: test.ok( nullUndef.xnumber2 === null, "Check to make sure null values are copied"); rob@77: rob@77: nullUndef = jQuery.extend({}, options, { xnumber2: undefined }); rob@77: test.ok( nullUndef.xnumber2 === options.xnumber2, "Check to make sure undefined values are not copied"); rob@77: rob@77: nullUndef = jQuery.extend({}, options, { xnumber0: null }); rob@77: test.ok( nullUndef.xnumber0 === null, "Check to make sure null values are inserted"); rob@77: rob@77: var target = {}; rob@77: var recursive = { foo:target, bar:5 }; rob@77: jQuery.extend(true, target, recursive); rob@77: test.same( target, { bar:5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" ); rob@77: rob@77: var ret = jQuery.extend(true, { foo: [] }, { foo: [0] } ); // 1907 rob@77: test.equals( ret.foo.length, 1, "Check to make sure a value with coersion 'false' copies over when necessary to fix #1907" ); rob@77: rob@77: var ret = jQuery.extend(true, { foo: "1,2,3" }, { foo: [1, 2, 3] } ); rob@77: test.ok( typeof ret.foo != "string", "Check to make sure values equal with coersion (but not actually equal) overwrite correctly" ); rob@77: rob@77: var ret = jQuery.extend(true, { foo:"bar" }, { foo:null } ); rob@77: test.ok( typeof ret.foo !== 'undefined', "Make sure a null value doesn't crash with deep extend, for #1908" ); rob@77: rob@77: var obj = { foo:null }; rob@77: jQuery.extend(true, obj, { foo:"notnull" } ); rob@77: test.equals( obj.foo, "notnull", "Make sure a null value can be overwritten" ); rob@77: rob@77: function func() {} rob@77: jQuery.extend(func, { key: "value" } ); rob@77: test.equals( func.key, "value", "Verify a function can be extended" ); rob@77: rob@77: var defaults = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" }, rob@77: defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" }, rob@77: options1 = { xnumber2: 1, xstring2: "x" }, rob@77: options1Copy = { xnumber2: 1, xstring2: "x" }, rob@77: options2 = { xstring2: "xx", xxx: "newstringx" }, rob@77: options2Copy = { xstring2: "xx", xxx: "newstringx" }, rob@77: merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" }; rob@77: rob@77: var settings = jQuery.extend({}, defaults, options1, options2); rob@77: test.same( settings, merged2, "Check if extended: settings must be extended" ); rob@77: test.same( defaults, defaultsCopy, "Check if not modified: options1 must not be modified" ); rob@77: test.same( options1, options1Copy, "Check if not modified: options1 must not be modified" ); rob@77: test.same( options2, options2Copy, "Check if not modified: options2 must not be modified" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.each(Object,Function)": function(test) { rob@77: test.expect(13); rob@77: jQuery.each( [0,1,2], function(i, n){ rob@77: test.equals( i, n, "Check array iteration" ); rob@77: }); rob@77: rob@77: jQuery.each( [5,6,7], function(i, n){ rob@77: test.equals( i, n - 5, "Check array iteration" ); rob@77: }); rob@77: rob@77: jQuery.each( { name: "name", lang: "lang" }, function(i, n){ rob@77: test.equals( i, n, "Check object iteration" ); rob@77: }); rob@77: rob@77: var total = 0; rob@77: jQuery.each([1,2,3], function(i,v){ total += v; }); rob@77: test.equals( total, 6, "Looping over an array" ); rob@77: total = 0; rob@77: jQuery.each([1,2,3], function(i,v){ total += v; if ( i == 1 ) return false; }); rob@77: test.equals( total, 3, "Looping over an array, with break" ); rob@77: total = 0; rob@77: jQuery.each({"a":1,"b":2,"c":3}, function(i,v){ total += v; }); rob@77: test.equals( total, 6, "Looping over an object" ); rob@77: total = 0; rob@77: jQuery.each({"a":3,"b":3,"c":3}, function(i,v){ total += v; return false; }); rob@77: test.equals( total, 3, "Looping over an object, with break" ); rob@77: rob@77: var f = function(){}; rob@77: f.foo = 'bar'; rob@77: jQuery.each(f, function(i){ rob@77: f[i] = 'baz'; rob@77: }); rob@77: test.equals( "baz", f.foo, "Loop over a function" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.makeArray": function(test){ rob@77: test.expect(17); rob@77: rob@77: test.equals( jQuery.makeArray(jQuery('html>*'))[0].nodeName.toUpperCase(), "HEAD", "Pass makeArray a jQuery object" ); rob@77: rob@77: test.equals( jQuery.makeArray(document.getElementsByName("PWD")).slice(0,1)[0].name, "PWD", "Pass makeArray a nodelist" ); rob@77: rob@77: test.equals( (function(){ return jQuery.makeArray(arguments); })(1,2).join(""), "12", "Pass makeArray an arguments array" ); rob@77: rob@77: test.equals( jQuery.makeArray([1,2,3]).join(""), "123", "Pass makeArray a real array" ); rob@77: rob@77: test.equals( jQuery.makeArray().length, 0, "Pass nothing to makeArray and test.expect an empty array" ); rob@77: rob@77: test.equals( jQuery.makeArray( 0 )[0], 0 , "Pass makeArray a number" ); rob@77: rob@77: test.equals( jQuery.makeArray( "foo" )[0], "foo", "Pass makeArray a string" ); rob@77: rob@77: test.equals( jQuery.makeArray( true )[0].constructor, Boolean, "Pass makeArray a boolean" ); rob@77: rob@77: test.equals( jQuery.makeArray( document.createElement("div") )[0].nodeName.toUpperCase(), "DIV", "Pass makeArray a single node" ); rob@77: rob@77: test.equals( jQuery.makeArray( {length:2, 0:"a", 1:"b"} ).join(""), "ab", "Pass makeArray an array like map (with length)" ); rob@77: rob@77: test.ok( !!jQuery.makeArray( document.documentElement.childNodes ).slice(0,1)[0].nodeName, "Pass makeArray a childNodes array" ); rob@77: rob@77: // function, is tricky as it has length rob@77: test.equals( jQuery.makeArray( function(){ return 1;} )[0](), 1, "Pass makeArray a function" ); rob@77: rob@77: //window, also has length rob@77: test.equals( jQuery.makeArray(window)[0], window, "Pass makeArray the window" ); rob@77: rob@77: test.equals( jQuery.makeArray(/a/)[0].constructor, RegExp, "Pass makeArray a regex" ); rob@77: rob@77: test.equals( jQuery.makeArray(document.getElementById('form')).length, 2, "Pass makeArray a form (treat as elements)" ); rob@77: rob@77: // For #5610 rob@77: test.same( jQuery.makeArray({'length': '0'}), [], "Make sure object is coerced properly."); rob@77: test.same( jQuery.makeArray({'length': '5'}), [], "Make sure object is coerced properly."); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.isEmptyObject": function(test){ rob@77: test.expect(2); rob@77: rob@77: test.equals(true, jQuery.isEmptyObject({}), "isEmptyObject on empty object literal" ); rob@77: test.equals(false, jQuery.isEmptyObject({a:1}), "isEmptyObject on non-empty object literal" ); rob@77: rob@77: // What about this ? rob@77: // test.equals(true, jQuery.isEmptyObject(null), "isEmptyObject on null" ); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.proxy": function(test){ rob@77: test.expect(4); rob@77: rob@77: var testfn = function(){ test.equals( this, thisObject, "Make sure that scope is set properly." ); }; rob@77: var thisObject = { foo: "bar", method: testfn }; rob@77: rob@77: // Make sure normal works rob@77: testfn.call( thisObject ); rob@77: rob@77: // Basic scoping rob@77: jQuery.proxy( testfn, thisObject )(); rob@77: rob@77: // Make sure it doesn't freak out rob@77: test.equals( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." ); rob@77: rob@77: // Use the string shortcut rob@77: jQuery.proxy( thisObject, "method" )(); rob@77: test.done(); rob@77: }, rob@77: "jQuery.parseJSON": function(test){ rob@77: test.expect(8); rob@77: rob@77: test.equals( jQuery.parseJSON(), null, "Nothing in, null out." ); rob@77: test.equals( jQuery.parseJSON( null ), null, "Nothing in, null out." ); rob@77: test.equals( jQuery.parseJSON( "" ), null, "Nothing in, null out." ); rob@77: rob@77: test.same( jQuery.parseJSON("{}"), {}, "Plain object parsing." ); rob@77: test.same( jQuery.parseJSON('{"test":1}'), {"test":1}, "Plain object parsing." ); rob@77: rob@77: test.same( jQuery.parseJSON('\n{"test":1}'), {"test":1}, "Make sure leading whitespaces are handled." ); rob@77: rob@77: try { rob@77: jQuery.parseJSON("{a:1}"); rob@77: test.ok( false, "Test malformed JSON string." ); rob@77: } catch( e ) { rob@77: test.ok( true, "Test malformed JSON string." ); rob@77: } rob@77: rob@77: try { rob@77: jQuery.parseJSON("{'a':1}"); rob@77: test.ok( false, "Test malformed JSON string." ); rob@77: } catch( e ) { rob@77: test.ok( true, "Test malformed JSON string." ); rob@77: } rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.sub() - Static Methods": function(test){ rob@77: test.expect(18); rob@77: var Subclass = jQuery.sub(); rob@77: Subclass.extend({ rob@77: topLevelMethod: function() {return this.debug;}, rob@77: debug: false, rob@77: config: { rob@77: locale: 'en_US' rob@77: }, rob@77: setup: function(config) { rob@77: this.extend(true, this.config, config); rob@77: } rob@77: }); rob@77: Subclass.fn.extend({subClassMethod: function() { return this;}}); rob@77: rob@77: //Test Simple Subclass rob@77: test.ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true'); rob@77: test.ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!'); rob@77: test.same(Subclass.config.test, undefined, 'Subclass.config.test is set incorrectly'); rob@77: test.equal(jQuery.ajax, Subclass.ajax, 'The subclass failed to get all top level methods'); rob@77: rob@77: //Create a SubSubclass rob@77: var SubSubclass = Subclass.sub(); rob@77: rob@77: //Make Sure the SubSubclass inherited properly rob@77: test.ok(SubSubclass.topLevelMethod() === false, 'SubSubclass.topLevelMethod thought debug was true'); rob@77: test.ok(SubSubclass.config.locale == 'en_US', SubSubclass.config.locale + ' is wrong!'); rob@77: test.same(SubSubclass.config.test, undefined, 'SubSubclass.config.test is set incorrectly'); rob@77: test.equal(jQuery.ajax, SubSubclass.ajax, 'The subsubclass failed to get all top level methods'); rob@77: rob@77: //Modify The Subclass and test the Modifications rob@77: SubSubclass.fn.extend({subSubClassMethod: function() { return this;}}); rob@77: SubSubclass.setup({locale: 'es_MX', test: 'worked'}); rob@77: SubSubclass.debug = true; rob@77: SubSubclass.ajax = function() {return false;}; rob@77: test.ok(SubSubclass.topLevelMethod(), 'SubSubclass.topLevelMethod thought debug was false'); rob@77: test.same(SubSubclass(document).subClassMethod, Subclass.fn.subClassMethod, 'Methods Differ!'); rob@77: test.ok(SubSubclass.config.locale == 'es_MX', SubSubclass.config.locale + ' is wrong!'); rob@77: test.ok(SubSubclass.config.test == 'worked', 'SubSubclass.config.test is set incorrectly'); rob@77: test.notEqual(jQuery.ajax, SubSubclass.ajax, 'The subsubclass failed to get all top level methods'); rob@77: rob@77: //This shows that the modifications to the SubSubClass did not bubble back up to it's superclass rob@77: test.ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true'); rob@77: test.ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!'); rob@77: test.same(Subclass.config.test, undefined, 'Subclass.config.test is set incorrectly'); rob@77: test.same(Subclass(document).subSubClassMethod, undefined, 'subSubClassMethod set incorrectly'); rob@77: test.equal(jQuery.ajax, Subclass.ajax, 'The subclass failed to get all top level methods'); rob@77: test.done(); rob@77: }, rob@77: rob@77: "jQuery.sub() - .fn Methods": function(test){ rob@77: test.expect(378); rob@77: rob@77: var Subclass = jQuery.sub(), rob@77: SubclassSubclass = Subclass.sub(), rob@77: jQueryDocument = jQuery(document), rob@77: selectors, contexts, methods, method, arg, description; rob@77: rob@77: jQueryDocument.toString = function(){ return 'jQueryDocument'; }; rob@77: rob@77: Subclass.fn.subclassMethod = function(){}; rob@77: SubclassSubclass.fn.subclassSubclassMethod = function(){}; rob@77: rob@77: selectors = [ rob@77: 'body', rob@77: 'html, body', rob@77: '
' rob@77: ]; rob@77: rob@77: methods = [ // all methods that return a new jQuery instance rob@77: ['eq', 1], rob@77: ['add', document], rob@77: ['end'], rob@77: ['has'], rob@77: ['closest', 'div'], rob@77: ['filter', document], rob@77: ['find', 'div'] rob@77: ]; rob@77: rob@77: contexts = [undefined, document, jQueryDocument]; rob@77: rob@77: jQuery.each(selectors, function(i, selector){ rob@77: rob@77: jQuery.each(methods, function(){ rob@77: method = this[0]; rob@77: arg = this[1]; rob@77: rob@77: jQuery.each(contexts, function(i, context){ rob@77: rob@77: description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')'; rob@77: rob@77: test.same( rob@77: jQuery(selector, context)[method](arg).subclassMethod, undefined, rob@77: 'jQuery'+description+' doesnt have Subclass methods' rob@77: ); rob@77: test.same( rob@77: jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined, rob@77: 'jQuery'+description+' doesnt have SubclassSubclass methods' rob@77: ); rob@77: test.same( rob@77: Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod, rob@77: 'Subclass'+description+' has Subclass methods' rob@77: ); rob@77: test.same( rob@77: Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined, rob@77: 'Subclass'+description+' doesnt have SubclassSubclass methods' rob@77: ); rob@77: test.same( rob@77: SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod, rob@77: 'SubclassSubclass'+description+' has Subclass methods' rob@77: ); rob@77: test.same( rob@77: SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod, rob@77: 'SubclassSubclass'+description+' has SubclassSubclass methods' rob@77: ); rob@77: rob@77: }); rob@77: }); rob@77: }); rob@77: test.done(); rob@77: } rob@77: }); rob@77: