ullamlaboriosam
Version:
Lightweight and intuitive javascript library
1,756 lines (1,367 loc) • 87.7 kB
JavaScript
var expect = chai.expect;
// Whether or not to run the tests. When this is set to "false", then all of
// the tests for this function should fail
var work = true;
var wrap = function(cb){
cb();
}
// Check whether or not the element has a class
// - cls: the classes that should be checked
// - negate: whether or not the class should be present
// - root: the element to check (defaults to "base")
// hasClass('bla', true, 'ul')
function hasClass(cls, negate, root) {
root = root ? u(root) : base;
u().args(cls).forEach(function(cl){
expect(root.hasClass(cl)).to.equal(!negate);
});
return hasClass;
}
// Check that two objects are the same
// same({ a: 'hi' }, { a: 'hi' })
function same(a, b) {
expect(a).to.deep.equal(b);
return isFn;
}
// Chech whether or not something is a function
function isFn(fn) {
expect(typeof fn).to.equal('function');
return isFn;
}
// Quickly test the size of a selector and returns itself for chaining:
// size('.a', 2)('.b', 3)('.c', 1)
function size(sel, number) {
expect(u(sel).length).to.equal(number);
return size;
}
// Get a great list of classes for testing different configurations
function getListOfClasses(){
return [
// Strings
{ from: 'bla blu blo', it: 'a space-separated string' },
{ from: 'bla,blu,blo,', it: 'a comma-separated string' },
{ from: 'bla, blu, blo, ', it: 'a comma and space separated string' },
{ from: 'bla\n\tblu\n\tblo\n\t', it: 'a whitespace-separated string' },
// Single array
{ from: ['bla', 'blu', 'blo'], it: 'an array' },
{ from: ['bla blu ', 'blo '], it: 'a space-separated array' },
{ from: ['bla,blu,', 'blo,'], it: 'a comma-separated array' },
{ from: ['bla, blu, ', 'blo, '], it: 'a comma and space separated array' },
{ from: ['bla\n\tblu\n\t', 'blo\n\t'], it: 'a whitespace-separated array' },
// Nested
{ from: [['bla', 'blu'], 'blo'], it: 'an array' },
{ from: [['bla blu '], 'blo '], it: 'a space-separated array' },
{ from: [['bla,blu,'], 'blo,'], it: 'a comma-separated array' },
{ from: [['bla, blu, '], 'blo, '], it: 'a comma and space separated array' },
{ from: [['bla\n\tblu\n\t'], 'blo\n\t'], it: 'a whitespace-separated array' },
];
}
// Testing the main file
describe("u()", function() {
it("should be defined", function() {
expect(!!u).to.equal(true);
});
it("should be a function", function() {
expect(typeof u).to.equal("function");
});
it("can accept no argument", function() {
expect(typeof u()).to.equal('object', typeof u());
expect(u().length).to.equal(0);
});
it("can select by class", function() {
expect(u('.demo').length).to.equal(1);
});
it("can select by tag", function() {
expect(u('body').length).to.equal(1);
});
it("can select by id", function() {
expect(u('#demo').length).to.equal(1);
});
it("can select with css", function() {
expect(u('[id="demo"]').length).to.equal(1);
expect(u('.demo ul').length).to.equal(1);
});
it("can select a NodeList", function() {
expect(u(document.querySelectorAll('.demo li')).length).to.equal(3);
});
it("can select an html element", function() {
var object = u('.demo li').nodes[0];
expect(u(object).length).to.equal(1);
});
it("won't select a function", function() {
expect(u(function(){ return "test"; }).length).to.equal(0);
});
it("will select a random object", function() {
expect(u({ a: 'b', c: 'd' }).length).to.equal(1);
});
it("can select an Umbrella instance", function() {
var inst = u('.demo');
expect(u(inst).length).to.equal(1);
expect(u(inst)).to.equal(inst);
});
// it("accepts a function", function() {
// expect(u(function(){}).first()).to.equal(false);
// });
//
// it("generates some html", function() {
// expect(u(function(node, i){
// return "<li></li>"; }, 2).first()).to.equal('<li></li>');
// });
it("can use a context", function() {
var context = u('.demo li').nodes[0];
expect(u('a', context).length).to.equal(1);
});
it("can read the length", function() {
expect(u('a').nodes.length).to.equal(u('a').length);
});
describe("performance tests", function(){
function performance(callback, times){
var init = new Date().getTime();
for (var i = 0; i < times; i++) {
callback(i);
}
return new Date().getTime() - init;
}
// Generate a big and varied 100 element table
before(function(){
performance(function(i){
u('.performance').append('<tr class="ro"><td id="idn' + i + '"></td><td class="tabletest"></td><td></td><td></td></tr>');
}, 1000);
});
after(function(){
u('.performance').remove();
});
it("simple select by class 10.000/second", function() {
uTime = performance(function(){
u('.demo');
}, 1000);
console.log(' - u: ' + uTime + 'ms');
expect(uTime).to.be.below(100, uTime + ' ms');
});
it("select by class is comparable to jquery (50% margin)", function() {
size('.demo', 1);
var uTime = performance(function(){
u('.demo');
}, 5000);
var $Time = performance(function(){
$('.demo');
}, 5000);
console.log(' - u: ' + uTime + 'ms $: ' + $Time + 'ms');
expect(uTime).to.be.below($Time * 1.5, uTime + ' ms');
});
it("vs jquery: class selector (50% margin)", function() {
size('.tabletest', 1000);
var uTime = performance(function(){
u('.tabletest');
}, 100);
var $Time = performance(function(){
$('.tabletest');
}, 100);
console.log(' - u: ' + uTime + 'ms $: ' + $Time + 'ms');
expect(uTime).to.be.below($Time * 1.5, uTime + ' ms');
});
it("vs jquery: complex selector (50% margin)", function() {
size('table td:first-child', 1000);
var uTime = performance(function(){
u('table td:first-child');
}, 50);
var $Time = performance(function(){
$('table td:first-child');
}, 50);
console.log(' - u: ' + uTime + 'ms $: ' + $Time + 'ms');
expect(uTime).to.be.below($Time * 1.5, uTime + ' ms');
});
it("vs jquery: jquery optimized vs raw umbrella (50% margin)", function() {
size(".ro > *", 4000);
var uTime = performance(function(){
u(".ro > *");
}, 50);
var $Time = performance(function(){
$(".ro > *");
}, 50);
console.log(' - u: ' + uTime + 'ms $: ' + $Time + 'ms');
expect(uTime).to.be.below($Time * 1.5, uTime + ' ms');
});
});
});
var listOfClasses = getListOfClasses();
describe(".addClass()", function() {
beforeEach(function(){
base.removeClass('bla blu blo');
hasClass('bla blu blo', true);
});
afterEach(function(){
base.removeClass('bla blu blo');
hasClass('bla blu blo', true);
});
it("should be defined", function() {
isFn(work ? base.addClass : false);
});
it("can be called empty", function() {
base.addClass();
base.addClass("");
base.addClass([]);
base.addClass("","");
base.addClass(" ");
if (!work) throw "Forced failure";
});
it("can be concatenated", function() {
if (work) base.addClass('bla').addClass('blu');
hasClass('bla')('blu');
});
it("returns the same instance", function() {
var inst = false;
if (work) inst = base.addClass('bla,blu');
same(base, inst);
});
it("adds a single class", function() {
if (work) base.addClass('bla');
hasClass('bla');
});
describe("single argument", function(){
listOfClasses.forEach(function(part){
it("accepts " + part.it, function(){
if (work) base.addClass(part.from);
hasClass('bla blu blo');
});
});
});
describe("single function argument uses the return value", function(){
listOfClasses.forEach(function(part){
it("accepts as a return value " + part.it, function(){
if (work) base.addClass(function() { return part.from; });
hasClass('bla blu blo');
});
});
});
describe("multiple functions uses the return value", function(){
function add(arg){ return function(){ return arg; }; }
listOfClasses.forEach(function(part){
it("accepts as a return value " + part.it, function(){
if (work) base.addClass(add(part.from), add("bli"));
hasClass('bla blu blo bli');
});
});
});
describe("several arguments", function(){
listOfClasses.filter(function(part){
return Array.isArray(part.from);
}).forEach(function(part){
it("used .apply() with " + part.it, function(){
if (work) base.addClass.apply(base, part.from);
hasClass('bla blu blo');
});
});
});
describe("callback uses the arguments", function(){
// Testing the main file
function addTest(node, i){
return 'test' + i;
}
it("adds classes with callback", function(){
if (work) base.addClass(addTest);
hasClass('test0');
base.removeClass('test0');
expect(base.hasClass('test0')).to.equal(false);
});
it("adds many classes with callback", function(){
if (work) base.find('li').addClass(addTest);
base.find('li').each(function(node, i){
hasClass('test' + i, false, node);
u(node).removeClass('test' + i);
});
});
});
});
// Testing the main file
describe(".after(html)", function() {
//var work = false;
// Default callback for the tests
function callback(cl){
return '<a class="bla ' + cl + '">Link</a>';
}
beforeEach(function(){
expect(u('.bla').length).to.equal(0);
});
afterEach(function(){
u('.bla').remove();
});
it("should be a function", function() {
expect(work ? typeof base.after : false).to.equal('function');
});
it("can add content in the right place", function() {
if (work) base.after('<a class="bla">Link</a>');
size('.bla', 1)('.base + .bla', 1);
});
it("accepts a callback that will be called once", function(){
if (work) base.after(callback);
size('.bla', 1)('.base + .bla', 1);
});
it("accepts a single parameter", function(){
if (work) base.after(callback, ['a']);
size('.base + .bla.a', 1);
});
it("can add as many as the array", function(){
if (work) base.after(callback, ['a', 'b']);
expect(base.html().match('function')).to.equal(null);
size('.base ~ .bla', 2)('.base ~ .bla.a', 1)('.base ~ .bla.b', 1);
size('.base + .bla.a + .bla.b', 1);
});
});
// Testing the main file
describe(".ajax(done, before)", function() {
it("should be defined", function() {
expect(typeof base.ajax).to.equal('function');
});
it("works even if empty", function() {
// This is needed to make sure that the previous one is cleared
setTimeout(function(){
u('form.login').ajax();
u('form.login').trigger('submit');
setTimeout(function(){ u('form.login').off('submit'); }, 100);
}, 110);
});
it("calls before", function(next) {
setTimeout(function(){
u('form.login').ajax(function(err, body, xhr){
same(this.nodeName, 'FORM');
same(!!xhr, true);
next();
});
u('form.login').trigger('submit');
// SetTimeout is needed not to interrupt te current event
setTimeout(function(){ u('form.login').off('submit'); }, 100);
}, 110);
});
});
// Testing the main file
describe(".append(html)", function() {
// Default callback for the tests
function callback(cl){
return '<a class="bla ' + cl + '">Link</a>';
}
beforeEach(function(){
expect(u('.bla, .blu').length).to.equal(0);
});
afterEach(function(){
// Just in case it stringifies the callback
expect(base.html().match('function')).to.equal(null);
u('.bla, .blu').remove();
});
it("should be a function", function() {
expect(typeof base.append).to.equal('function');
});
it("can be called empty", function() {
base.append();
});
it("can be called with empty string", function() {
base.append("");
});
it("a function looping data has right footprint", function() {
base.append(function(value, index, node, j){
if (['a', 'b'].indexOf(value) === -1) throw new Error("Not an element");
if (value === 'a') same(index, 0);
if (value === 'b') same(index, 1);
same(node, base.first());
same(j, 0)
}, ['a', 'b']);
});
it("a function looping a number has right footprint", function() {
var iterations = 0;
base.append(function(value, index, node, j){
if ([0, 1].indexOf(value) === -1) throw new Error("Not an element");
if (value === 0) same(index, 0);
if (value === 1) same(index, 1);
same(node, base.first());
same(j, 0);
iterations++;
}, 2);
same(iterations, 2);
});
// HTML
describe("HTML string", function(){
it("can add a link", function() {
base.append('<a class="bla">Link</a>');
size('.base > .bla', 1);
});
it("can add sibling links", function() {
base.append('<a class="bla">Link</a><a class="bla">Link</a>');
size('.base > .bla', 2);
});
it("can add nested content", function() {
base.append('<strong class="bla"><a>Link</a></strong>');
size('.base > .bla > a', 1);
});
it("can append a table row", function() {
u('table.tbl').append('<tr><td>Hi</td></tr>');
});
it("can add just text", function() {
var frag = u('<div>').append('Hello world!\n');
same(frag.html(), 'Hello world!\n');
});
});
describe("HTML string looped with array", function(){
it("insert two links", function() {
base.append('<a class="bla">Link</a>', ['a', 'b']);
size('.base > .bla', 2)('.base > .bla:last-child', 1);
});
it("can add nested content", function() {
base.append('<strong class="bla"><a>Link</a></strong>', ['a', 'b']);
size('.base > .bla > a', 2);
});
it("can append simple text", function() {
var frag = u('<div>').append('Hello!\n', ['a', 'b']);
same(frag.html(), 'Hello!\nHello!\n');
});
});
// Callback
describe("Callback", function(){
it("can add a link", function() {
base.append(function(){ return '<a class="bla">Link</a>'; });
size('.base > .bla', 1)('.base > .bla:last-child', 1);
});
it("can add sibling links", function() {
base.append(function(){ return '<a class="bla">Link</a><a class="bla">Link</a>'; });
size('.base > .bla', 2)('.base > .bla:last-child', 1);
});
it("can add nested content", function() {
base.append(function(){ return '<strong class="bla"><a>Link</a></strong>'; });
size('.base > .bla > a', 1);
});
it("can add just text", function() {
var frag = u('<div>').append(function(){ return 'Hello world!\n'; });
same(frag.html(), 'Hello world!\n');
});
});
describe("Callback looped with array", function(){
it("can add sibling links", function() {
base.append(function(v){ return '<a class="bla">Link</a>'; }, ['a', 'b']);
size('.base > .bla', 2)('.base > .bla:last-child', 1);
});
it("can add nested content", function() {
base.append(function(){ return '<strong class="bla"><a>Link</a></strong>'; }, ['a', 'b']);
size('.base > .bla > a', 2);
});
it("can add just text", function() {
var frag = u('<div>').append(function(){ return 'Hello world!\n'; }, ['a', 'b']);
same(frag.html(), 'Hello world!\nHello world!\n');
});
it("can add content with a callback and data", function() {
base.append(callback, ['a', 'b']);
size('.base > .bla', 2)('.base > .bla.a', 1)('.base > .bla.b', 1);
size('.bla.a + .bla.b', 1)('.bla.b + .bla.a', 0)('.base > .bla.b:last-child', 1);
});
});
describe("Umbrella instance", function(){
it("Accepts a simple one", function(){
base.append(u('<div class="bla"></div>'));
size('.base > .bla', 1)('.base > .bla:last-child', 1);
});
it("Keeps the events when appending", function(done){
base.append(u('<div class="bla">').on('click', function(){ done(); }));
size('.base > .bla', 1)('.base > .bla:last-child', 1);
u('.base .bla').trigger('click');
});
it("Clones multiple events when appending", function(done){
base.append(u('<div class="bla">').on('click touch', function(){ done(); }));
size('.base > .bla', 1)('.base > .bla:last-child', 1);
u('.base .bla').trigger('touch');
});
});
it("can generate some text", function(){
var list = u("<div>");
if (work) list.append(function(n){ return n + "\n" }, ['a', 'b']);
expect(list.children().length).to.equal(0);
expect(list.html()).to.equal('a\nb\n');
});
it("can generate some text with number", function(){
var list = u("<div>");
if (work) list.append(function(n){ return n + "\n" }, 2);
expect(list.children().length).to.equal(0);
expect(list.html()).to.equal('0\n1\n');
});
it("isn't called any time with 0", function(){
u('<div>').append(function(n){ throw new Error("Shouldn't be called"); }, 0);
});
// Node
it("can append an html node", function() {
base.append(u('<div class="bla">').first());
size('.bla', 1);
});
it("should append supplied html to each targeted element and not only the last instance", function() {
base.append(u('<span class="test-span"></span><span class="test-span"></span><span class="test-span"></span><span class="test-span"></span>'));
base.append(u('<a class="append-me"></a>'));
u(".test-span").append(u(".append-me"));
size(".test-span .append-me", 4);
});
});
describe(".args(arguments)", function() {
it("should be defined", function() {
expect(typeof u().args).to.equal('function');
});
it("accepts zero parameters", function(){
expect(u().args()).to.deep.equal([]);
});
it("accepts falsy", function(){
expect(u().args(null)).to.deep.equal([]);
expect(u().args(false)).to.deep.equal([]);
expect(u().args(undefined)).to.deep.equal([]);
expect(u().args("")).to.deep.equal([]);
expect(u().args([])).to.deep.equal([]);
});
it("doesn't accept two parameters", function(){
expect(u().args('a', 'b')).to.deep.equal(['a']);
});
it("accepts an umbrella instance", function(){
expect(u().args(u(['a', 'b']))).to.deep.equal(['a', 'b']);
expect(u().args(u(['a', 'b']).nodes)).to.deep.equal(['a', 'b']);
});
describe("works with a single string", function(){
it("single string", function(){
expect(u().args('a')).to.deep.equal(['a']);
});
it("splits a string with space", function(){
expect(u().args('a b ')).to.deep.equal(['a', 'b']);
});
it("splits a string with comma", function(){
expect(u().args('a,b,')).to.deep.equal(['a', 'b']);
});
it("splits a string with space and comma", function(){
expect(u().args('a, b, ')).to.deep.equal(['a', 'b']);
});
it("splits a string with enter", function(){
expect(u().args('a\nb\t')).to.deep.equal(['a', 'b']);
});
});
describe("works with different arrays", function(){
it("single element", function(){
expect(u().args(['a'])).to.deep.equal(['a']);
});
it("single element", function(){
expect(u().args(['a', 'b', 'c'])).to.deep.equal(['a', 'b', 'c']);
});
it("splits a string with space", function(){
expect(u().args(['a b', 'c d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with comma", function(){
expect(u().args(['a,b', 'c,d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with space and comma", function(){
expect(u().args(['a, b', 'c, d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with whitespaces", function(){
expect(u().args(['a\nb', 'c\td'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
});
describe("works with a function", function(){
it("single element", function(){
expect(u().args(['a'])).to.deep.equal(['a']);
});
it("single element", function(){
expect(u().args(['a', 'b', 'c'])).to.deep.equal(['a', 'b', 'c']);
});
it("splits a string with space", function(){
expect(u().args(['a b', 'c d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with comma", function(){
expect(u().args(['a,b', 'c,d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with space and comma", function(){
expect(u().args(['a, b', 'c, d'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
it("splits a string with whitespaces", function(){
expect(u().args(['a\nb', 'c\td'])).to.deep.equal(['a', 'b', 'c', 'd']);
});
});
});
describe(".array()", function() {
it("should be defined", function() {
expect(typeof base.array).to.equal('function');
});
it("empty gives an error", function(){
same(base.array(), [base.html()]);
});
it("can loop as each()", function() {
u([0, 1, 2, 3]).array(function(node, i){
expect(node).to.equal(i);
});
});
it("can loop a real element", function() {
base.array(function(node, i){
expect(u(node).hasClass('base')).to.equal(true);
expect(i).to.equal(0);
});
});
it("can remove an element", function() {
var final = u([1, 2, 3, 4]).array(function(node, i){
if (i !== 0) return node;
});
expect(final.length).to.equal(3);
});
it("can remove several elements", function() {
var final = u([1, 2, 3, 4]).array(function(node, i){
if (i >= 3) return node;
});
expect(final.length).to.equal(1);
});
it("can add an element", function() {
var final = u([1, 2, 3, 4]).array(function(node, i){
return i === 0 ? [node, 'a'] : node;
});
expect(final.length).to.equal(5);
});
it("can add an many elements", function() {
var final = u([1, 2, 3, 4]).array(function(node, i){
return [node + 'a', node + 'b', node + 'c'];
});
expect(final.length).to.equal(12);
});
it("has the right this", function(){
u(['a', 'b']).array(function(node, i){
expect(this instanceof u).to.equal(true);
});
});
it("returns a simple array", function(){
var ret = u(['a', 'b']).array(function(){});
expect(Array.isArray(ret)).to.equal(true);
});
});
// Testing the main file
describe(".attr(name, value)", function() {
afterEach(function(){
base.first().removeAttribute('title');
expect(!base.attr('title')).to.equal(true);
});
it("should be a function", function() {
expect(typeof base.attr).to.equal('function');
});
it("can add an attribute with two params", function() {
base.attr('title', 'Hello');
expect(base.attr('title')).to.equal('Hello');
});
it("can remove an attribute with two params", function() {
base.attr('title', 'Hello').attr('title', '');
expect(base.attr('title')).to.equal('');
});
it("can add an attribute with an object", function() {
base.attr({title: 'Hello'});
expect(base.attr('title')).to.equal('Hello');
});
it("can read the first element attribute", function() {
base.first().setAttribute('title', 'Hello');
expect(base.attr('title')).to.equal('Hello');
});
it("can be called with no nodes", function() {
expect(u('dfsdf').attr('title')).to.equal('');
});
});
// Testing the main file
describe(".before(html)", function() {
// Default callback for the tests
function callback(cl){
return '<a class="bla ' + cl + '">Link</a>';
}
beforeEach(function(){
expect(u('.bla').length).to.equal(0);
});
afterEach(function(){
u('.bla').remove();
});
it("should be a function", function() {
expect(typeof base.after).to.equal('function');
});
it("can add content in the right place", function() {
base.before('<a class="bla">Link</a>');
expect(u('.bla').length).to.equal(1);
expect(base.parent().find('.base, .bla').length).to.equal(2);
expect(base.parent().find('.bla ~ .base').length).to.equal(1);
});
it("second parameter defaults to ''", function(){
if (work) base.before(callback);
expect(base.html().match('function')).to.equal(null);
size('.bla', 1)('.bla + .base', 1);
});
it("can add a single one", function(){
if (work) base.before(callback, ['a']);
expect(base.html().match('function')).to.equal(null);
size('.bla', 1)('.bla.a', 1)('.bla.a + .base', 1);
});
it("can add as many as the array", function(){
if (work) base.before(callback, ['a', 'b']);
expect(base.html().match('function')).to.equal(null);
size('.bla', 2)('.bla.a', 1)('.bla.b', 1)('.bla.a + .bla.b + .base', 1);
});
});
// Testing the main file
describe(".children(selector)", function() {
afterEach(function(){
// A previous bug that would change the inner of the original reference
expect(base.length).to.equal(1);
});
it("should be a function", function() {
expect(typeof base.children).to.equal('function');
});
it("can select the children of ul", function() {
expect(base.find('ul').children().length).to.equal(3);
});
it("can filter the children", function() {
expect(base.find('ul').children(':first-child').length).to.equal(1);
});
it("okay with no children", function() {
expect(base.find('ul').children('.nonexist').length).to.equal(0);
});
});
// Testing the main file
describe(".clone(options)", function() {
afterEach(function(){
u('.container').remove();
});
describe("clone() nodes without events", function() {
beforeEach(function() {
base.append('<div class="container">\
<div class="testClone1">Hello</div>\
<div class="cloneDestination">Goodbye</div>\
</div>');
});
it("should be a function", function() {
isFn(base.clone);
});
it("should clone a single simple node", function() {
u('.cloneDestination').append(u('.testClone1'));
size('.container > .testClone1', 1);
size('.cloneDestination > .testClone1', 1);
size('.testClone1', 2);
expect(u('.cloneDestination > .testClone1').text()).to.eq('Hello');
});
it("should clone nested nodes", function() {
u('.testClone1').append('<div class="testClone2">Hi</div>');
size('.container > .testClone1 > .testClone2', 1);
expect(u('.testClone2').text()).to.eq('Hi');
});
});
describe("clone() nodes with events", function() {
beforeEach(function() {
base.append('<div class="container">\
<div class="testClone1">Hello</div>\
<div class="testClone2">\
<div class="testCloneWithEvents1">\
click, touch, etc\
</div>\
</div>\
<div class="cloneDestination"></div>\
</div>');
});
it("should clone a node and its events by default", function(done) {
u('<div>').on('click', function(e){
u(e.target).off('click');
done();
}).clone().trigger('click').trigger('click');
});
it("should clone nested nodes and their events by default", function(done) {
u('.testCloneWithEvents1').on('click', function() { done(); });
u('.cloneDestination').append(u('.testClone2'));
u('.cloneDestination > .testClone2 > .testCloneWithEvents1').trigger('click');
});
});
describe("clone() form elements", function() {
before(function() {
u('form.clone [type=text]').first().value = 'test input';
u('form.clone [type=checkbox]').first().checked = true;
u('form.clone [type=radio]').first().checked = true;
u('form.clone select').first().value = 'b';
u('form.clone textarea').first().value = 'test textarea';
});
afterEach(function(){
u('.destination').html("");
});
it("has the correct values initially", function(){
expect(u('form.clone [type=text]').first().value).to.equal('test input', 'beforeClone');
expect(u('form.clone [type=checkbox]').first().checked).to.equal(true, 'beforeClone');
expect(u('form.clone [type=radio]').first().checked).to.equal(true, 'beforeClone');
expect(u('form.clone select').first().value).to.equal('b', 'beforeClone');
expect(u('form.clone textarea').first().value).to.equal('test textarea', 'beforeClone');
});
it ("clones a full form correctly", function(){
u('.destination').append(u('form.clone'));
expect(u('.destination [type=text]').length).to.equal(1);
expect(u('.destination [type=text]').first().value).to.equal('test input');
expect(u('.destination [type=checkbox]').first().checked).to.equal(true);
expect(u('.destination [type=radio]').first().checked).to.equal(true);
expect(u('.destination select').first().value).to.equal('b');
expect(u('.destination textarea').first().value).to.equal('test textarea');
});
it ("should clone a text input and its value by default", function() {
u('.destination').append(u('form.clone [type=text]'));
expect(u('.destination [type=text]').first().value).to.eq('test input');
});
it ("should clone a checkbox input and its value by default", function() {
u('.destination').append(u('form.clone [type=checkbox]'));
expect(u('.destination [type=checkbox]').first().checked).to.eq(true);
});
it ("should clone a radio input and its value by default", function() {
u('.destination').append(u('form.clone [type=radio]'));
expect(u('.destination [type=radio]').first().checked).to.eq(true);
});
it ("should clone a textarea input and its value by default", function() {
u('.destination').append(u('form.clone textarea'));
expect(u('.destination textarea').first().value).to.eq('test textarea');
});
it ("should clone a select input and its value by default", function() {
u('.destination').append(u('form.clone select'));
expect(u('.destination select').first().value).to.eq('b');
});
});
describe(".clone() and node data attributes", function() {
beforeEach(function() {
base.append('<div class="container"><div class="testCloneData" data-foo="bar"></div><div class="destination"></div></div>');
});
it("should clone node data attributes", function() {
u('.destination').append(u('.testCloneData'));
expect(u('.destination .testCloneData').data('foo')).to.eq('bar');
});
});
});
// Testing the main file
describe(".closest(selector)", function() {
afterEach(function(){
// A previous bug that would change the inner of the original reference
expect(base.length).to.equal(1);
});
it("should be a function", function() {
expect(typeof base.closest).to.equal('function');
});
it("can select the children of ul", function() {
expect(base.find('li').closest('ul').length).to.equal(1);
});
it("is okay with no ancestors", function() {
expect(base.closest('.nonexist').length).to.equal(0);
});
});
// Testing the main file
describe(".data(name, value)", function() {
it("should be a function", function() {
expect(typeof base.data).to.equal('function');
});
it("can add an attribute with two params", function() {
base.data('title', 'Hello');
expect(base.data('title')).to.equal('Hello');
base.first().removeAttribute('data-title');
expect(!base.data('title')).to.equal(true);
});
it("can add an attribute with an object", function() {
base.data({title: 'Hello'});
expect(base.data('title')).to.equal('Hello');
});
it("can read the first element attribute", function() {
base.first().setAttribute('data-title', 'Hello');
expect(base.data('title')).to.equal('Hello');
});
it("can be called with no nodes", function() {
expect(u('dfsdf').data('title')).to.equal('');
});
});
describe(".each(function(){})", function() {
it("should be defined", function() {
expect(typeof base.each).to.equal('function');
});
it("empty gives an error", function(done){
try {
u([0, 1, 2]).each();
} catch (e) {
return done();
}
throw "Shouldn't get here";
});
it("can loop", function() {
u([0, 1, 2, 3]).each(function(node, i){
expect(node).to.equal(i);
});
u([3, 4, 5, 6]).each(function(node, i){
expect(node).to.equal(i + 3);
});
});
it("can loop a real element", function() {
base.each(function(node, i){
expect(u(node).hasClass('base')).to.equal(true);
expect(i).to.equal(0);
});
});
it("has the right this", function(){
u(['a', 'b']).each(function(node, i){
expect(this instanceof u).to.equal(true);
});
});
it("returns an umbrella object", function(){
var ret = u(['a', 'b']).each(function(){});
expect(ret instanceof u).to.equal(true);
});
});
describe(".eacharg([], function(){})", function() {
it("should be defined", function() {
expect(typeof base.each).to.equal('function');
});
it("no data, everything is is okay", function(){
base.eacharg();
base.eacharg("");
base.eacharg("", function(){});
base.eacharg(false);
base.eacharg(false, function(){});
base.eacharg(undefined);
base.eacharg(undefined, function(){});
base.eacharg(function(){ return false; });
base.eacharg(function(){ return false; }, function(){});
});
it("only first arguments gives an error", function(){
expect(base.eacharg.bind(base, ["a"])).to.throw();
});
it("has the right this", function(){
u(['a', 'b']).eacharg(['a'], function(node, arg){
expect(this instanceof u).to.equal(true);
});
});
it("returns an umbrella object", function(){
var ret = u(['a', 'b']).eacharg(['a'], function(){});
expect(ret instanceof u).to.equal(true);
});
// STRING
describe('loops over an string', function(){
it("accepts commas as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg('A,B,', function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts space as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg('A B ', function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts commas and spaces as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg('A, B, ', function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts other whitespace as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg('A\nB\n', function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
});
// ARRAY
describe("loops over an array", function(){
it("accepts an array of elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(['A', 'B', ''], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts an array with space-separated elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(['A B '], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts an array with comma-separated elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(['A,B,'], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts an array with comma and space separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(['A, B, '], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts an array with other whitespace as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(['A\nB\n'], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
it("accepts an array with a combination", function() {
var values = ['aA', 'aB', 'aC', 'bA', 'bB', 'bC'];
u(['a', 'b']).eacharg(['A, B', 'C, '], function(node, arg){
expect(node + arg).to.equal(values.shift());
});
});
});
// FUNCTION
describe("loops over a function return", function(){
var called = false;
beforeEach(function(){
called = false;
});
it("accepts commas as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return 'A,B,'; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts space as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return 'A B '; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts commas and spaces as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return 'A, B, '; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts other whitespace as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return 'A\nB\n'; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array of elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return ['A', 'B', '']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array with space-separated elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return ['A B ']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array with comma-separated elements", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return ['A,B,']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array with comma and space separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return ['A, B, ']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array with other whitespace as separation", function() {
var values = ['aA', 'aB', 'bA', 'bB'];
u(['a', 'b']).eacharg(function(){ return ['A\nB\n']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
it("accepts an array with a combination", function() {
var values = ['aA', 'aB', 'aC', 'bA', 'bB', 'bC'];
u(['a', 'b']).eacharg(function(){ return ['A, B', 'C, ']; }, function(node, arg){
expect(node + arg).to.equal(values.shift());
called = true;
});
expect(called).to.equal(true);
});
});
});
// Testing the main file
describe(".empty()", function() {
beforeEach(function() {
base.append('\
<div class="empty-test"> \
<p></p> \
<p></p> \
</div> \
');
expect(u('.empty-test').length).to.equal(1);
expect(u('.empty-test p').length).to.equal(2);
});
afterEach(function() {
u('.empty-test').remove();
});
it("should be defined", function() {
expect(typeof base.empty).to.equal('function');
});
it("can be called even without any node", function() {
expect(u('.empty-test div').length).to.equal(0);
u('.empty-test div').empty();
});
it("will clean text-only nodes", function() {
u('.empty-test').html('Hello world');
expect(u('.empty-test').html()).to.equal('Hello world');
u('.empty-test').empty();
expect(u('.empty-test').html()).to.equal('');
});
it("will clean mixed nodes", function() {
u('.empty-test').html('Hello world!<p>How <strong>are you</strong>?</p>');
u('.empty-test').empty();
expect(u('.empty-test').html()).to.equal('');
});
it("should return an instance of umbrella with the empty nodes", function() {
var result = u('.empty-test').empty();
expect(result).to.be.instanceof(u);
expect(result.nodes).to.have.length(1);
expect(result.attr('class')).to.equal('empty-test');
});
it("empty element", function() {
u('.empty-test').empty();
expect(u('.empty-test p').length).to.equal(0);
});
});
// Testing the main file
describe(".filter(selector)", function() {
it("should be defined", function() {
expect(typeof base.filter).to.equal('function');
});
it("can be called empty", function() {
base.filter();
base.filter("");
});
it("stays the same", function() {
expect(base.filter('.base').length).to.equal(1);
});
it("gets only one", function() {
expect(base.find('a').filter('#world').length).to.equal(1);
});
it("accepts a function", function() {
expect(base.filter(function(){ return true; }).length).to.equal(1);
expect(base.filter(function(){ return false; }).length).to.equal(0);
});
it("accepts an object", function() {
expect(base.filter(base).length).to.equal(1);
expect(base.filter(u('.bla')).length).to.equal(0);
});
it("returns the same if called empty", function() {
expect(base.find('.not-test li').filter().length).to.equal(base.find('.not-test li').length);
expect(base.find('.not-test li').filter('').length).to.equal(base.find('.not-test li').length);
expect(base.find('.not-test li').filter(null).length).to.equal(base.find('.not-test li').length);
expect(base.find('.not-test li').filter(undefined).length).to.equal(base.find('.not-test li').length);
expect(base.find('.not-test li').filter(false).length).to.equal(base.find('.not-test li').length);
});
});
// Testing the main file
describe(".find(selector)", function() {
it("should be a function", function() {
expect(typeof base.find).to.equal('function');
});
it("can be empty and it selects all", function() {
expect(base.find().length).to.equal(base.find('*').length);
});
it("can select the list ul", function() {
expect(base.find('ul').length).to.equal(1);
});
it("cannot select body", function() {
expect(base.find('body').length).to.equal(0);
});
it("doesn't select duplicates", function(){
expect(u("*").find('.brand a').length).to.equal(1);
});
});
// Testing the main file
describe(".first()", function() {
it("should be a function", function() {
expect(typeof base.first).to.equal('function');
});
it("the first element is an HTML element", function() {
expect(base.find("li").first().nodeType).to.equal(1);
});
it("can get the first li and it's a LI", function() {
expect(base.find("li").first().nodeName).to.equal('LI');
});
});
// Testing the main file
describe("Function ajax(done, before)", function() {
// Generate the url (allow for testing locally)
function url(frag){
frag = frag || '';
var url = window.location.href;
if (!/^http/.test(window.location.href)) {
url = 'http://localhost:3000';
}
if (/tests(\/)?$/.test(url)) {
url = url.replace(/tests(\/)?/, '');
}
return url.replace(/\/$/, '') + '/' + frag.replace(/^\//, '');
}
function ifActive(cb){
return function(done){
ajax(url('/active'), {}, function(error, data){
if (!error && data === 'active') {
cb(done);
} else {
u('.noserver').html("Note: there is no server running, so AJAX methods are not being tested");
console.log("- Server not active");
done();
}
});
}
};
it("should be a function", function() {
isFn(ajax);
});
it("can make a simple get", ifActive(function(done) {
ajax(url('/plain'), {}, function(error, data, xhr){
expect(error).to.equal(null);
expect(data).to.equal('GET');
expect(xhr instanceof XMLHttpRequest).to.equal(true, 'XMLHttpRequest');
done();
}, function(xhr){
expect(xhr instanceof XMLHttpRequest).to.equal(true, 'XMLHttpRequest');
});
}));
it("can make a simple get", ifActive(function(done) {
ajax(url('/plain'), {}, function(error, data, xhr){
expect(data).to.equal('GET');
expect(xhr instanceof XMLHttpRequest).to.equal(true, 'XMLHttpRequest');
done();
});
}));
it("can send GET but data is lost", ifActive(function(done) {
var body = { send: '123' };
var options = { method: 'GET', body: body };
ajax(url('/json'), options, function(error, data){
expect(data.method).to.equal('GET');
expect(data.body).to.deep.equal({});
done();
});
}));
it("can send POST with data", ifActive(function(done) {
var body = { send: '123' };
var options = { method: 'POST', body: body };
ajax(url('/json'), options, function(error, data){
expect(data.method).to.equal('POST');
expect(data.body).to.deep.equal(body);
done();
});
}));
it("can send PUT with data", ifActive(function(done) {
var body = { send: '123' };
var options = { method: 'PUT', body: body };
ajax(url('/json'), options, function(error, data){
expect(data.method).to.equal('PUT');
expect(data.body).to.deep.equal(body);
done();
});
}));
it("can send DELETE", ifActive(function(done) {
var options = { method: 'DELETE' };
ajax(url('/json'), options, function(error, data){
expect(data.method).to.equal('DELETE');
if (!window.mochaPhantomJS) {
expect(data.body).to.deep.equal({}, "Body should be ignored");
}
done();
});
}));
});
describe("fn ajax()", function() {
beforeEach(function() {
this.xhr = sinon.useFakeXMLHttpRequest();
this.requests = [];
this.xhr.onCreate = function(xhr) {
this.requests.push(xhr);
}.bind(this);
});
afterEach(function() {
this.xhr.restore();
})
it("should be a function", function() {
expect(typeof ajax).to.equal('function');
});
it("should parameterize objects", function() {
var body = {hello: 'world'};
ajax('#', {body: body, method: 'POST'});
expect(this.requests[0].requestBody).to.equal('hello=world');
});
it("should not parameterize FormData", function() {
var body = new FormData();
ajax('#', {body: body, method: 'POST'});
expect(typeof this.requests[0].requestBody).to.equal('object');
});
});
// Testing the main file
describe("parseJsom(string)", function() {
it("should be defined", function() {
expect(typeof parseJson).to.equal('function');
});
it("can be called empty", function() {
expect(parseJson()).to.equal(false);
expect(parseJson("")).to.equal(false);
expect(parseJson([])).to.equal(false);
expect(parseJson("","")).to.equal(false);
expect(parseJson(" ")).to.equal(false);
});
it("parses correctly", function() {
expect(parseJson('{"hello": "world"}').hello).to.equal('world');
});
});
// Note: node._e['submit'] and other events will appear as [null] in PhantomJS
// but they work as expected
describe(".handle(event, fn)", function() {
beforeEach(function(){
base.append('<div class="clickable"><a>Hi</a></div>');
});
afterEach(function(){
u('.clickable').remove();
base.off('click');
});
it("should be defined", function() {
expect(typeof base.handle).to.equal('function');
});
it("triggers the event", function(done) {
base.find('.clickable').handle('click', function(e){
expect(e.target).to.equal(this);
done();
});
base.find('.clickable').trigger('click');
});
it("triggers the event twice", function(done) {
var i = 1;
base.find('.clickable').handle('click submit', function(e){
expect(e.target).to.equal(this);
i++;
if (i === 3) {
done();
}
});
base.find('.clickable').trigger('click');
base.find('.clickable').trigger('submit');
});
it("can do event delegation", function(done) {
base.handle('click', '.clickable', function(e){
expect(e.target.className).to.equal('clickable');
done();
});
base.find('.clickable').trigger('click');
base.off('click');
});
it("event delegation not triggered by others", function() {
base.handle('click', '.clickable', function(e){
throw new Error("Should never get here");
});
base.find('ul').not('.clickable').trigger('click');
base.off('click');
});
it("triggers the delegated event when child element is target", function(done) {
base.handle('click', '.clickable', function(e) {
expect(e.target.tagName).to.equal('A');
expect(e.target.className).to.not.equal('clickable');
done();
});
base.find('.clickable a').trigger('click');
});
it("triggers the event with custom data", function(done) {
base.find('.clickable').handle('click', fun