dojo
Version:
Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.
900 lines (821 loc) • 34.6 kB
JavaScript
define([
'intern!object',
'intern/chai!assert',
'require',
'dojo/_base/array'
], function (registerSuite, assert, require, array) {
array.forEach(["query.html", "queryQuirks.html"], function (file) {
array.forEach(["lite", "css2", "css2.1", "css3", "acme"], function (selector) {
var tests = {
name: file + ": " + selector,
before: function () {
return this.get("remote")
.get(require.toUrl("./" + file))
.setExecuteAsyncTimeout(10000)
.executeAsync(function (selector, send) {
require([
'dojo/query!' + selector,
'dojo/sniff',
'dojo/_base/array',
'dojo/dom',
'dojo/dom-construct',
'dojo/request/iframe',
'dojo/domReady!'
], function (_query, _sniff, _array, _dom, _domConstruct, _iframe) {
query = _query;
has = _sniff;
array = _array;
dom = _dom;
domConstruct = _domConstruct;
iframe = _iframe;
send();
})
}, [selector])
.execute(function () {
createDocument = function (xml) {
var fauxXhr = {responseText: xml};
if ("DOMParser" in window) {
var parser = new DOMParser();
fauxXhr.responseXML = parser.parseFromString(xml, "text/xml");
}
// kludge: code from dojo.xhr contentHandler to create doc on IE
var result = fauxXhr.responseXML;
if (has("ie")) {
// Needed for IE6-8
if ((!result || !result.documentElement)) {
var ms = function (n) {
return "MSXML" + n + ".DOMDocument";
};
var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
array.some(dp, function (p) {
try {
var dom = new ActiveXObject(p);
dom.async = false;
dom.loadXML(fauxXhr.responseText);
result = dom;
} catch (e) {
return false;
}
return true;
});
}
}
return result; // DOMDocument
}
});
},
css2: {
"basic sanity checks": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['h3'] = query('h3').length;
result['#t'] = query('#t').length;
result['#bug'] = query('#bug').length;
result['#t h3'] = query('#t h3').length;
result['div#t'] = query('div#t').length;
result['div#t h3'] = query('div#t h3').length;
result['span#t'] = query('span#t').length;
result['.bogus'] = query('.bogus').length;
result['.bogus-scoped'] = query('.bogus', dom.byId('container')).length;
result['#bogus'] = query('#bogus').length;
result['#bogus-scoped'] = query('#bogus', dom.byId('container')).length;
result['#t div > h3'] = query('#t div > h3').length;
result['.foo'] = query('.foo').length;
result['.foo.bar'] = query('.foo.bar').length;
result['.baz'] = query('.baz').length;
result['#t > h3'] = query('#t > h3').length;
result['null'] = query(null).length;
return result;
}).then(function (results) {
assert.equal((results['h3']), 4);
assert.equal((results['#t']), 1);
assert.equal((results['#bug']), 1);
assert.equal((results['#t h3']), 4);
assert.equal((results['div#t']), 1);
assert.equal((results['div#t h3']), 4);
assert.equal((results['span#t']), 0);
assert.equal((results['.bogus']), 0);
assert.equal((results['.bogus-scoped']), 0);
assert.equal((results['#bogus']), 0);
assert.equal((results['#bogus-scoped']), 0);
assert.equal((results['#t div > h3']), 1);
assert.equal((results['.foo']), 2);
assert.equal((results['.foo.bar']), 1);
assert.equal((results['.baz']), 2);
assert.equal((results['#t > h3']), 3);
assert.equal((results['null']), 0);
});
},
"comma1": function () {
return this.get("remote")
.execute(function () {
return query('#baz,#foo,#t').length;
})
.then(function (result) {
assert.equal(result, 2);
});
},
"comma2": function () {
return this.get("remote")
.execute(function () {
return query('#foo,#baz,#t').length;
})
.then(function (result) {
assert.equal(result, 2);
});
},
"syntactic equivalents": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["#t > *"] = query('#t > *').length;
result[".foo > *"] = query('.foo > *').length;
return result;
})
.then(function (result) {
assert.equal(result["#t > *"], 12);
assert.equal(result[".foo > *"], 3);
});
},
"with a root, by ID": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['> *'] = query('> *', 'container').length;
result['> *, > h3'] = query('> *, > h3', 'container').length;
result['> h3'] = query('> h3', 't').length;
return result;
})
.then(function (result) {
assert.equal(result['> *'], 3);
assert.equal(result['> *, > h3'], 3);
assert.equal(result['> h3'], 3);
});
},
"compound queries": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['.foo, .bar'] = query('.foo, .bar').length;
result['.foo,.bar'] = query('.foo,.bar').length;
return result;
})
.then(function (result) {
assert.equal(result['.foo, .bar'], 2);
assert.equal(result['.foo,.bar'], 2);
});
},
"multiple class attribute": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['.foo.bar'] = query('.foo.bar').length;
result['.foo'] = query('.foo').length;
result['.baz'] = query('.baz').length;
return result;
})
.then(function (result) {
assert.equal(result['.foo.bar'], 1);
assert.equal(result['.foo'], 2);
assert.equal(result['.baz'], 2);
});
},
"case sensitivity": function () {
return this.get("remote")
.execute(function () {
return {
baz: [query('span.baz').length, query('sPaN.baz').length, query('SPAN.baz').length],
fooBar: query('.fooBar').length
};
})
.then(function (result) {
assert.deepEqual(result.baz, [1, 1, 1]);
// For quirks mode, case sensitivity is browser dependent, so querying .fooBar
// may return 1 or 2 entries. See #8775 and #14874 for details.
if (!/quirks/i.test(file)) {
assert.equal(result.fooBar, 1);
}
});
},
"attribute selectors": function () {
return this.get("remote")
.execute(function () {
return query('[foo]').length;
})
.then(function (result) {
assert.equal(result, 3);
});
},
"attribute substring selectors": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['[foo$=\"thud\"]'] = query('[foo$=\"thud\"]').length;
result['[foo$=thud]'] = query('[foo$=thud]').length;
result['[foo$=\"thudish\"]'] = query('[foo$=\"thudish\"]').length;
result['#t [foo$=thud]'] = query('#t [foo$=thud]').length;
result['#t [title$=thud]'] = query('#t [title$=thud]').length;
result['#t span[title$=thud ]'] = query('#t span[title$=thud ]').length;
result['[id$=\'55555\']'] = query('[id$=\'55555\']').length;
result['[foo~=\"bar\"]'] = query('[foo~=\"bar\"]').length;
result['[ foo ~= \"bar\" ]'] = query('[ foo ~= \"bar\" ]').length;
result['[foo|=\"bar\"]'] = query('[foo|=\"bar\"]').length;
result['[foo|=\"bar-baz\"]'] = query('[foo|=\"bar-baz\"]').length;
result['[foo|=\"baz\"]'] = query('[foo|=\"baz\"]').length;
return result;
})
.then(function (result) {
assert.equal(result['[foo$=\"thud\"]'], 1);
assert.equal(result['[foo$=thud]'], 1);
assert.equal(result['[foo$=\"thudish\"]'], 1);
assert.equal(result['#t [foo$=thud]'], 1);
assert.equal(result['#t [title$=thud]'], 1);
assert.equal(result['#t span[title$=thud ]'], 0);
assert.equal(result['[id$=\'55555\']'], 1);
assert.equal(result['[foo~=\"bar\"]'], 2);
assert.equal(result['[ foo ~= \"bar\" ]'], 2);
assert.equal(result['[foo|=\"bar\"]'], 2);
assert.equal(result['[foo|=\"bar-baz\"]'], 1);
assert.equal(result['[foo|=\"baz\"]'], 0);
});
},
"descendant selectors": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['> *'] = query('> *', 'container').length;
result['> [qux]'] = query('> [qux]', 'container').length;
result['> [qux][0].id'] = query('> [qux]', 'container')[0].id;
result['> [qux][1].id'] = query('> [qux]', 'container')[1].id;
result['>*'] = query('>*', 'container').length;
result['#bug[0].value'] = query('#bug')[0].value; // test id query doesn't match name
// suppress exception for known bug #18516; remove this code if that bug is fixed.
if(has("ie") <= 9 && has("quirks")){
result['#bug[0].value'] = "passed";
}
return result;
})
.then(function (result) {
assert.equal(result['> *'], 3, '> *');
assert.equal(result['> [qux]'], 2, '> [qux]');
assert.equal(result['> [qux][0].id'], "child1", '> [qux][0].id');
assert.equal(result['> [qux][1].id'], "child3", '> [qux][1].id');
assert.equal(result['>*'], 3, '>*');
assert.equal(result['#bug[0].value'], "passed", '#bug[0].value');
});
},
"bug 9071": function () {
// bug 9071
return this.get("remote")
.execute(function () {
var result = {};
result['t4 a'] = query('a', 't4').length;
result['t4 p a'] = query('p a', 't4').length;
result['t4 div p'] = query('div p', 't4').length;
result['t4 div p a'] = query('div p a', 't4').length;
result['t4 .subA'] = query('.subA', 't4').length;
result['t4 .subP .subA'] = query('.subP .subA', 't4').length;
result['t4 .subDiv .subP'] = query('.subDiv .subP', 't4').length;
result['t4 .subDiv .subP .subA'] = query('.subDiv .subP .subA', 't4').length;
return result;
})
.then(function (result) {
assert.equal(result['t4 a'], 2);
assert.equal(result['t4 p a'], 2);
assert.equal(result['t4 div p'], 2);
assert.equal(result['t4 div p a'], 2);
assert.equal(result['t4 .subA'], 2);
assert.equal(result['t4 .subP .subA'], 2);
assert.equal(result['t4 .subDiv .subP'], 2);
assert.equal(result['t4 .subDiv .subP .subA'], 2);
});
},
"failed scope arg": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['thinger *'] = query('*', 'thinger').length;
result['div#foo'] = query('div#foo').length;
return result;
})
.then(function (result) {
assert.equal(result['thinger *'], 0);
assert.equal(result['div#foo'], 0);
});
},
"escaping special characters with quotes": function () {
// http://www.w3.org/TR/CSS21/syndata.html#strings
// bug 10651
return this.get("remote")
.execute(function () {
var result = {};
result['option[value="a+b"]'] = query('option[value="a+b"]', "attrSpecialChars").length;
result['option[value="a~b"]'] = query('option[value="a~b"]', "attrSpecialChars").length;
result['option[value="a^b"]'] = query('option[value="a^b"]', "attrSpecialChars").length;
result['option[value="a,b"]'] = query('option[value="a,b"]', "attrSpecialChars").length;
return result;
})
.then(function (result) {
assert.equal(result['option[value="a+b"]'], 1);
assert.equal(result['option[value="a~b"]'], 1);
assert.equal(result['option[value="a^b"]'], 1);
assert.equal(result['option[value="a,b"]'], 1);
});
},
"selector with substring that contains equals sign - bug 7479": function () {
return this.get("remote")
.execute(function () {
return query("a[href*='foo=bar']", 'attrSpecialChars').length;
})
.then(function (result) {
assert.equal(result, 1);
});
},
"selector with substring that contains brackets - bug 9193, 11189, 13084": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['input[name="data[foo][bar]"]'] = query('input[name="data[foo][bar]"]', "attrSpecialChars").length;
result['input[name="foo[0].bar'] = query('input[name="foo[0].bar"]', "attrSpecialChars").length;
result['input[name="test[0]"]'] = query('input[name="test[0]"]', "attrSpecialChars").length;
return result;
})
.then(function (result) {
assert.equal(result['input[name="data[foo][bar]"]'], 1);
assert.equal(result['input[name="foo[0].bar'], 1);
assert.equal(result['input[name="test[0]"]'], 1);
});
},
"escaping special characters with backslashes": function () {
//http://www.w3.org/TR/CSS21/syndata.html#characters
// selector with substring that contains brackets (bug 9193, 11189, 13084)
// eval() converts 4 backslashes --> 1 by the time dojo.query() sees the string
return this.get("remote")
.execute(function () {
var result = {};
result['input[name=data\\[foo\\]\\[bar\\]]'] = query("input[name=data\\[foo\\]\\[bar\\]]", "attrSpecialChars").length;
result['input[name=foo\\[0\\]\\.bar]'] = query("input[name=foo\\[0\\]\\.bar]", "attrSpecialChars").length;
return result;
})
.then(function (result) {
assert.equal(result['input[name=data\\[foo\\]\\[bar\\]]'], 1);
assert.equal(result['input[name=foo\\[0\\]\\.bar]'], 1);
});
},
"crossDocumentQuery": function () {
return this.get("remote")
.execute(function () {
var result = {};
var t3 = window.frames["t3"];
var doc = iframe.doc(t3);
doc.open();
doc.write([
"<html><head>",
"<title>inner document</title>",
"</head>",
"<body>",
" <div id='st1'>",
" <h3>h3",
" <span>",
" span",
" <span>",
" inner",
" <span>",
" inner-inner",
" </span>",
" </span>",
" </span>",
" endh3",
" </h3>",
" </div>",
"</body>",
"</html>"
].join(""));
doc.close();
result["st1 h3"] = query('h3', dom.byId("st1", doc)).length;
// use a long query to force a test of the XPath system on FF. see bug #7075
result['st1 h3 > span > span > span'] = query('h3 > span > span > span', dom.byId("st1", doc)).length;
result['body.children[0] h3 > span > span > span'] = query('h3 > span > span > span', doc.body.children[0]).length;
return result;
})
.then(function (result) {
assert.equal(result['st1 h3'], 1);
assert.equal(result['st1 h3 > span > span > span'], 1);
assert.equal(result['body.children[0] h3 > span > span > span'], 1);
});
},
"escaping of ':' chars inside an ID": {
"silly_IDs1": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["silly:id::with:colons"] = document.getElementById("silly:id::with:colons");
result["#silly\\:id\\:\\:with\\:colons"] = query("#silly\\:id\\:\\:with\\:colons").length;
result["#silly\\~id"] = query("#silly\\~id").length;
return result;
})
.then(function (result) {
assert.isNotNull(result["silly:id::with:colons"], "getElementById");
assert.equal(result["#silly\\:id\\:\\:with\\:colons"], 1, "query(\"#silly\\:id\\:\\:with\\:colons\")");
assert.equal(result["#silly\\~id"], 1, "query(\"#silly\\~id\")");
});
}
},
"xml": function () {
return this.get("remote")
.execute(function () {
var doc = createDocument([
"<ResultSet>",
"<Result>One</Result>",
"<RESULT>Two</RESULT>",
"<result><nested>Three</nested></result>",
"<result>Four</result>",
"</ResultSet>"
].join(""));
var de = doc.documentElement;
// note: don't name structure members after elements because it gets corrupted on IE (webdriver bug)
return {
lower: query("result", de).length,
mixed: query("Result", de).length,
upper: query("RESULT", de).length,
nomatch1: query("resulT", de).length,
nomatch2: query("rEsulT", de).length
};
})
.then(function (result) {
assert.equal(result.lower, 2, "all lower");
assert.equal(result.mixed, 1, "mixed case");
assert.equal(result.upper, 1, "all upper");
assert.equal(result.nomatch1, 0, "no match 1");
assert.equal(result.nomatch2, 0, "no match 2");
});
},
"xml_attrs": function () {
var remote = this.get("remote");
if (/internet explorer/.test(remote.environmentType.browserName)) {
return this.skip("do not run in IE till bug #14880 is fixed");
}
return remote.execute(function () {
var doc = createDocument([
"<ResultSet>",
"<RESULT thinger='blah'>ONE</RESULT>",
"<RESULT thinger='gadzooks'><CHILD>Two</CHILD></RESULT>",
"</ResultSet>"
].join(""));
var de = doc.documentElement;
return {
RESULT: query("RESULT", de).length,
"RESULT[THINGER]": query("RESULT[THINGER]", de).length,
"RESULT[thinger]": query("RESULT[thinger]", de).length,
"RESULT[thinger=blah]": query("RESULT[thinger=blah]", de).length,
"RESULT > CHILD": query("RESULT > CHILD", de).length
};
})
.then(function (result) {
assert.equal(result["RESULT"], 2, "result elements");
assert.equal(result["RESULT[THINGER]"], 0, "result elements with attrs (wrong)");
assert.equal(result["RESULT[thinger]"], 2, "result elements with attrs");
assert.equal(result["RESULT[thinger=blah]"], 1, "result elements with attr value");
assert.equal(result["RESULT > CHILD"], 1, "Using child operator");
});
},
"sort": function () {
return this.get("remote")
.execute(function () {
var i = query("div");
// smoke test
i.sort(function (a, b) {
return 1;
});
return true;
})
.then(function (result) {
assert.isTrue(result);
});
},
"document_fragment": function () {
return this.get("remote")
.execute(function () {
var result = {};
var detachedDom = domConstruct.toDom("<i><u><a></a><b id='b'></b></u></i>");
var documentFragment = domConstruct.toDom("<i></i> <u><a></a><b id='b'></b></u>");
var detachedDom2 = domConstruct.toDom("<i><u><a></a><b></b></u></i>");
var documentFragment2 = domConstruct.toDom("<i></i> <u><a></a><b></b></u>");
result["#b detached"] = query("#b", detachedDom).length;
result["#b detached first child"] = query("#b", detachedDom.firstChild).length;
result["#b fragment"] = query("#b", documentFragment).length;
// In IE8 in quirks mode there is no text node on the document fragment
result["#b fragment child"] = query("#b", has('ie') === 8 && has("quirks") ?
documentFragment.childNodes[1] : documentFragment.childNodes[2]).length;
result["#b detached2"] = query("#b", detachedDom2).length;
result["#b fragment2"] = query("#b", documentFragment2).length;
return result;
})
.then(function (result) {
assert.equal(result["#b detached"], 1);
assert.equal(result["#b detached first child"], 1);
assert.equal(result["#b fragment"], 1);
assert.equal(result["#b fragment child"], 1);
assert.equal(result["#b detached2"], 0);
assert.equal(result["#b fragment2"], 0);
});
}
}
};
if (/css2.1|css3|acme/.test(selector)) {
tests["css2.1"] = function () {
return this.get("remote")
.execute(function () {
var result = {};
result["h1:first-child"] = query('h1:first-child').length;
result["h3:first-child"] = query('h3:first-child').length;
result[".foo+ span"] = query('.foo+ span').length;
result[".foo+span"] = query('.foo+span').length;
result[".foo +span"] = query('.foo +span').length;
result[".foo + span"] = query('.foo + span').length;
return result;
})
.then(function (result) {
// first-child
assert.equal(result["h1:first-child"], 1);
assert.equal(result["h3:first-child"], 2);
// + sibling selector
assert.equal(result[".foo+ span"], 1);
assert.equal(result[".foo+span"], 1);
assert.equal(result[".foo +span"], 1);
assert.equal(result[".foo + span"], 1);
});
};
}
if (/css3|acme/.test(selector)) {
tests["css3"] = {
"sub-selector parsing": function () {
return this.get("remote")
.execute(function () {
return query('#t span.foo:not(:first-child)').length;
})
.then(function (result) {
assert.equal(result, 1);
});
},
"~ sibling selector": function () {
return this.get("remote")
.execute(function () {
var result = {};
result[".foo~ span"] = query('.foo~ span').length;
result[".foo~span"] = query('.foo~span').length;
result[".foo ~span"] = query('.foo ~span').length;
result[".foo ~ span"] = query('.foo ~ span').length;
result["#foo~ *"] = query('#foo~ *').length;
result["#foo ~*"] = query('#foo ~*').length;
result["#foo ~*"] = query('#foo ~*').length;
result["#foo ~ *"] = query('#foo ~ *').length;
return result;
})
.then(function (result) {
assert.equal(result[".foo~ span"], 4);
assert.equal(result[".foo~span"], 4);
assert.equal(result[".foo ~span"], 4);
assert.equal(result[".foo ~ span"], 4);
assert.equal(result["#foo~ *"], 1);
assert.equal(result["#foo ~*"], 1);
assert.equal(result["#foo ~*"], 1);
assert.equal(result["#foo ~ *"], 1);
});
},
"nth-child tests": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["#t > h3:nth-child(odd)"] = query('#t > h3:nth-child(odd)').length;
result["#t h3:nth-child(odd)"] = query('#t h3:nth-child(odd)').length;
result["#t h3:nth-child(2n+1)"] = query('#t h3:nth-child(2n+1)').length;
result["#t h3:nth-child(even)"] = query('#t h3:nth-child(even)').length;
result["#t h3:nth-child(2n)"] = query('#t h3:nth-child(2n)').length;
result["#t h3:nth-child(2n+3)"] = query('#t h3:nth-child(2n+3)').length;
result["#t h3:nth-child(1)"] = query('#t h3:nth-child(1)').length;
result["#t > h3:nth-child(1)"] = query('#t > h3:nth-child(1)').length;
result["#t :nth-child(3)"] = query('#t :nth-child(3)').length;
result["#t > div:nth-child(1)"] = query('#t > div:nth-child(1)').length;
result["#t :nth-child(3)"] = query('#t :nth-child(3)').length;
result["#t > div:nth-child(1)"] = query('#t > div:nth-child(1)').length;
result["#t span"] = query('#t span').length;
result["#t > *:nth-child(n+10)"] = query('#t > *:nth-child(n+10)').length;
result["#t > *:nth-child(n+12)"] = query('#t > *:nth-child(n+12)').length;
result["#t > *:nth-child(-n+10)"] = query('#t > *:nth-child(-n+10)').length;
result["#t > *:nth-child(-2n+10)"] = query('#t > *:nth-child(-2n+10)').length;
result["#t > *:nth-child(2n+2)"] = query('#t > *:nth-child(2n+2)').length;
result["#t > *:nth-child(2n+4)"] = query('#t > *:nth-child(2n+4)').length;
result["#t> *:nth-child(2n+4)"] = query('#t> *:nth-child(2n+4)').length;
result["#t > *:nth-child(n-5)"] = query('#t > *:nth-child(n-5)').length;
result["#t >*:nth-child(n-5)"] = query('#t >*:nth-child(n-5)').length;
result["#t > *:nth-child(2n-5)"] = query('#t > *:nth-child(2n-5)').length;
result["#t>*:nth-child(2n-5)"] = query('#t>*:nth-child(2n-5)').length;
// function(){ doh.is(dom.byId('_foo'), result[".foo:nth-child(2)"][0], ".foo:nth-child(2)"); },
return result;
})
.then(function (result) {
// nth-child tests
assert.equal(result["#t > h3:nth-child(odd)"], 2, "#t > h3:nth-child(odd)");
assert.equal(result["#t h3:nth-child(odd)"], 3, "#t h3:nth-child(odd)");
assert.equal(result["#t h3:nth-child(2n+1)"], 3, "#t h3:nth-child(2n+1)");
assert.equal(result["#t h3:nth-child(even)"], 1, "#t h3:nth-child(even)");
assert.equal(result["#t h3:nth-child(2n)"], 1, "#t h3:nth-child(2n)");
assert.equal(result["#t h3:nth-child(2n+3)"], 1, "#t h3:nth-child(2n+3)");
assert.equal(result["#t h3:nth-child(1)"], 2, "#t h3:nth-child(1)");
assert.equal(result["#t > h3:nth-child(1)"], 1, "#t > h3:nth-child(1)");
assert.equal(result["#t :nth-child(3)"], 3, "#t :nth-child(3)");
assert.equal(result["#t > div:nth-child(1)"], 0, "#t > div:nth-child(1)");
assert.equal(result["#t span"], 7, "#t span");
assert.equal(result["#t > *:nth-child(n+10)"], 3, "#t > *:nth-child(n+10)");
assert.equal(result["#t > *:nth-child(n+12)"], 1, "#t > *:nth-child(n+12)");
assert.equal(result["#t > *:nth-child(-n+10)"], 10, "#t > *:nth-child(-n+10)");
assert.equal(result["#t > *:nth-child(-2n+10)"], 5, "#t > *:nth-child(-2n+10)");
assert.equal(result["#t > *:nth-child(2n+2)"], 6, "#t > *:nth-child(2n+2)");
assert.equal(result["#t > *:nth-child(2n+4)"], 5, "#t > *:nth-child(2n+4)");
assert.equal(result["#t> *:nth-child(2n+4)"], 5, "#t> *:nth-child(2n+4)");
assert.equal(result["#t > *:nth-child(n-5)"], 12, "#t > *:nth-child(n-5)");
assert.equal(result["#t >*:nth-child(n-5)"], 12, "#t >*:nth-child(n-5)");
assert.equal(result["#t > *:nth-child(2n-5)"], 6, "#t > *:nth-child(2n-5)");
assert.equal(result["#t>*:nth-child(2n-5)"], 6, "#t>*:nth-child(2n-5)");
// function(){ doh.is(dom.byId('_foo'), result[".foo:nth-child(2)"][0], ".foo:nth-child(2)"); },
});
},
":checked pseudo-selector": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["#t2 > :checked"] = query('#t2 > :checked').length;
result["#t2 > input[type=checkbox]:checked"] =
query('#t2 > input[type=checkbox]:checked')[0] === dom.byId('checkbox2');
result["#t2 > input[type=radio]:checked"] =
query('#t2 > input[type=radio]:checked')[0] === dom.byId('radio2');
result["#t2select option:checked"] = query('#t2select option:checked').length;
result["#radio1:disabled"] = query('#radio1:disabled').length;
result["#radio1:enabled"] = query('#radio1:enabled').length;
result["#radio2:disabled"] = query('#radio2:disabled').length;
result["#radio2:enabled"] = query('#radio2:enabled').length;
return result;
})
.then(function (result) {
assert.equal(result['#t2 > :checked'], 2);
assert.isTrue(result['#t2 > input[type=checkbox]:checked']);
assert.isTrue(result['#t2 > input[type=radio]:checked']);
// This :checked selector is only defined for elements that have the checked property, option elements are not specified by the spec (http://www.w3.org/TR/css3-selectors/#checked) and not universally supported
//assert.equal(result['#t2select option:checked'], 2);
assert.equal(result['#radio1:disabled'], 1);
assert.equal(result['#radio1:enabled'], 0);
assert.equal(result['#radio2:disabled'], 0);
assert.equal(result['#radio2:enabled'], 1);
});
},
":empty pseudo-selector": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["#t > span:empty"] = query('#t > span:empty').length;
result["#t span:empty"] = query('#t span:empty').length;
result["h3 span:empty"] = query('h3 span:empty').length;
result["h3 :not(:empty)"] = query('h3 :not(:empty)').length;
return result;
})
.then(function (result) {
assert.equal(result['#t > span:empty'], 4);
assert.equal(result['#t span:empty'], 6);
assert.equal(result['h3 span:empty'], 0);
assert.equal(result['h3 :not(:empty)'], 1);
});
}
};
}
if (selector == "acme") {
tests.acme = {
"Case insensitive class selectors - bug #8775, #14874": function () {
// Case insensitive class selectors (#8775, #14874).
// In standards mode documents, querySelectorAll() is case-sensitive about class selectors,
// but acme is case-insensitive for backwards compatibility.
return this.get("remote")
.execute(function () {
return query(".fooBar").length;
})
.then(function (result) {
assert.equal(result, 1);
});
},
"sub-selector parsing": function () {
// TODO: move this test to CSS3 section when #14875 is fixed
return this.get("remote")
.execute(function () {
return query('#t span.foo:not(span:first-child)').length;
})
.then(function (result) {
assert.equal(result, 1);
});
},
"special characters in attribute values without backslashes": function () {
// supported by acme but apparently not standard, see http://www.w3.org/TR/CSS21/syndata.html#characters
function attrSpecialCharsNoEscape() {
// bug 10651
return this.get("remote")
.execute(function () {
var result = {};
result["option[value=a+b]"] = query('option[value=a+b]', 'attrSpecialChars').length;
result["option[value=a~b]"] = query('option[value=a~b]', 'attrSpecialChars').length;
result["option[value=a^b]"] = query('option[value=a^b]', 'attrSpecialChars').length;
return result;
})
.then(function (result) {
assert.equal(result["option[value=a+b]"], 1, "value=a+b");
assert.equal(result["option[value=a~b]"], 1, "value=a~b");
assert.equal(result["option[value=a^b]"], 1, "value=a^b");
});
}
},
"implied * after > (non-standard syntax)": function () {
return this.get("remote")
.execute(function () {
var result = {};
result['#t >'] = query('#t >').length;
result['.foo >'] = query('.foo >').length;
result['>'] = query('>', 'container').length;
result['> .not-there'] = query('> .not-there').length;
result['#foo ~'] = query('#foo ~').length;
result['#foo~'] = query('#foo~').length;
return result;
})
.then(function (result) {
assert.equal(result['#t >'], 12);
assert.equal(result['.foo >'], 3);
assert.equal(result['>'], 3);
assert.equal(result['> .not-there'], 0);
assert.equal(result['#foo ~'], 1);
assert.equal(result['#foo~'], 1);
});
},
"implied * before and after + and ~ (non-standard syntax)": function () {
return this.get("remote")
.execute(function () {
var result = {};
result["+"] = query('+', 'container').length;
result["~"] = query('~', 'container').length;
return result;
})
.then(function (result) {
assert.equal(result['+'], 1);
assert.equal(result['~'], 3);
});
},
"check for correct document order": {
// not sure if this is guaranteed by css3, so putting in acme section
domOrder: function () {
return this.get("remote")
.execute(function () {
var result = {};
var inputs = query(".upperclass .lowerclass input");
result["notbug"] = inputs[0].id;
result["bug"] = inputs[1].id;
result["checkbox1"] = inputs[2].id;
result["checkbox2"] = inputs[3].id;
result["radio1"] = inputs[4].id;
result["radio2"] = inputs[5].id;
result["radio3"] = inputs[6].id;
return result;
})
.then(function (result) {
assert.equal(result["notbug"], "notbug");
assert.equal(result["bug"], "bug");
assert.equal(result["checkbox1"], "checkbox1");
assert.equal(result["checkbox2"], "checkbox2");
assert.equal(result["radio1"], "radio1");
assert.equal(result["radio2"], "radio2");
assert.equal(result["radio3"], "radio3");
});
},
// TODO: move to css2 section after #7869 fixed for lite engine (on IE)
xml_nthchild: function () {
return this.get("remote")
.execute(function () {
var doc = createDocument([
"<ResultSet>",
"<result>One</result>",
"<result>Two</result>",
"<result>Three</result>",
"<result>Four</result>",
"</ResultSet>"
].join("")
);
var de = doc.documentElement;
return query("result:nth-child(4)", de)[0].firstChild.data;
})
.then(function (result) {
assert.equal(result, "Four", "fourth child");
});
}
}
};
}
registerSuite(tests);
});
});
});