var jsdom = require('../../lib/jsdom');
var fs = require('fs');
var jqueryString = fs.readFileSync(__dirname + '/support/jquery-1.6.2.js', 'utf-8');
var testFile = fs.readFileSync(__dirname + '/files/index.html', 'utf-8');
var qunit = require('./support/qunit').QUnit;
function test(fn) {
// return a nodeunit compatible test case
return function(test) {
jsdom.env({
html : testFile,
src : jqueryString,
done : function(e, window) {
var jQuery = window.jQuery;
var document = window.document;
/**
* Returns an array of elements with the given IDs, eg.
* @example q("main", "foo", "bar")
* @result [
, , ]
*/
function q() {
var r = [];
for ( var i = 0; i < arguments.length; i++ ) {
r.push( document.getElementById( arguments[i] ) );
}
return r;
}
/**
* Asserts that a select matches the given IDs * @example t(test,"Check for something", "//[a]", ["foo", "baar"]);
* @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
*/
function t(a,b,c) {
var f = jQuery(b).get(), s = "";
for ( var i = 0; i < f.length; i++ ) {
s += (s && ",") + '"' + f[i].id + '"';
}
var e = qunit.equiv(f, q.apply(q,c));
test.strictEqual(e, true, a + " (" + b + ")");
}
fn(test, window, jQuery, document, q, t);
}
});
}
}
/**
* Add random number to url to stop IE from caching
*
* @example url("data/test.html")
* @result "data/test.html?10538358428943"
*
* @example url("data/test.php?foo=bar")
* @result "data/test.php?foo=bar&10538358345554"
*/
function url(value) {
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
}
module.exports = {};
module.exports['element'] = test(function(test, window, jQuery, document, q, t) {
var all = jQuery("*"), good = true;
for ( var i = 0; i < all.length; i++ )
if ( all[i].nodeType == 8 )
good = false;
test.ok( good, "Select all elements, no comment nodes" );
t( "Element Selector", "#qunit-fixture p", ["firstp","ap","sndp","en","sap","first"] );
t( "Element Selector", "body", ["body"] );
t( "Element Selector", "html", ["html"] );
t( "Parent Element", "div p", ["firstp","ap","sndp","en","sap","first"] );
test.strictEqual( jQuery("param", "#object1").length, 2, "Object/param as context" );
test.deepEqual( jQuery("p", document.getElementsByTagName("div")).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
test.deepEqual( jQuery("p", "div").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
test.deepEqual( jQuery("p", jQuery("div")).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
test.deepEqual( jQuery("div").find("p").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
test.deepEqual( jQuery("#form").find("select").get(), q("select1","select2","select3","select4","select5"), "Finding selects with a context." );
test.ok( jQuery("#length").length, '<input name="length"> cannot be found under IE, see #945' );
test.ok( jQuery("#lengthtest input").length, '<input name="length"> cannot be found under IE, see #945' );
// Check for unique-ness and sort order
test.deepEqual( jQuery("p, div p").get(), jQuery("p").get(), "Check for duplicates: p, div p" );
t( "Checking sort order", "h2, h1", ["qunit-header", "qunit-banner", "qunit-userAgent"] );
t( "Checking sort order", "h2:first, h1:first", ["qunit-header", "qunit-banner"] );
t( "Checking sort order", "#qunit-fixture p, #qunit-fixture p a", ["firstp", "simon1", "ap", "google", "groups", "anchor1", "mark", "sndp", "en", "yahoo", "sap", "anchor2", "simon", "first"] );
// Test Conflict ID
test.deepEqual( jQuery("#lengthtest").find("#idTest").get(), q("idTest"), "Finding element with id of ID." );
test.deepEqual( jQuery("#lengthtest").find("[name='id']").get(), q("idTest"), "Finding element with id of ID." );
test.deepEqual( jQuery("#lengthtest").find("input[id='idTest']").get(), q("idTest"), "Finding elements with a context." );
test.done();
});
/*
if ( location.protocol != "file:" ) {
module.exports['XML Document Selectors'] = test(function(test, window, jQuery, document, q, t) {
stop();
test.ok(false, "needs xmldocument");
jQuery.get("data/with_fries.xml", function(xml) {
test.strictEqual( jQuery("foo_bar", xml).length, 1, "Element Selector with underscore" );
test.strictEqual( jQuery(".component", xml).length, 1, "Class selector" );
test.strictEqual( jQuery("[class*=component]", xml).length, 1, "Attribute selector for class" );
test.strictEqual( jQuery("property[name=prop2]", xml).length, 1, "Attribute selector with name" );
test.strictEqual( jQuery("[name=prop2]", xml).length, 1, "Attribute selector with name" );
test.strictEqual( jQuery("#seite1", xml).length, 1, "Attribute selector with ID" );
test.strictEqual( jQuery("component#seite1", xml).length, 1, "Attribute selector with ID" );
test.strictEqual( jQuery("component", xml).filter("#seite1").length, 1, "Attribute selector filter with ID" );
test.ok( jQuery( xml.lastChild ).is( "soap\\:Envelope" ), "Check for namespaced element" );
start();
test.done();
});
test.done()
});
}*/
module.exports['broken'] = test(function(test, window, jQuery, document, q, t) {
function broken(name, selector) {
try {
jQuery(selector);
test.ok( false, name + ": " + selector );
} catch(e){
test.ok( typeof e === "string" && e.indexOf("Syntax error") >= 0,
name + ": " + selector );
}
}
broken( "Broken Selector", "[", [] );
broken( "Broken Selector", "(", [] );
broken( "Broken Selector", "{", [] );
broken( "Broken Selector", "<", [] );
broken( "Broken Selector", "()", [] );
broken( "Broken Selector", "<>", [] );
broken( "Broken Selector", "{}", [] );
broken( "Doesn't exist", ":visble", [] );
broken( "Nth-child", ":nth-child", [] );
// Sigh again. IE 9 thinks this is also a real selector
// not super critical that we fix this case
//broken( "Nth-child", ":nth-child(-)", [] );
// Sigh. WebKit thinks this is a real selector in qSA
// They've already fixed this and it'll be coming into
// current browsers soon.
//broken( "Nth-child", ":nth-child(asdf)", [] );
broken( "Nth-child", ":nth-child(2n+-0)", [] );
broken( "Nth-child", ":nth-child(2+0)", [] );
broken( "Nth-child", ":nth-child(- 1n)", [] );
broken( "Nth-child", ":nth-child(-1 n)", [] );
broken( "First-child", ":first-child(n)", [] );
broken( "Last-child", ":last-child(n)", [] );
broken( "Only-child", ":only-child(n)", [] );
// Make sure attribute value quoting works correctly. See: #6093
var attrbad = jQuery('').appendTo("body");
broken( "Attribute not escaped", "input[name=foo.baz]", [] );
broken( "Attribute not escaped", "input[name=foo[baz]]", [] );
attrbad.remove();
test.done()
});
module.exports['id'] = test(function(test, window, jQuery, document, q, t) {
t( "ID Selector", "#body", ["body"] );
t( "ID Selector w/ Element", "body#body", ["body"] );
t( "ID Selector w/ Element", "ul#first", [] );
t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] );
t( "ID selector with non-existant descendant", "#firstp #foobar", [] );
t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] );
t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] );
t( "Descendant ID selector using UTF8", "div #台北", ["台北"] );
t( "Child ID selector using UTF8", "form > #台北", ["台北"] );
t( "Escaped ID", "#foo\\:bar", ["foo:bar"] );
t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant escaped ID", "div #foo\\:bar", ["foo:bar"] );
t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Child escaped ID", "form > #foo\\:bar", ["foo:bar"] );
t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267
t( "ID Selector, not an ancestor ID", "#form #first", [] );
t( "ID Selector, not a child ID", "#form > #option1a", [] );
t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] );
t( "All Children of ID with no children", "#firstUL > *", [] );
var a = jQuery('
').appendTo('#qunit-fixture');
test.strictEqual( jQuery("#tName1")[0].id, 'tName1', "ID selector with same value for a name attribute" );
test.strictEqual( jQuery("#tName2").length, 0, "ID selector non-existing but name attribute on an A tag" );
a.remove();
t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", ["lengthtest"] );
t( "ID selector with non-existant ancestor", "#asdfasdf #foobar", [] ); // bug #986
test.deepEqual( jQuery("body").find("div#form").get(), [], "ID selector within the context of another element" );
//#7533
test.strictEqual( jQuery("
foo
").find("p").length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" );
t( "Underscore ID", "#types_all", ["types_all"] );
t( "Dash ID", "#fx-queue", ["fx-queue"] );
t( "ID with weird characters in it", "#name\\+value", ["name+value"] );
test.done()
});
module.exports['class'] = test(function(test, window, jQuery, document, q, t) {
t( "Class Selector", ".blog", ["mark","simon"] );
t( "Class Selector", ".GROUPS", ["groups"] );
t( "Class Selector", ".blog.link", ["simon"] );
t( "Class Selector w/ Element", "a.blog", ["mark","simon"] );
t( "Parent Class Selector", "p .blog", ["mark","simon"] );
test.deepEqual( jQuery(".blog", document.getElementsByTagName("p")).get(), q("mark", "simon"), "Finding elements with a context." );
test.deepEqual( jQuery(".blog", "p").get(), q("mark", "simon"), "Finding elements with a context." );
test.deepEqual( jQuery(".blog", jQuery("p")).get(), q("mark", "simon"), "Finding elements with a context." );
test.deepEqual( jQuery("p").find(".blog").get(), q("mark", "simon"), "Finding elements with a context." );
t( "Class selector using UTF8", ".台北Táiběi", ["utf8class1"] );
//t( "Class selector using UTF8", ".台北", ["utf8class1","utf8class2"] );
t( "Class selector using UTF8", ".台北Táiběi.台北", ["utf8class1"] );
t( "Class selector using UTF8", ".台北Táiběi, .台北", ["utf8class1","utf8class2"] );
t( "Descendant class selector using UTF8", "div .台北Táiběi", ["utf8class1"] );
t( "Child class selector using UTF8", "form > .台北Táiběi", ["utf8class1"] );
t( "Escaped Class", ".foo\\:bar", ["foo:bar"] );
t( "Escaped Class", ".test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant scaped Class", "div .foo\\:bar", ["foo:bar"] );
t( "Descendant scaped Class", "div .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Child escaped Class", "form > .foo\\:bar", ["foo:bar"] );
t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
var div = document.createElement("div");
div.innerHTML = "";
test.deepEqual( jQuery(".e", div).get(), [ div.firstChild ], "Finding a second class." );
div.lastChild.className = "e";
test.deepEqual( jQuery(".e", div).get(), [ div.firstChild, div.lastChild ], "Finding a modified class." );
test.done()
});
module.exports['name'] = test(function(test, window, jQuery, document, q, t) {
t( "Name selector", "input[name=action]", ["text1"] );
t( "Name selector with single quotes", "input[name='action']", ["text1"] );
t( "Name selector with double quotes", 'input[name="action"]', ["text1"] );
t( "Name selector non-input", "[name=test]", ["length", "fx-queue"] );
t( "Name selector non-input", "[name=div]", ["fadein"] );
t( "Name selector non-input", "*[name=iframe]", ["iframe"] );
t( "Name selector for grouped input", "input[name='types[]']", ["types_all", "types_anime", "types_movie"] )
test.deepEqual( jQuery("#form").find("input[name=action]").get(), q("text1"), "Name selector within the context of another element" );
test.deepEqual( jQuery("#form").find("input[name='foo[bar]']").get(), q("hidden2"), "Name selector for grouped form element within the context of another element" );
var form = jQuery("").appendTo("body");
test.strictEqual( form.find("input").length, 1, "Make sure that rooted queries on forms (with possible expandos) work." );
form.remove();
var a = jQuery('