Fixed typo in logic, also disabled function setters in this case to allow the functi...
[jquery.git] / test / unit / core.js
index 25ff1f5..85b421d 100644 (file)
@@ -12,11 +12,11 @@ test("Basic requirements", function() {
 });
 
 test("jQuery()", function() {
-       expect(12);
+       expect(23);
 
        // 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([])" );
@@ -51,14 +51,39 @@ test("jQuery()", function() {
 
        var code = jQuery("<code/>");
        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("<img/>");
        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("<div/><hr/><code/><b/>");
        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("<div/>", {
+               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() {
@@ -135,41 +160,27 @@ test("selector state", function() {
        );
 });
 
+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);
@@ -189,6 +200,75 @@ test("noConflict", function() {
        jQuery = $$;
 });
 
+test("trim", function() {
+  expect(4);
+
+  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", "&nbsp;" );
+});
+
+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");
+       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("<body onload='window.top.iframeDone(Object);'>");
+       doc.close();
+});
+
 test("isFunction", function() {
        expect(19);
 
@@ -310,7 +390,7 @@ test("isXMLDoc - XML", function() {
 }
 
 test("jQuery('html')", function() {
-       expect(13);
+       expect(15);
 
        reset();
        jQuery.foo = false;
@@ -339,6 +419,9 @@ test("jQuery('html')", function() {
        ok( j.length >= 2, "Check node,textnode,comment creation (some browsers delete comments)" );
 
        ok( !jQuery("<option>test</option>")[0].selected, "Make sure that options are auto-selected #2050" );
+
+       ok( jQuery("<div></div>")[0], "Create a div with closing tag." );
+       ok( jQuery("<table></table>")[0], "Create a table with closing tag." );
 });
 
 test("jQuery('html', context)", function() {
@@ -364,6 +447,16 @@ test("jQuery(selector, xml).text(str) - Loaded via XML document", function() {
 });
 }
 
+test("end()", function() {
+       expect(3);
+       equals( 'Yahoo', jQuery('#yahoo').parent().end().text(), 'Check for end' );
+       ok( jQuery('#yahoo').end(), 'Check for end with nothing to end' );
+
+       var x = jQuery('#yahoo');
+       x.parent();
+       equals( 'Yahoo', jQuery('#yahoo').text(), 'Check for non-destructive behaviour' );
+});
+
 test("length", function() {
        expect(1);
        equals( jQuery("p").length, 6, "Get Number of Elements Found" );
@@ -459,45 +552,83 @@ test("each(Function)", function() {
        ok( pass, "Execute a function, Relative" );
 });
 
-test("index()", function() {
-       expect(1);
+test("slice()", function() {
+       expect(7);
+
+       var $links = jQuery("#ap a");
+
+       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)" );
 
-       equals( jQuery("#text2").index(), 2, "Returns the index of a child amongst its siblings" )
+       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("index(Object|String|undefined)", function() {
-       expect(16);
+test("first()/last()", function() {
+       expect(4);
+
+       var $links = jQuery("#ap a"), $none = jQuery("asdf");
 
-       var elements = jQuery([window, document]),
-               inputElements = jQuery('#radio1,#radio2,#check1,#check2');
-
-       // 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" );
-
-       // 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" );
-
-       // 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( $links.first().get(), q("google"), "first()" );
+       same( $links.last().get(), q("mark"), "last()" );
+
+       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;
 
@@ -511,10 +642,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(23);
+       expect(27);
 
        var settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
                options = { xnumber2: 1, xstring2: "x", xxx: "newstring" },
@@ -524,7 +659,9 @@ 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);
        same( settings, merged, "Check if extended: settings must be extended" );
@@ -539,6 +676,9 @@ test("jQuery.extend(Object, Object)", function() {
        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, [], arr) !== arr, "Deep extend of array must clone array" );
+       ok( jQuery.extend(true, {}, nestedarray).arr !== arr, "Deep extend of object must clone child array" );
+
        var empty = {};
        var optionsWithLength = { foo: { length: -1 } };
        jQuery.extend(true, empty, optionsWithLength);
@@ -550,10 +690,20 @@ test("jQuery.extend(Object, Object)", function() {
        same( empty.foo, optionsWithDate.foo, "Dates copy correctly" );
 
        var myKlass = function() {};
+       var customObject = new myKlass();
+       var optionsWithCustomObject = { foo: { date: customObject } };
        empty = {};
-       var optionsWithCustomObject = { foo: { date: new myKlass } };
        jQuery.extend(true, empty, optionsWithCustomObject);
-       same( empty.foo, optionsWithCustomObject.foo, "Custom objects copy correctly" );
+       ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" );
+       
+       // 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 });
@@ -638,7 +788,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" );
 
@@ -671,6 +821,10 @@ 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(){
@@ -682,3 +836,22 @@ test("jQuery.isEmptyObject", function(){
        // 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" )();
+});