');
+ });
+
+ $apple = $fruits.eq(0);
+ $orange = $fruits.eq(1);
+ $pear = $fruits.eq(2);
+
+ expect($apple.find('.second')[0]).to.equal($apple.contents()[0]);
+ expect($orange.find('.second')[0]).to.equal($orange.contents()[0]);
+ expect($pear.find('.second')[0]).to.equal($pear.contents()[0]);
+ });
+
+ it('(fn) : should add returned Node as first child', function() {
+ var $apple, $orange, $pear;
+ $fruits = $fruits.children();
+
+ $fruits.prepend(function() {
+ return $('
')[0];
+ });
+
+ $apple = $fruits.eq(0);
+ $orange = $fruits.eq(1);
+ $pear = $fruits.eq(2);
+
+ expect($apple.find('.third')[0]).to.equal($apple.contents()[0]);
+ expect($orange.find('.third')[0]).to.equal($orange.contents()[0]);
+ expect($pear.find('.third')[0]).to.equal($pear.contents()[0]);
+ });
+
+
+ it('($(...)) : should remove from root element', function() {
+ var $plum = $('
Plum');
+ var root = $plum[0].root;
+ expect(root).to.be.ok();
+
+ $fruits.prepend($plum);
+ expect($plum[0].root).to.not.be.ok();
+ expect(root.childNodes).to.not.contain($plum[0]);
+ });
+ });
+
+ describe('.after', function() {
+
+ it('() : should do nothing', function() {
+ expect($('#fruits').after()[0].tagName).to.equal('ul');
+ });
+
+ it('(html) : should add element as next sibling', function() {
+ var grape = '
Grape';
+ $('.apple').after(grape);
+ expect($('.apple').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('(Array) : should add all elements in the array as next sibling', function() {
+ var more = $('
PlumGrape')
+ .get();
+ $('.apple').after(more);
+ expect($fruits.children().eq(1).hasClass('plum')).to.be.ok();
+ expect($fruits.children().eq(2).hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should add element as next sibling', function() {
+ var $plum = $('
Plum');
+ $('.apple').after($plum);
+ expect($('.apple').next().hasClass('plum')).to.be.ok();
+ });
+
+ it('(Node) : should add element as next sibling', function() {
+ var plum = $('
Plum')[0];
+ $('.apple').after(plum);
+ expect($('.apple').next().hasClass('plum')).to.be.ok();
+ });
+
+ it('(existing Node) : should remove existing nodes from previous locations', function() {
+ var pear = $fruits.children()[2];
+ var $children;
+
+ $('.apple').after(pear);
+
+ $children = $fruits.children();
+ expect($children).to.have.length(3);
+ expect($children[1]).to.be(pear);
+ });
+
+ it('(existing Node) : should update original direct siblings', function() {
+ $('.pear').after($('.orange'));
+ expect($('.apple').next()[0]).to.be($('.pear')[0]);
+ expect($('.pear').prev()[0]).to.be($('.apple')[0]);
+ });
+
+ it('(existing Node) : should clone all but the last occurrence', function() {
+ var $originalApple = $('.apple');
+ $('.orange, .pear').after($originalApple);
+
+ expect($('.apple')).to.have.length(2);
+ expect($('.apple').eq(0).prev()[0]).to.be($('.orange')[0]);
+ expect($('.apple').eq(0).next()[0]).to.be($('.pear')[0]);
+ expect($('.apple').eq(1).prev()[0]).to.be($('.pear')[0]);
+ expect($('.apple').eq(1).next()).to.have.length(0);
+ expect($('.apple')[0]).to.not.eql($originalApple[0]);
+ expect($('.apple')[1]).to.eql($originalApple[0]);
+ });
+
+ it('(elem) : should handle if removed', function() {
+ var $apple = $('.apple');
+ var $plum = $('
Plum');
+
+ $apple.remove();
+ $apple.after($plum);
+ expect($plum.prev()).to.be.empty();
+ });
+
+ it('($(...), html) : should add multiple elements as next siblings', function() {
+ var $plum = $('
Plum');
+ var grape = '
Grape';
+ $('.apple').after($plum, grape);
+ expect($('.apple').next().hasClass('plum')).to.be.ok();
+ expect($('.plum').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('(fn) : should invoke the callback with the correct arguments and context', function() {
+ var args = [];
+ var thisValues = [];
+ $fruits = $fruits.children();
+
+ $fruits.after(function() {
+ args.push(toArray(arguments));
+ thisValues.push(this);
+ });
+
+ expect(args).to.eql([[0, 'Apple'], [1, 'Orange'], [2, 'Pear']]);
+ expect(thisValues).to.eql([
+ $fruits[0],
+ $fruits[1],
+ $fruits[2]
+ ]);
+ });
+
+ it('(fn) : should add returned string as next sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.after(function() {
+ return '
';
+ });
+
+ expect($('.first')[0]).to.equal($('#fruits').contents()[1]);
+ expect($('.first')[1]).to.equal($('#fruits').contents()[3]);
+ expect($('.first')[2]).to.equal($('#fruits').contents()[5]);
+ });
+
+ it('(fn) : should add returned Cheerio object as next sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.after(function() {
+ return $('');
+ });
+
+ expect($('.second')[0]).to.equal($('#fruits').contents()[1]);
+ expect($('.second')[1]).to.equal($('#fruits').contents()[3]);
+ expect($('.second')[2]).to.equal($('#fruits').contents()[5]);
+ });
+
+ it('(fn) : should add returned element as next sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.after(function() {
+ return $('')[0];
+ });
+
+ expect($('.third')[0]).to.equal($('#fruits').contents()[1]);
+ expect($('.third')[1]).to.equal($('#fruits').contents()[3]);
+ expect($('.third')[2]).to.equal($('#fruits').contents()[5]);
+ });
+
+ it('($(...)) : should remove from root element', function() {
+ var $plum = $('Plum');
+ var root = $plum[0].root;
+ expect(root).to.be.ok();
+
+ $fruits.after($plum);
+ expect($plum[0].root).to.not.be.ok();
+ expect(root.childNodes).to.not.contain($plum[0]);
+ });
+ });
+
+ describe('.insertAfter', function() {
+
+ it('(selector) : should create element and add as next sibling', function() {
+ var grape = $('
Grape');
+ grape.insertAfter('.apple');
+ expect($('.apple').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('(selector) : should create element and add as next sibling of multiple elements', function() {
+ var grape = $('
Grape');
+ grape.insertAfter('.apple, .pear');
+ expect($('.apple').next().hasClass('grape')).to.be.ok();
+ expect($('.pear').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create element and add as next sibling', function() {
+ var grape = $('
Grape');
+ grape.insertAfter($('.apple'));
+ expect($('.apple').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create element and add as next sibling of multiple elements', function() {
+ var grape = $('
Grape');
+ grape.insertAfter($('.apple, .pear'));
+ expect($('.apple').next().hasClass('grape')).to.be.ok();
+ expect($('.pear').next().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create all elements in the array and add as next siblings', function() {
+ var more = $('
PlumGrape');
+ more.insertAfter($('.apple'));
+ expect($fruits.children().eq(0).hasClass('apple')).to.be.ok();
+ expect($fruits.children().eq(1).hasClass('plum')).to.be.ok();
+ expect($fruits.children().eq(2).hasClass('grape')).to.be.ok();
+ });
+
+ it('(existing Node) : should remove existing nodes from previous locations', function() {
+ $('.orange').insertAfter('.pear');
+ expect($fruits.children().eq(1).hasClass('orange')).to.not.be.ok();
+ expect($fruits.children().length).to.be(3);
+ expect($('.orange').length).to.be(1);
+ });
+
+ it('(existing Node) : should update original direct siblings', function() {
+ $('.orange').insertAfter('.pear');
+ expect($('.apple').next().hasClass('pear')).to.be.ok();
+ expect($('.pear').prev().hasClass('apple')).to.be.ok();
+ expect($('.pear').next().hasClass('orange')).to.be.ok();
+ expect($('.orange').next()).to.be.empty();
+ });
+
+ it('(existing Node) : should update original direct siblings of multiple elements', function() {
+ $('.apple').insertAfter('.orange, .pear');
+ expect($('.orange').prev()).to.be.empty();
+ expect($('.orange').next().hasClass('apple')).to.be.ok();
+ expect($('.pear').next().hasClass('apple')).to.be.ok();
+ expect($('.pear').prev().hasClass('apple')).to.be.ok();
+ expect($fruits.children().length).to.be(4);
+ var apples = $('.apple');
+ expect(apples.length).to.be(2);
+ expect(apples.eq(0).prev().hasClass('orange')).to.be.ok();
+ expect(apples.eq(1).prev().hasClass('pear')).to.be.ok();
+ });
+
+ it('(elem) : should handle if removed', function() {
+ var $apple = $('.apple');
+ var $plum = $('
Plum');
+ $apple.remove();
+ $plum.insertAfter($apple);
+ expect($plum.prev()).to.be.empty();
+ });
+
+ it('(single) should return the new element for chaining', function() {
+ var $grape = $('
Grape').insertAfter('.apple');
+ expect($grape.cheerio).to.be.ok();
+ expect($grape.each).to.be.ok();
+ expect($grape.length).to.be(1);
+ expect($grape.hasClass('grape')).to.be.ok();
+ });
+
+ it('(single) should return the new elements for chaining', function() {
+ var $purple = $('
GrapePlum').insertAfter('.apple');
+ expect($purple.cheerio).to.be.ok();
+ expect($purple.each).to.be.ok();
+ expect($purple.length).to.be(2);
+ expect($purple.eq(0).hasClass('grape')).to.be.ok();
+ expect($purple.eq(1).hasClass('plum')).to.be.ok();
+ });
+
+ it('(multiple) should return the new elements for chaining', function() {
+ var $purple = $('
GrapePlum').insertAfter('.apple, .pear');
+ expect($purple.cheerio).to.be.ok();
+ expect($purple.each).to.be.ok();
+ expect($purple.length).to.be(4);
+ expect($purple.eq(0).hasClass('grape')).to.be.ok();
+ expect($purple.eq(1).hasClass('plum')).to.be.ok();
+ expect($purple.eq(2).hasClass('grape')).to.be.ok();
+ expect($purple.eq(3).hasClass('plum')).to.be.ok();
+ });
+
+ it('(single) should return the existing element for chaining', function() {
+ var $pear = $('.pear').insertAfter('.apple');
+ expect($pear.cheerio).to.be.ok();
+ expect($pear.each).to.be.ok();
+ expect($pear.length).to.be(1);
+ expect($pear.hasClass('pear')).to.be.ok();
+ });
+
+ it('(single) should return the existing elements for chaining', function() {
+ var $things = $('.orange, .apple').insertAfter('.pear');
+ expect($things.cheerio).to.be.ok();
+ expect($things.each).to.be.ok();
+ expect($things.length).to.be(2);
+ expect($things.eq(0).hasClass('apple')).to.be.ok();
+ expect($things.eq(1).hasClass('orange')).to.be.ok();
+ });
+
+ it('(multiple) should return the existing elements for chaining', function() {
+ $('
Grape').insertAfter('.apple');
+ var $things = $('.orange, .apple').insertAfter('.pear, .grape');
+ expect($things.cheerio).to.be.ok();
+ expect($things.each).to.be.ok();
+ expect($things.length).to.be(4);
+ expect($things.eq(0).hasClass('apple')).to.be.ok();
+ expect($things.eq(1).hasClass('orange')).to.be.ok();
+ expect($things.eq(2).hasClass('apple')).to.be.ok();
+ expect($things.eq(3).hasClass('orange')).to.be.ok();
+ });
+
+ });
+
+ describe('.before', function() {
+
+ it('() : should do nothing', function() {
+ expect($('#fruits').before()[0].tagName).to.equal('ul');
+ });
+
+ it('(html) : should add element as previous sibling', function() {
+ var grape = '
Grape';
+ $('.apple').before(grape);
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should add element as previous sibling', function() {
+ var $plum = $('
Plum');
+ $('.apple').before($plum);
+ expect($('.apple').prev().hasClass('plum')).to.be.ok();
+ });
+
+ it('(Node) : should add element as previous sibling', function() {
+ var plum = $('
Plum');
+ $('.apple').before(plum);
+ expect($('.apple').prev().hasClass('plum')).to.be.ok();
+ });
+
+ it('(existing Node) : should remove existing nodes from previous locations', function() {
+ var pear = $fruits.children()[2];
+ var $children;
+
+ $('.apple').before(pear);
+
+ $children = $fruits.children();
+ expect($children).to.have.length(3);
+ expect($children[0]).to.be(pear);
+ });
+
+ it('(existing Node) : should update original direct siblings', function() {
+ $('.apple').before($('.orange'));
+ expect($('.apple').next()[0]).to.be($('.pear')[0]);
+ expect($('.pear').prev()[0]).to.be($('.apple')[0]);
+ });
+
+ it('(existing Node) : should clone all but the last occurrence', function() {
+ var $originalPear = $('.pear');
+ $('.apple, .orange').before($originalPear);
+
+ expect($('.pear')).to.have.length(2);
+ expect($('.pear').eq(0).prev()).to.have.length(0);
+ expect($('.pear').eq(0).next()[0]).to.be($('.apple')[0]);
+ expect($('.pear').eq(1).prev()[0]).to.be($('.apple')[0]);
+ expect($('.pear').eq(1).next()[0]).to.be($('.orange')[0]);
+ expect($('.pear')[0]).to.not.eql($originalPear[0]);
+ expect($('.pear')[1]).to.eql($originalPear[0]);
+ });
+
+ it('(elem) : should handle if removed', function() {
+ var $apple = $('.apple');
+ var $plum = $('
Plum');
+
+ $apple.remove();
+ $apple.before($plum);
+ expect($plum.next()).to.be.empty();
+ });
+
+ it('(Array) : should add all elements in the array as previous sibling', function() {
+ var more = $('
PlumGrape')
+ .get();
+ $('.apple').before(more);
+ expect($fruits.children().eq(0).hasClass('plum')).to.be.ok();
+ expect($fruits.children().eq(1).hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...), html) : should add multiple elements as previous siblings', function() {
+ var $plum = $('
Plum');
+ var grape = '
Grape';
+ $('.apple').before($plum, grape);
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ expect($('.grape').prev().hasClass('plum')).to.be.ok();
+ });
+
+ it('(fn) : should invoke the callback with the correct arguments and context', function() {
+ var args = [];
+ var thisValues = [];
+ $fruits = $fruits.children();
+
+ $fruits.before(function() {
+ args.push(toArray(arguments));
+ thisValues.push(this);
+ });
+
+ expect(args).to.eql([[0, 'Apple'], [1, 'Orange'], [2, 'Pear']]);
+ expect(thisValues).to.eql([
+ $fruits[0],
+ $fruits[1],
+ $fruits[2]
+ ]);
+ });
+
+ it('(fn) : should add returned string as previous sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.before(function() {
+ return '
';
+ });
+
+ expect($('.first')[0]).to.equal($('#fruits').contents()[0]);
+ expect($('.first')[1]).to.equal($('#fruits').contents()[2]);
+ expect($('.first')[2]).to.equal($('#fruits').contents()[4]);
+ });
+
+ it('(fn) : should add returned Cheerio object as previous sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.before(function() {
+ return $('');
+ });
+
+ expect($('.second')[0]).to.equal($('#fruits').contents()[0]);
+ expect($('.second')[1]).to.equal($('#fruits').contents()[2]);
+ expect($('.second')[2]).to.equal($('#fruits').contents()[4]);
+ });
+
+ it('(fn) : should add returned Node as previous sibling', function() {
+ $fruits = $fruits.children();
+
+ $fruits.before(function() {
+ return $('')[0];
+ });
+
+ expect($('.third')[0]).to.equal($('#fruits').contents()[0]);
+ expect($('.third')[1]).to.equal($('#fruits').contents()[2]);
+ expect($('.third')[2]).to.equal($('#fruits').contents()[4]);
+ });
+
+ it('($(...)) : should remove from root element', function() {
+ var $plum = $('Plum');
+ var root = $plum[0].root;
+ expect(root).to.be.ok();
+
+ $fruits.before($plum);
+ expect($plum[0].root).to.not.be.ok();
+ expect(root.childNodes).to.not.contain($plum[0]);
+ });
+ });
+
+ describe('.insertBefore', function() {
+
+ it('(selector) : should create element and add as prev sibling', function() {
+ var grape = $('
Grape');
+ grape.insertBefore('.apple');
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ });
+
+ it('(selector) : should create element and add as prev sibling of multiple elements', function() {
+ var grape = $('
Grape');
+ grape.insertBefore('.apple, .pear');
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ expect($('.pear').prev().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create element and add as prev sibling', function() {
+ var grape = $('
Grape');
+ grape.insertBefore($('.apple'));
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create element and add as next sibling of multiple elements', function() {
+ var grape = $('
Grape');
+ grape.insertBefore($('.apple, .pear'));
+ expect($('.apple').prev().hasClass('grape')).to.be.ok();
+ expect($('.pear').prev().hasClass('grape')).to.be.ok();
+ });
+
+ it('($(...)) : should create all elements in the array and add as prev siblings', function() {
+ var more = $('
PlumGrape');
+ more.insertBefore($('.apple'));
+ expect($fruits.children().eq(0).hasClass('plum')).to.be.ok();
+ expect($fruits.children().eq(1).hasClass('grape')).to.be.ok();
+ expect($fruits.children().eq(2).hasClass('apple')).to.be.ok();
+ });
+
+ it('(existing Node) : should remove existing nodes from previous locations', function() {
+ $('.pear').insertBefore('.apple');
+ expect($fruits.children().eq(2).hasClass('pear')).to.not.be.ok();
+ expect($fruits.children().length).to.be(3);
+ expect($('.pear').length).to.be(1);
+ });
+
+ it('(existing Node) : should update original direct siblings', function() {
+ $('.pear').insertBefore('.apple');
+ expect($('.apple').prev().hasClass('pear')).to.be.ok();
+ expect($('.apple').next().hasClass('orange')).to.be.ok();
+ expect($('.pear').next().hasClass('apple')).to.be.ok();
+ expect($('.pear').prev()).to.be.empty();
+ });
+
+ it('(existing Node) : should update original direct siblings of multiple elements', function() {
+ $('.pear').insertBefore('.apple, .orange');
+ expect($('.apple').prev().hasClass('pear')).to.be.ok();
+ expect($('.apple').next().hasClass('pear')).to.be.ok();
+ expect($('.orange').prev().hasClass('pear')).to.be.ok();
+ expect($('.orange').next()).to.be.empty();
+ expect($fruits.children().length).to.be(4);
+ var pears = $('.pear');
+ expect(pears.length).to.be(2);
+ expect(pears.eq(0).next().hasClass('apple')).to.be.ok();
+ expect(pears.eq(1).next().hasClass('orange')).to.be.ok();
+ });
+
+ it('(elem) : should handle if removed', function() {
+ var $apple = $('.apple');
+ var $plum = $('
Plum');
+
+ $apple.remove();
+ $plum.insertBefore($apple);
+ expect($plum.next()).to.be.empty();
+ });
+
+ it('(single) should return the new element for chaining', function() {
+ var $grape = $('
Grape').insertBefore('.apple');
+ expect($grape.cheerio).to.be.ok();
+ expect($grape.each).to.be.ok();
+ expect($grape.length).to.be(1);
+ expect($grape.hasClass('grape')).to.be.ok();
+ });
+
+ it('(single) should return the new elements for chaining', function() {
+ var $purple = $('
GrapePlum').insertBefore('.apple');
+ expect($purple.cheerio).to.be.ok();
+ expect($purple.each).to.be.ok();
+ expect($purple.length).to.be(2);
+ expect($purple.eq(0).hasClass('grape')).to.be.ok();
+ expect($purple.eq(1).hasClass('plum')).to.be.ok();
+ });
+
+ it('(multiple) should return the new elements for chaining', function() {
+ var $purple = $('
GrapePlum').insertBefore('.apple, .pear');
+ expect($purple.cheerio).to.be.ok();
+ expect($purple.each).to.be.ok();
+ expect($purple.length).to.be(4);
+ expect($purple.eq(0).hasClass('grape')).to.be.ok();
+ expect($purple.eq(1).hasClass('plum')).to.be.ok();
+ expect($purple.eq(2).hasClass('grape')).to.be.ok();
+ expect($purple.eq(3).hasClass('plum')).to.be.ok();
+ });
+
+ it('(single) should return the existing element for chaining', function() {
+ var $orange = $('.orange').insertBefore('.apple');
+ expect($orange.cheerio).to.be.ok();
+ expect($orange.each).to.be.ok();
+ expect($orange.length).to.be(1);
+ expect($orange.hasClass('orange')).to.be.ok();
+ });
+
+ it('(single) should return the existing elements for chaining', function() {
+ var $things = $('.orange, .pear').insertBefore('.apple');
+ expect($things.cheerio).to.be.ok();
+ expect($things.each).to.be.ok();
+ expect($things.length).to.be(2);
+ expect($things.eq(0).hasClass('orange')).to.be.ok();
+ expect($things.eq(1).hasClass('pear')).to.be.ok();
+ });
+
+ it('(multiple) should return the existing elements for chaining', function() {
+ $('
Grape').insertBefore('.apple');
+ var $things = $('.orange, .apple').insertBefore('.pear, .grape');
+ expect($things.cheerio).to.be.ok();
+ expect($things.each).to.be.ok();
+ expect($things.length).to.be(4);
+ expect($things.eq(0).hasClass('apple')).to.be.ok();
+ expect($things.eq(1).hasClass('orange')).to.be.ok();
+ expect($things.eq(2).hasClass('apple')).to.be.ok();
+ expect($things.eq(3).hasClass('orange')).to.be.ok();
+ });
+
+ });
+
+ describe('.remove', function() {
+
+ it('() : should remove selected elements', function() {
+ $('.apple').remove();
+ expect($fruits.find('.apple')).to.have.length(0);
+ });
+
+ it('() : should be reentrant', function() {
+ var $apple = $('.apple');
+ $apple.remove();
+ $apple.remove();
+ expect($fruits.find('.apple')).to.have.length(0);
+ });
+
+ it('(selector) : should remove matching selected elements', function() {
+ $('li').remove('.apple');
+ expect($fruits.find('.apple')).to.have.length(0);
+ });
+
+ it('($(...)) : should remove from root element', function() {
+ var $plum = $('
Plum');
+ var root = $plum[0].root;
+ expect(root).to.be.ok();
+
+ $plum.remove();
+ expect($plum[0].root).to.not.be.ok();
+ expect(root.childNodes).to.not.contain($plum[0]);
+ });
+ });
+
+ describe('.replaceWith', function() {
+
+ it('(elem) : should replace one
tag with another', function() {
+ var $plum = $('Plum');
+ $('.pear').replaceWith($plum);
+ expect($('.orange').next().hasClass('plum')).to.be.ok();
+ expect($('.orange').next().html()).to.equal('Plum');
+ });
+
+ it('(Array) : should replace one
tag with the elements in the array', function() {
+ var more = $('PlumGrape')
+ .get();
+ $('.pear').replaceWith(more);
+
+ expect($fruits.children().eq(2).hasClass('plum')).to.be.ok();
+ expect($fruits.children().eq(3).hasClass('grape')).to.be.ok();
+ expect($fruits.children()).to.have.length(4);
+ });
+
+ it('(Node) : should replace the selected element with given node', function() {
+ var $src = $('
hi there
');
+ var $new = $('
');
+ var $replaced = $src.find('span').replaceWith($new[0]);
+ expect($new[0].parentNode).to.equal($src[0]);
+ expect($replaced[0].parentNode).to.equal(null);
+ expect($.html($src)).to.equal('
hi
');
+ });
+
+ it('(existing element) : should remove element from its previous location', function() {
+ $('.pear').replaceWith($('.apple'));
+ expect($fruits.children()).to.have.length(2);
+ expect($fruits.children()[0]).to.equal($('.orange')[0]);
+ expect($fruits.children()[1]).to.equal($('.apple')[0]);
+ });
+
+ it('(elem) : should NOP if removed', function() {
+ var $pear = $('.pear');
+ var $plum = $('
Plum');
+
+ $pear.remove();
+ $pear.replaceWith($plum);
+ expect($('.orange').next().hasClass('plum')).to.not.be.ok();
+ });
+
+ it('(elem) : should replace the single selected element with given element', function() {
+ var $src = $('
hi there
');
+ var $new = $('
here
');
+ var $replaced = $src.find('span').replaceWith($new);
+ expect($new[0].parentNode).to.equal($src[0]);
+ expect($replaced[0].parentNode).to.equal(null);
+ expect($.html($src)).to.equal('
hi
here
');
+ });
+
+ it('(str) : should accept strings', function() {
+ var $src = $('
hi there
');
+ var newStr = '
here
';
+ var $replaced = $src.find('span').replaceWith(newStr);
+ expect($replaced[0].parentNode).to.equal(null);
+ expect($.html($src)).to.equal('
hi
here
');
+ });
+
+ it('(str) : should replace all selected elements', function() {
+ var $src = $('
a
b
c
d');
+ var $replaced = $src.find('br').replaceWith(' ');
+ expect($replaced[0].parentNode).to.equal(null);
+ expect($.html($src)).to.equal('
a b c d');
+ });
+
+ it('(fn) : should invoke the callback with the correct argument and context', function() {
+ var origChildren = $fruits.children().get();
+ var args = [];
+ var thisValues = [];
+
+ $fruits.children().replaceWith(function() {
+ args.push(toArray(arguments));
+ thisValues.push(this);
+ return '
';
+ });
+
+ expect(args).to.eql([
+ [0, origChildren[0]],
+ [1, origChildren[1]],
+ [2, origChildren[2]]
+ ]);
+ expect(thisValues).to.eql([
+ origChildren[0],
+ origChildren[1],
+ origChildren[2]
+ ]);
+ });
+
+ it('(fn) : should replace the selected element with the returned string', function() {
+ $fruits.children().replaceWith(function() {
+ return '';
+ });
+
+ expect($fruits.find('.first')).to.have.length(3);
+ });
+
+ it('(fn) : should replace the selected element with the returned Cheerio object', function() {
+ $fruits.children().replaceWith(function() {
+ return $('');
+ });
+
+ expect($fruits.find('.second')).to.have.length(3);
+ });
+
+ it('(fn) : should replace the selected element with the returned node', function() {
+ $fruits.children().replaceWith(function() {
+ return $('')[0];
+ });
+
+ expect($fruits.find('.third')).to.have.length(3);
+ });
+
+ it('($(...)) : should remove from root element', function() {
+ var $plum = $('Plum');
+ var root = $plum[0].root;
+ expect(root).to.be.ok();
+
+ $fruits.children().replaceWith($plum);
+ expect($plum[0].root).to.not.be.ok();
+ expect(root.childNodes).to.not.contain($plum[0]);
+ });
+ });
+
+ describe('.empty', function() {
+ it('() : should remove all children from selected elements', function() {
+ expect($fruits.children()).to.have.length(3);
+
+ $fruits.empty();
+ expect($fruits.children()).to.have.length(0);
+ });
+
+ it('() : should allow element reinsertion', function() {
+ var $children = $fruits.children();
+
+ $fruits.empty();
+ expect($fruits.children()).to.have.length(0);
+ expect($children).to.have.length(3);
+
+ $fruits.append($('
'));
+ var $remove = $fruits.children().eq(0);
+
+ $remove.replaceWith($children);
+ expect($fruits.children()).to.have.length(4);
+ });
+
+ it('() : should destroy children\'s references to the parent', function() {
+ var $children = $fruits.children();
+
+ $fruits.empty();
+
+ expect($children.eq(0).parent()).to.have.length(0);
+ expect($children.eq(0).next()).to.have.length(0);
+ expect($children.eq(0).prev()).to.have.length(0);
+ expect($children.eq(1).parent()).to.have.length(0);
+ expect($children.eq(1).next()).to.have.length(0);
+ expect($children.eq(1).prev()).to.have.length(0);
+ expect($children.eq(2).parent()).to.have.length(0);
+ expect($children.eq(2).next()).to.have.length(0);
+ expect($children.eq(2).prev()).to.have.length(0);
+ });
+
+ });
+
+ describe('.html', function() {
+
+ it('() : should get the innerHTML for an element', function() {
+ expect($fruits.html()).to.equal([
+ '
Apple',
+ '
Orange',
+ '
Pear'
+ ].join(''));
+ });
+
+ it('() : should get innerHTML even if its just text', function() {
+ var item = '
Pear';
+ expect($('.pear', item).html()).to.equal('Pear');
+ });
+
+ it('() : should return empty string if nothing inside', function() {
+ var item = '
';
+ expect($('li', item).html()).to.equal('');
+ });
+
+ it('(html) : should set the html for its children', function() {
+ $fruits.html('
Durian');
+ var html = $fruits.html();
+ expect(html).to.equal('
Durian');
+ });
+
+ it('(html) : should add new elements for each element in selection', function() {
+ var $fruits = $('li');
+ $fruits.html('
Durian');
+ var tested = 0;
+ $fruits.each(function(){
+ expect($(this).children().parent().get(0)).to.equal(this);
+ tested++;
+ });
+ expect(tested).to.equal(3);
+ });
+
+ it('(elem) : should set the html for its children with element', function() {
+ $fruits.html($('
Durian'));
+ var html = $fruits.html();
+ expect(html).to.equal('
Durian');
+ });
+
+ it('() : should allow element reinsertion', function() {
+ var $children = $fruits.children();
+
+ $fruits.html('
');
+ expect($fruits.children()).to.have.length(2);
+
+ var $remove = $fruits.children().eq(0);
+
+ $remove.replaceWith($children);
+ expect($fruits.children()).to.have.length(4);
+ });
+ });
+
+ describe('.toString', function() {
+ it('() : should get the outerHTML for an element', function() {
+ expect($fruits.toString()).to.equal(fruits);
+ });
+
+ it('() : should return an html string for a set of elements', function() {
+ expect($fruits.find('li').toString()).to.equal('
AppleOrangePear');
+ });
+
+ it('() : should be called implicitly', function() {
+ var string = [$('
'), $(''), $('')].join('');
+ expect(string).to.equal('');
+ });
+
+ it('() : should pass options', function() {
+ var dom = cheerio.load('&', {decodeEntities: false});
+ expect(dom.root().toString()).to.equal('&');
+ });
+ });
+
+ describe('.text', function() {
+
+ it('() : gets the text for a single element', function() {
+ expect($('.apple').text()).to.equal('Apple');
+ });
+
+ it('() : combines all text from children text nodes', function() {
+ expect($('#fruits').text()).to.equal('AppleOrangePear');
+ });
+
+ it('(text) : sets the text for the child node', function() {
+ $('.apple').text('Granny Smith Apple');
+ expect($('.apple')[0].childNodes[0].data).to.equal('Granny Smith Apple');
+ });
+
+ it('(text) : inserts separate nodes for all children', function() {
+ $('li').text('Fruits');
+ var tested = 0;
+ $('li').each(function(){
+ expect(this.childNodes[0].parent).to.equal(this);
+ tested++;
+ });
+ expect(tested).to.equal(3);
+ });
+
+ it('should allow functions as arguments', function() {
+ $('.apple').text(function(idx, content) {
+ expect(idx).to.equal(0);
+ expect(content).to.equal('Apple');
+ return 'whatever mate';
+ });
+ expect($('.apple')[0].childNodes[0].data).to.equal('whatever mate');
+ });
+
+ it('should decode special chars', function() {
+ var text = $('M&M
').text();
+ expect(text).to.equal('M&M');
+ });
+
+ it('should work with special chars added as strings', function() {
+ var text = $('M&M
').text();
+ expect(text).to.equal('M&M');
+ });
+
+ it('( undefined ) : should act as an accessor', function() {
+ var $div = $('test
');
+ expect($div.text(undefined)).to.be.a('string');
+ expect($div.text()).to.be('test');
+ });
+
+ it('( "" ) : should convert to string', function() {
+ var $div = $('test
');
+ expect($div.text('').text()).to.equal('');
+ });
+
+ it('( null ) : should convert to string', function() {
+ expect($('').text(null).text()).to.equal('null');
+ });
+
+ it('( 0 ) : should convert to string', function() {
+ expect($('
').text(0).text()).to.equal('0');
+ });
+
+ it('(str) should encode then decode unsafe characters', function() {
+ var $apple = $('.apple');
+
+ $apple.text('blah blah');
+ expect($apple[0].childNodes[0].data).to.equal('blah blah');
+ expect($apple.text()).to.equal('blah blah');
+
+ $apple.text('blah blah');
+ expect($apple.html()).to.not.contain('');
+ });
+ });
+
+});
diff --git a/node_modules/cheerio/test/api/traversing.js b/node_modules/cheerio/test/api/traversing.js
new file mode 100644
index 00000000..7ed5786a
--- /dev/null
+++ b/node_modules/cheerio/test/api/traversing.js
@@ -0,0 +1,1408 @@
+var expect = require('expect.js'),
+ cheerio = require('../..'),
+ food = require('../fixtures').food,
+ fruits = require('../fixtures').fruits,
+ drinks = require('../fixtures').drinks,
+ text = require('../fixtures').text;
+
+describe('$(...)', function() {
+
+ var $;
+
+ beforeEach(function() {
+ $ = cheerio.load(fruits);
+ });
+
+ describe('.find', function() {
+
+ it('() : should find nothing', function() {
+ expect($('ul').find()).to.have.length(0);
+ });
+
+ it('(single) : should find one descendant', function() {
+ expect($('#fruits').find('.apple')[0].attribs['class']).to.equal('apple');
+ });
+
+ it('(many) : should find all matching descendant', function() {
+ expect($('#fruits').find('li')).to.have.length(3);
+ });
+
+ it('(many) : should merge all selected elems with matching descendants', function() {
+ expect($('#fruits, #food', food).find('.apple')).to.have.length(1);
+ });
+
+ it('(invalid single) : should return empty if cant find', function() {
+ expect($('ul').find('blah')).to.have.length(0);
+ });
+
+ it('(invalid single) : should query descendants only', function() {
+ expect($('#fruits').find('ul')).to.have.length(0);
+ });
+
+ it('should return empty if search already empty result', function() {
+ expect($('#not-fruits').find('li')).to.have.length(0);
+ });
+
+ it('should lowercase selectors', function() {
+ expect($('#fruits').find('LI')).to.have.length(3);
+ });
+
+ it('should query case-sensitively when in xmlMode', function() {
+ var q = cheerio.load('
', {xmlMode: true});
+ expect(q('caseSenSitive')).to.have.length(1);
+ expect(q('[allTheWay]')).to.have.length(1);
+ expect(q('casesensitive')).to.have.length(0);
+ expect(q('[alltheway]')).to.have.length(0);
+ });
+
+ it('should throw a SyntaxError if given an invalid selector', function() {
+ expect(function() {
+ $('#fruits').find(':bah');
+ }).to.throwException(function(err) {
+ expect(err).to.be.a(SyntaxError);
+ });
+ });
+
+ describe('(cheerio object) :', function() {
+ it('returns only those nodes contained within the current selection', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('#fruits').find($('li'));
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($('.apple')[0]);
+ expect($selection[1]).to.be($('.orange')[0]);
+ expect($selection[2]).to.be($('.pear')[0]);
+ });
+ it('returns only those nodes contained within any element in the current selection', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('.apple, #vegetables').find($('li'));
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($('.carrot')[0]);
+ expect($selection[1]).to.be($('.sweetcorn')[0]);
+ });
+ });
+
+ describe('(node) :', function() {
+ it('returns node when contained within the current selection', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('#fruits').find($('.apple')[0]);
+
+ expect($selection).to.have.length(1);
+ expect($selection[0]).to.be($('.apple')[0]);
+ });
+ it('returns node when contained within any element the current selection', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('#fruits, #vegetables').find($('.carrot')[0]);
+
+ expect($selection).to.have.length(1);
+ expect($selection[0]).to.be($('.carrot')[0]);
+ });
+ it('does not return node that is not contained within the current selection', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('#fruits').find($('.carrot')[0]);
+
+ expect($selection).to.have.length(0);
+ });
+ });
+ });
+
+ describe('.children', function() {
+
+ it('() : should get all children', function() {
+ expect($('ul').children()).to.have.length(3);
+ });
+
+ it('() : should return children of all matched elements', function() {
+ expect($('ul ul', food).children()).to.have.length(5);
+ });
+
+ it('(selector) : should return children matching selector', function() {
+ var cls = $('ul').children('.orange')[0].attribs['class'];
+ expect(cls).to.equal('orange');
+ });
+
+ it('(invalid selector) : should return empty', function() {
+ expect($('ul').children('.lulz')).to.have.length(0);
+ });
+
+ it('should only match immediate children, not ancestors', function() {
+ expect($(food).children('li')).to.have.length(0);
+ });
+
+ });
+
+ describe('.contents', function() {
+
+ beforeEach(function() {
+ $ = cheerio.load(text);
+ });
+
+ it('() : should get all contents', function() {
+ expect($('p').contents()).to.have.length(5);
+ });
+
+ it('() : should include text nodes', function() {
+ expect($('p').contents().first()[0].type).to.equal('text');
+ });
+
+ it('() : should include comment nodes', function() {
+ expect($('p').contents().last()[0].type).to.equal('comment');
+ });
+
+ });
+
+ describe('.next', function() {
+
+ it('() : should return next element', function() {
+ var cls = $('.orange').next()[0].attribs['class'];
+ expect(cls).to.equal('pear');
+ });
+
+ it('(no next) : should return empty for last child', function() {
+ expect($('.pear').next()).to.have.length(0);
+ });
+
+ it('(next on empty object) : should return empty', function() {
+ expect($('.banana').next()).to.have.length(0);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ expect($('.apple, .orange', food).next()).to.have.length(2);
+ });
+
+ describe('(selector) :', function() {
+ it('should reject elements that violate the filter', function() {
+ expect($('.apple').next('.non-existent')).to.have.length(0);
+ });
+
+ it('should accept elements that satisify the filter', function() {
+ expect($('.apple').next('.orange')).to.have.length(1);
+ });
+ });
+
+ });
+
+ describe('.nextAll', function() {
+
+ it('() : should return all following siblings', function() {
+ var elems = $('.apple').nextAll();
+ expect(elems).to.have.length(2);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ expect(elems[1].attribs['class']).to.equal('pear');
+ });
+
+ it('(no next) : should return empty for last child', function() {
+ expect($('.pear').nextAll()).to.have.length(0);
+ });
+
+ it('(nextAll on empty object) : should return empty', function() {
+ expect($('.banana').nextAll()).to.have.length(0);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ expect($('.apple, .carrot', food).nextAll()).to.have.length(3);
+ });
+
+ it('() : should not contain duplicate elements', function() {
+ var elems = $('.apple, .orange', food);
+ expect(elems.nextAll()).to.have.length(2);
+ });
+
+ describe('(selector) :', function() {
+ it('should filter according to the provided selector', function() {
+ expect($('.apple').nextAll('.pear')).to.have.length(1);
+ });
+
+ it('should not consider siblings\' contents when filtering', function() {
+ expect($('#fruits', food).nextAll('li')).to.have.length(0);
+ });
+ });
+
+ });
+
+ describe('.nextUntil', function() {
+
+ it('() : should return all following siblings if no selector specified', function() {
+ var elems = $('.apple', food).nextUntil();
+ expect(elems).to.have.length(2);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ expect(elems[1].attribs['class']).to.equal('pear');
+ });
+
+ it('() : should filter out non-element nodes', function() {
+ var elems = $('');
+ var div = elems.children().eq(0);
+ expect(div.nextUntil()).to.have.length(1);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ var elems = $('.apple, .carrot', food);
+ expect(elems.nextUntil()).to.have.length(3);
+ });
+
+ it('() : should not contain duplicate elements', function() {
+ var elems = $('.apple, .orange', food);
+ expect(elems.nextUntil()).to.have.length(2);
+ });
+
+ it('(selector) : should return all following siblings until selector', function() {
+ var elems = $('.apple', food).nextUntil('.pear');
+ expect(elems).to.have.length(1);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ });
+
+ it('(selector not sibling) : should return all following siblings', function() {
+ var elems = $('.apple').nextUntil('#vegetables');
+ expect(elems).to.have.length(2);
+ });
+
+ it('(selector, filterString) : should return all following siblings until selector, filtered by filter', function() {
+ var elems = $('.beer', drinks).nextUntil('.water', '.milk');
+ expect(elems).to.have.length(1);
+ expect(elems[0].attribs['class']).to.equal('milk');
+ });
+
+ it('(null, filterString) : should return all following siblings until selector, filtered by filter', function() {
+ var elems = $('');
+ var empty = elems.find('li').eq(0).nextUntil(null, 'p');
+ expect(empty).to.have.length(0);
+ });
+
+ it('() : should return an empty object for last child', function() {
+ expect($('.pear').nextUntil()).to.have.length(0);
+ });
+
+ it('() : should return an empty object when called on an empty object', function() {
+ expect($('.banana').nextUntil()).to.have.length(0);
+ });
+
+ it('(node) : should return all following siblings until the node', function() {
+ var $fruits = $('#fruits').children();
+ var elems = $fruits.eq(0).nextUntil($fruits[2]);
+ expect(elems).to.have.length(1);
+ });
+
+ it('(cheerio object) : should return all following siblings until any member of the cheerio object', function() {
+ var $drinks = $(drinks).children();
+ var $until = $([$drinks[4], $drinks[3]]);
+ var elems = $drinks.eq(0).nextUntil($until);
+ expect(elems).to.have.length(2);
+ });
+
+ });
+
+ describe('.prev', function() {
+
+ it('() : should return previous element', function() {
+ var cls = $('.orange').prev()[0].attribs['class'];
+ expect(cls).to.equal('apple');
+ });
+
+ it('(no prev) : should return empty for first child', function() {
+ expect($('.apple').prev()).to.have.length(0);
+ });
+
+ it('(prev on empty object) : should return empty', function() {
+ expect($('.banana').prev()).to.have.length(0);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ expect($('.orange, .pear', food).prev()).to.have.length(2);
+ });
+
+ describe('(selector) :', function() {
+ it('should reject elements that violate the filter', function() {
+ expect($('.orange').prev('.non-existent')).to.have.length(0);
+ });
+
+ it('should accept elements that satisify the filter', function() {
+ expect($('.orange').prev('.apple')).to.have.length(1);
+ });
+ });
+
+ });
+
+ describe('.prevAll', function() {
+
+ it('() : should return all preceding siblings', function() {
+ var elems = $('.pear').prevAll();
+ expect(elems).to.have.length(2);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ expect(elems[1].attribs['class']).to.equal('apple');
+ });
+
+ it('(no prev) : should return empty for first child', function() {
+ expect($('.apple').prevAll()).to.have.length(0);
+ });
+
+ it('(prevAll on empty object) : should return empty', function() {
+ expect($('.banana').prevAll()).to.have.length(0);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ expect($('.orange, .sweetcorn', food).prevAll()).to.have.length(2);
+ });
+
+ it('() : should not contain duplicate elements', function() {
+ var elems = $('.orange, .pear', food);
+ expect(elems.prevAll()).to.have.length(2);
+ });
+
+ describe('(selector) :', function() {
+ it('should filter returned elements', function() {
+ var elems = $('.pear').prevAll('.apple');
+ expect(elems).to.have.length(1);
+ });
+
+ it('should not consider siblings\'s descendents', function() {
+ var elems = $('#vegetables', food).prevAll('li');
+ expect(elems).to.have.length(0);
+ });
+ });
+
+ });
+
+ describe('.prevUntil', function() {
+
+ it('() : should return all preceding siblings if no selector specified', function() {
+ var elems = $('.pear').prevUntil();
+ expect(elems).to.have.length(2);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ expect(elems[1].attribs['class']).to.equal('apple');
+ });
+
+ it('() : should filter out non-element nodes', function() {
+ var elems = $('');
+ var div = elems.children().last();
+ expect(div.prevUntil()).to.have.length(1);
+ });
+
+ it('() : should operate over all elements in the selection', function() {
+ var elems = $('.pear, .sweetcorn', food);
+ expect(elems.prevUntil()).to.have.length(3);
+ });
+
+ it('() : should not contain duplicate elements', function() {
+ var elems = $('.orange, .pear', food);
+ expect(elems.prevUntil()).to.have.length(2);
+ });
+
+ it('(selector) : should return all preceding siblings until selector', function() {
+ var elems = $('.pear').prevUntil('.apple');
+ expect(elems).to.have.length(1);
+ expect(elems[0].attribs['class']).to.equal('orange');
+ });
+
+ it('(selector not sibling) : should return all preceding siblings', function() {
+ var elems = $('.sweetcorn', food).prevUntil('#fruits');
+ expect(elems).to.have.length(1);
+ expect(elems[0].attribs['class']).to.equal('carrot');
+ });
+
+ it('(selector, filterString) : should return all preceding siblings until selector, filtered by filter', function() {
+ var elems = $('.cider', drinks).prevUntil('.juice', '.water');
+ expect(elems).to.have.length(1);
+ expect(elems[0].attribs['class']).to.equal('water');
+ });
+
+ it('(selector, filterString) : should return all preceding siblings until selector', function() {
+ var elems = $('');
+ var empty = elems.find('li').eq(1).prevUntil(null, 'p');
+ expect(empty).to.have.length(0);
+ });
+
+ it('() : should return an empty object for first child', function() {
+ expect($('.apple').prevUntil()).to.have.length(0);
+ });
+
+ it('() : should return an empty object when called on an empty object', function() {
+ expect($('.banana').prevUntil()).to.have.length(0);
+ });
+
+ it('(node) : should return all previous siblings until the node', function() {
+ var $fruits = $('#fruits').children();
+ var elems = $fruits.eq(2).prevUntil($fruits[0]);
+ expect(elems).to.have.length(1);
+ });
+
+ it('(cheerio object) : should return all previous siblings until any member of the cheerio object', function() {
+ var $drinks = $(drinks).children();
+ var $until = $([$drinks[0], $drinks[1]]);
+ var elems = $drinks.eq(4).prevUntil($until);
+ expect(elems).to.have.length(2);
+ });
+
+ });
+
+ describe('.siblings', function() {
+
+ it('() : should get all the siblings', function() {
+ expect($('.orange').siblings()).to.have.length(2);
+ expect($('#fruits').siblings()).to.have.length(0);
+ expect($('.apple, .carrot', food).siblings()).to.have.length(3);
+ });
+
+ it('(selector) : should get all siblings that match the selector', function() {
+ expect($('.orange').siblings('.apple')).to.have.length(1);
+ expect($('.orange').siblings('.peach')).to.have.length(0);
+ });
+
+ it('(selector) : should throw a SyntaxError if given an invalid selector', function() {
+ expect(function() {
+ $('.orange').siblings(':bah');
+ }).to.throwException(function(err) {
+ expect(err).to.be.a(SyntaxError);
+ });
+ });
+
+ it('(selector) : does not consider the contents of siblings when filtering (GH-374)', function() {
+ expect($('#fruits', food).siblings('li')).to.have.length(0);
+ });
+
+ });
+
+ describe('.parents', function() {
+
+ beforeEach(function() {
+ $ = cheerio.load(food);
+ });
+
+ it('() : should get all of the parents in logical order', function(){
+ var result = $('.orange').parents();
+ expect(result).to.have.length(2);
+ expect(result[0].attribs.id).to.be('fruits');
+ expect(result[1].attribs.id).to.be('food');
+ result = $('#fruits').parents();
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('food');
+ });
+
+ it('(selector) : should get all of the parents that match the selector in logical order', function() {
+ var result = $('.orange').parents('#fruits');
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ result = $('.orange').parents('ul');
+ expect(result).to.have.length(2);
+ expect(result[0].attribs.id).to.be('fruits');
+ expect(result[1].attribs.id).to.be('food');
+ });
+
+ it('() : should not break if the selector does not have any results', function() {
+ var result = $('.saladbar').parents();
+ expect(result).to.have.length(0);
+ });
+
+ it('() : should return an empty set for top-level elements', function() {
+ var result = $('#food').parents();
+ expect(result).to.have.length(0);
+ });
+
+ it('() : should return the parents of every element in the *reveresed* collection, omitting duplicates', function() {
+ var $parents = $('li').parents();
+
+ expect($parents).to.have.length(3);
+ expect($parents[0]).to.be($('#vegetables')[0]);
+ expect($parents[1]).to.be($('#food')[0]);
+ expect($parents[2]).to.be($('#fruits')[0]);
+ });
+
+ });
+
+ describe('.parentsUntil', function() {
+
+ beforeEach(function() {
+ $ = cheerio.load(food);
+ });
+
+ it('() : should get all of the parents in logical order', function() {
+ var result = $('.orange').parentsUntil();
+ expect(result).to.have.length(2);
+ expect(result[0].attribs.id).to.be('fruits');
+ expect(result[1].attribs.id).to.be('food');
+ });
+
+ it('() : should get all of the parents in reversed order, omitting duplicates', function() {
+ var result = $('.apple, .sweetcorn').parentsUntil();
+ expect(result).to.have.length(3);
+ expect(result[0].attribs.id).to.be('vegetables');
+ expect(result[1].attribs.id).to.be('food');
+ expect(result[2].attribs.id).to.be('fruits');
+ });
+
+ it('(selector) : should get all of the parents until selector', function() {
+ var result = $('.orange').parentsUntil('#food');
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ result = $('.orange').parentsUntil('#fruits');
+ expect(result).to.have.length(0);
+ });
+
+ it('(selector not parent) : should return all parents', function() {
+ var result = $('.orange').parentsUntil('.apple');
+ expect(result).to.have.length(2);
+ expect(result[0].attribs.id).to.be('fruits');
+ expect(result[1].attribs.id).to.be('food');
+ });
+
+ it('(selector, filter) : should get all of the parents that match the filter', function() {
+ var result = $('.apple, .sweetcorn').parentsUntil('.saladbar', '#vegetables');
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('vegetables');
+ });
+
+ it('() : should return empty object when called on an empty object', function() {
+ var result = $('.saladbar').parentsUntil();
+ expect(result).to.have.length(0);
+ });
+
+ it('() : should return an empty set for top-level elements', function() {
+ var result = $('#food').parentsUntil();
+ expect(result).to.have.length(0);
+ });
+
+ it('(cheerio object) : should return all parents until any member of the cheerio object', function() {
+ var $fruits = $('#fruits');
+ var $until = $('#food');
+ var result = $fruits.children().eq(1).parentsUntil($until);
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ });
+
+ });
+
+ describe('.parent', function() {
+
+ it('() : should return the parent of each matched element', function() {
+ var result = $('.orange').parent();
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ result = $('li', food).parent();
+ expect(result).to.have.length(2);
+ expect(result[0].attribs.id).to.be('fruits');
+ expect(result[1].attribs.id).to.be('vegetables');
+ });
+
+ it('() : should return an empty object for top-level elements', function() {
+ var result = $('ul').parent();
+ expect(result).to.have.length(0);
+ });
+
+ it('() : should not contain duplicate elements', function() {
+ var result = $('li').parent();
+ expect(result).to.have.length(1);
+ });
+
+ it('(selector) : should filter the matched parent elements by the selector', function() {
+ var result = $('.orange').parent();
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ result = $('li', food).parent('#fruits');
+ expect(result).to.have.length(1);
+ expect(result[0].attribs.id).to.be('fruits');
+ });
+
+ });
+
+ describe('.closest', function() {
+
+ it('() : should return an empty array', function() {
+ var result = $('.orange').closest();
+ expect(result).to.have.length(0);
+ expect(result).to.be.a(cheerio);
+ });
+
+ it('(selector) : should find the closest element that matches the selector, searching through its ancestors and itself', function() {
+ expect($('.orange').closest('.apple')).to.have.length(0);
+ var result = $('.orange', food).closest('#food');
+ expect(result[0].attribs.id).to.be('food');
+ result = $('.orange', food).closest('ul');
+ expect(result[0].attribs.id).to.be('fruits');
+ result = $('.orange', food).closest('li');
+ expect(result[0].attribs['class']).to.be('orange');
+ });
+
+ it('(selector) : should find the closest element of each item, removing duplicates', function() {
+ var result = $('li', food).closest('ul');
+ expect(result).to.have.length(2);
+ });
+
+ it('() : should not break if the selector does not have any results', function() {
+ var result = $('.saladbar', food).closest('ul');
+ expect(result).to.have.length(0);
+ });
+
+ });
+
+ describe('.each', function() {
+
+ it('( (i, elem) -> ) : should loop selected returning fn with (i, elem)', function() {
+ var items = [],
+ classes = ['apple', 'orange', 'pear'];
+ $('li').each(function(idx, elem) {
+ items[idx] = elem;
+ expect(this.attribs['class']).to.equal(classes[idx]);
+ });
+ expect(items[0].attribs['class']).to.equal('apple');
+ expect(items[1].attribs['class']).to.equal('orange');
+ expect(items[2].attribs['class']).to.equal('pear');
+ });
+
+ it('( (i, elem) -> ) : should break iteration when the iterator function returns false', function() {
+ var iterationCount = 0;
+ $('li').each(function(idx) {
+ iterationCount++;
+ return idx < 1;
+ });
+
+ expect(iterationCount).to.equal(2);
+ });
+
+ });
+
+ describe('.map', function() {
+ it('(fn) : should be invoked with the correct arguments and context', function() {
+ var $fruits = $('li');
+ var args = [];
+ var thisVals = [];
+
+ $fruits.map(function() {
+ args.push(Array.prototype.slice.call(arguments));
+ thisVals.push(this);
+ });
+
+ expect(args).to.eql([
+ [0, $fruits[0]],
+ [1, $fruits[1]],
+ [2, $fruits[2]]
+ ]);
+ expect(thisVals).to.eql([
+ $fruits[0],
+ $fruits[1],
+ $fruits[2]
+ ]);
+ });
+
+ it('(fn) : should return an Cheerio object wrapping the returned items', function() {
+ var $fruits = $('li');
+ var $mapped = $fruits.map(function(i) {
+ return $fruits[2 - i];
+ });
+
+ expect($mapped).to.have.length(3);
+ expect($mapped[0]).to.be($fruits[2]);
+ expect($mapped[1]).to.be($fruits[1]);
+ expect($mapped[2]).to.be($fruits[0]);
+ });
+
+ it('(fn) : should ignore `null` and `undefined` returned by iterator', function() {
+ var $fruits = $('li');
+ var retVals = [null, undefined, $fruits[1]];
+
+ var $mapped = $fruits.map(function(i) {
+ return retVals[i];
+ });
+
+ expect($mapped).to.have.length(1);
+ expect($mapped[0]).to.be($fruits[1]);
+ });
+
+ it('(fn) : should preform a shallow merge on arrays returned by iterator', function() {
+ var $fruits = $('li');
+
+ var $mapped = $fruits.map(function() {
+ return [1, [3, 4]];
+ });
+
+ expect($mapped.get()).to.eql([
+ 1, [3, 4],
+ 1, [3, 4],
+ 1, [3, 4]
+ ]);
+ });
+
+ it('(fn) : should tolerate `null` and `undefined` when flattening arrays returned by iterator', function() {
+ var $fruits = $('li');
+
+ var $mapped = $fruits.map(function() {
+ return [null, undefined];
+ });
+
+ expect($mapped.get()).to.eql([
+ null, undefined,
+ null, undefined,
+ null, undefined,
+ ]);
+ });
+ });
+
+ describe('.filter', function() {
+ it('(selector) : should reduce the set of matched elements to those that match the selector', function() {
+ var pear = $('li').filter('.pear').text();
+ expect(pear).to.be('Pear');
+ });
+
+ it('(selector) : should not consider nested elements', function() {
+ var lis = $('#fruits').filter('li');
+ expect(lis).to.have.length(0);
+ });
+
+ it('(selection) : should reduce the set of matched elements to those that are contained in the provided selection', function() {
+ var $fruits = $('li');
+ var $pear = $fruits.filter('.pear, .apple');
+ expect($fruits.filter($pear)).to.have.length(2);
+ });
+
+ it('(element) : should reduce the set of matched elements to those that specified directly', function() {
+ var $fruits = $('li');
+ var pear = $fruits.filter('.pear')[0];
+ expect($fruits.filter(pear)).to.have.length(1);
+ });
+
+ it('(fn) : should reduce the set of matched elements to those that pass the function\'s test', function() {
+ var orange = $('li').filter(function(i, el) {
+ expect(this).to.be(el);
+ expect(el.tagName).to.be('li');
+ expect(i).to.be.a('number');
+ return $(this).attr('class') === 'orange';
+ }).text();
+
+ expect(orange).to.be('Orange');
+ });
+ });
+
+ describe('.not', function() {
+ it('(selector) : should reduce the set of matched elements to those that do not match the selector', function() {
+ var $fruits = $('li');
+
+ var $notPear = $fruits.not('.pear');
+
+ expect($notPear).to.have.length(2);
+ expect($notPear[0]).to.be($fruits[0]);
+ expect($notPear[1]).to.be($fruits[1]);
+ });
+
+ it('(selector) : should not consider nested elements', function() {
+ var lis = $('#fruits').not('li');
+ expect(lis).to.have.length(1);
+ });
+
+ it('(selection) : should reduce the set of matched elements to those that are mot contained in the provided selection', function() {
+ var $fruits = $('li');
+ var $orange = $('.orange');
+
+ var $notOrange = $fruits.not($orange);
+
+ expect($notOrange).to.have.length(2);
+ expect($notOrange[0]).to.be($fruits[0]);
+ expect($notOrange[1]).to.be($fruits[2]);
+ });
+
+ it('(element) : should reduce the set of matched elements to those that specified directly', function() {
+ var $fruits = $('li');
+ var apple = $('.apple')[0];
+
+ var $notApple = $fruits.not(apple);
+
+ expect($notApple).to.have.length(2);
+ expect($notApple[0]).to.be($fruits[1]);
+ expect($notApple[1]).to.be($fruits[2]);
+ });
+
+ it('(fn) : should reduce the set of matched elements to those that do not pass the function\'s test', function() {
+ var $fruits = $('li');
+
+ var $notOrange = $fruits.not(function(i, el) {
+ expect(this).to.be(el);
+ expect(el.name).to.be('li');
+ expect(i).to.be.a('number');
+ return $(this).attr('class') === 'orange';
+ });
+
+ expect($notOrange).to.have.length(2);
+ expect($notOrange[0]).to.be($fruits[0]);
+ expect($notOrange[1]).to.be($fruits[2]);
+ });
+ });
+
+ describe('.has', function() {
+
+ beforeEach(function() {
+ $ = cheerio.load(food);
+ });
+
+ it('(selector) : should reduce the set of matched elements to those with descendants that match the selector', function() {
+ var $fruits = $('#fruits,#vegetables').has('.pear');
+ expect($fruits).to.have.length(1);
+ expect($fruits[0]).to.be($('#fruits')[0]);
+ });
+
+ it('(selector) : should only consider nested elements', function() {
+ var $empty = $('#fruits').has('#fruits');
+ expect($empty).to.have.length(0);
+ });
+
+ it('(element) : should reduce the set of matched elements to those that are ancestors of the provided element', function() {
+ var $fruits = $('#fruits,#vegetables').has($('.pear')[0]);
+ expect($fruits).to.have.length(1);
+ expect($fruits[0]).to.be($('#fruits')[0]);
+ });
+
+ it('(element) : should only consider nested elements', function() {
+ var $fruits = $('#fruits');
+ var fruits = $fruits[0];
+ var $empty = $fruits.has(fruits);
+
+ expect($empty).to.have.length(0);
+ });
+ });
+
+ describe('.first', function() {
+
+ it('() : should return the first item', function() {
+ var $src = $('foobarbaz');
+ var $elem = $src.first();
+ expect($elem.length).to.equal(1);
+ expect($elem[0].childNodes[0].data).to.equal('foo');
+ });
+
+ it('() : should return an empty object for an empty object', function() {
+ var $src = $();
+ var $first = $src.first();
+ expect($first.length).to.equal(0);
+ expect($first[0]).to.be(undefined);
+ });
+
+ });
+
+ describe('.last', function() {
+
+ it('() : should return the last element', function() {
+ var $src = $('foobarbaz');
+ var $elem = $src.last();
+ expect($elem.length).to.equal(1);
+ expect($elem[0].childNodes[0].data).to.equal('baz');
+ });
+
+ it('() : should return an empty object for an empty object', function() {
+ var $src = $();
+ var $last = $src.last();
+ expect($last.length).to.equal(0);
+ expect($last[0]).to.be(undefined);
+ });
+
+ });
+
+ describe('.first & .last', function() {
+
+ it('() : should return equivalent collections if only one element', function() {
+ var $src = $('bar');
+ var $first = $src.first();
+ var $last = $src.last();
+ expect($first.length).to.equal(1);
+ expect($first[0].childNodes[0].data).to.equal('bar');
+ expect($last.length).to.equal(1);
+ expect($last[0].childNodes[0].data).to.equal('bar');
+ expect($first[0]).to.equal($last[0]);
+ });
+
+ });
+
+ describe('.eq', function() {
+
+ function getText(el) {
+ if(!el.length) return '';
+ return el[0].childNodes[0].data;
+ }
+
+ it('(i) : should return the element at the specified index', function() {
+ expect(getText($('li').eq(0))).to.equal('Apple');
+ expect(getText($('li').eq(1))).to.equal('Orange');
+ expect(getText($('li').eq(2))).to.equal('Pear');
+ expect(getText($('li').eq(3))).to.equal('');
+ expect(getText($('li').eq(-1))).to.equal('Pear');
+ });
+
+ });
+
+ describe('.get', function() {
+
+ it('(i) : should return the element at the specified index', function() {
+ var children = $('#fruits').children();
+ expect(children.get(0)).to.be(children[0]);
+ expect(children.get(1)).to.be(children[1]);
+ expect(children.get(2)).to.be(children[2]);
+ });
+
+ it('(-1) : should return the element indexed from the end of the collection', function() {
+ var children = $('#fruits').children();
+ expect(children.get(-1)).to.be(children[2]);
+ expect(children.get(-2)).to.be(children[1]);
+ expect(children.get(-3)).to.be(children[0]);
+ });
+
+ it('() : should return an array containing all of the collection', function() {
+ var children = $('#fruits').children();
+ var all = children.get();
+ expect(Array.isArray(all)).to.be.ok();
+ expect(all).to.eql([
+ children[0],
+ children[1],
+ children[2]
+ ]);
+ });
+
+ });
+
+ describe('.index', function() {
+ describe('() : ', function() {
+ it('returns the index of a child amongst its siblings', function() {
+ expect($('.orange').index()).to.be(1);
+ });
+ it('returns -1 when the selection has no parent', function() {
+ expect($('').index()).to.be(-1);
+ });
+ });
+
+ describe('(selector) : ', function() {
+ it('returns the index of the first element in the set matched by `selector`', function() {
+ expect($('.apple').index('#fruits, li')).to.be(1);
+ });
+ it('returns -1 when the item is not present in the set matched by `selector`', function() {
+ expect($('.apple').index('#fuits')).to.be(-1);
+ });
+ it('returns -1 when the first element in the set has no parent', function() {
+ expect($('').index('*')).to.be(-1);
+ });
+ });
+
+ describe('(node) : ', function() {
+ it('returns the index of the given node within the current selection', function() {
+ var $lis = $('li');
+ expect($lis.index($lis.get(1))).to.be(1);
+ });
+ it('returns the index of the given node within the current selection when the current selection has no parent', function() {
+ var $apple = $('.apple').remove();
+
+ expect($apple.index($apple.get(0))).to.be(0);
+ });
+ it('returns -1 when the given node is not present in the current selection', function() {
+ expect($('li').index($('#fruits').get(0))).to.be(-1);
+ });
+ it('returns -1 when the current selection is empty', function() {
+ expect($('.not-fruit').index($('#fruits').get(0))).to.be(-1);
+ });
+ });
+
+ describe('(selection) : ', function() {
+ it('returns the index of the first node in the provided selection within the current selection', function() {
+ var $lis = $('li');
+ expect($lis.index($('.orange, .pear'))).to.be(1);
+ });
+ it('returns -1 when the given node is not present in the current selection', function() {
+ expect($('li').index($('#fruits'))).to.be(-1);
+ });
+ it('returns -1 when the current selection is empty', function() {
+ expect($('.not-fruit').index($('#fruits'))).to.be(-1);
+ });
+ });
+ });
+
+ describe('.slice', function() {
+
+ function getText(el) {
+ if(!el.length) return '';
+ return el[0].childNodes[0].data;
+ }
+
+ it('(start) : should return all elements after the given index', function() {
+ var sliced = $('li').slice(1);
+ expect(sliced).to.have.length(2);
+ expect(getText(sliced.eq(0))).to.equal('Orange');
+ expect(getText(sliced.eq(1))).to.equal('Pear');
+ });
+
+ it('(start, end) : should return all elements matching the given range', function() {
+ var sliced = $('li').slice(1, 2);
+ expect(sliced).to.have.length(1);
+ expect(getText(sliced.eq(0))).to.equal('Orange');
+ });
+
+ it('(-start) : should return element matching the offset from the end', function() {
+ var sliced = $('li').slice(-1);
+ expect(sliced).to.have.length(1);
+ expect(getText(sliced.eq(0))).to.equal('Pear');
+ });
+
+ });
+
+ describe('.end() :', function() {
+ var $fruits;
+
+ beforeEach(function() {
+ $fruits = $('#fruits').children();
+ });
+
+ it('returns an empty object at the end of the chain', function() {
+ expect($fruits.end().end().end()).to.be.ok();
+ expect($fruits.end().end().end()).to.have.length(0);
+ });
+ it('find', function() {
+ expect($fruits.find('.apple').end()).to.be($fruits);
+ });
+ it('filter', function() {
+ expect($fruits.filter('.apple').end()).to.be($fruits);
+ });
+ it('map', function() {
+ expect($fruits.map(function() { return this; }).end()).to.be($fruits);
+ });
+ it('contents', function() {
+ expect($fruits.contents().end()).to.be($fruits);
+ });
+ it('eq', function() {
+ expect($fruits.eq(1).end()).to.be($fruits);
+ });
+ it('first', function() {
+ expect($fruits.first().end()).to.be($fruits);
+ });
+ it('last', function() {
+ expect($fruits.last().end()).to.be($fruits);
+ });
+ it('slice', function() {
+ expect($fruits.slice(1).end()).to.be($fruits);
+ });
+ it('children', function() {
+ expect($fruits.children().end()).to.be($fruits);
+ });
+ it('parent', function() {
+ expect($fruits.parent().end()).to.be($fruits);
+ });
+ it('parents', function() {
+ expect($fruits.parents().end()).to.be($fruits);
+ });
+ it('closest', function() {
+ expect($fruits.closest('ul').end()).to.be($fruits);
+ });
+ it('siblings', function() {
+ expect($fruits.siblings().end()).to.be($fruits);
+ });
+ it('next', function() {
+ expect($fruits.next().end()).to.be($fruits);
+ });
+ it('nextAll', function() {
+ expect($fruits.nextAll().end()).to.be($fruits);
+ });
+ it('prev', function() {
+ expect($fruits.prev().end()).to.be($fruits);
+ });
+ it('prevAll', function() {
+ expect($fruits.prevAll().end()).to.be($fruits);
+ });
+ it('clone', function() {
+ expect($fruits.clone().end()).to.be($fruits);
+ });
+ });
+
+ describe('.add', function() {
+ var $ = cheerio.load(food);
+ var $fruits = $('#fruits');
+ var $apple = $('.apple');
+ var $orange = $('.orange');
+ var $pear = $('.pear');
+ var $carrot = $('.carrot');
+ var $sweetcorn = $('.sweetcorn');
+
+ describe('(selector', function() {
+ describe(') :', function() {
+ describe('matched element', function() {
+ it('occurs before current selection', function() {
+ var $selection = $orange.add('.apple');
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('is identical to the current selection', function() {
+ var $selection = $orange.add('.orange');
+
+ expect($selection).to.have.length(1);
+ expect($selection[0]).to.be($orange[0]);
+ });
+ it('occurs after current selection', function() {
+ var $selection = $orange.add('.pear');
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($orange[0]);
+ expect($selection[1]).to.be($pear[0]);
+ });
+ it('contains the current selection', function() {
+ var $selection = $orange.add('#fruits');
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('is a child of the current selection', function() {
+ var $selection = $fruits.add('.orange');
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ });
+ describe('matched elements', function() {
+ it('occur before the current selection', function() {
+ var $selection = $pear.add('.apple, .orange');
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('include the current selection', function() {
+ var $selection = $pear.add('#fruits li');
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur after the current selection', function() {
+ var $selection = $apple.add('.orange, .pear');
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur within the current selection', function() {
+ var $selection = $fruits.add('#fruits li');
+
+ expect($selection).to.have.length(4);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($apple[0]);
+ expect($selection[2]).to.be($orange[0]);
+ expect($selection[3]).to.be($pear[0]);
+ });
+ });
+ });
+ it(', context)', function() {
+ var $selection = $fruits.add('li', '#vegetables');
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($carrot[0]);
+ expect($selection[2]).to.be($sweetcorn[0]);
+ });
+ });
+
+ describe('(element) :', function() {
+ describe('honors document order when element occurs', function() {
+ it('before the current selection', function() {
+ var $selection = $orange.add($apple[0]);
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('after the current selection', function() {
+ var $selection = $orange.add($pear[0]);
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($orange[0]);
+ expect($selection[1]).to.be($pear[0]);
+ });
+ it('within the current selection', function() {
+ var $selection = $fruits.add($orange[0]);
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('as an ancestor of the current selection', function() {
+ var $selection = $orange.add($fruits[0]);
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ });
+ it('does not insert an element already contained within the current selection', function() {
+ var $selection = $apple.add($apple[0]);
+
+ expect($selection).to.have.length(1);
+ expect($selection[0]).to.be($apple[0]);
+ });
+ });
+ describe('([elements]) : elements', function() {
+ it('occur before the current selection', function() {
+ var $selection = $pear.add($('.apple, .orange').get());
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('include the current selection', function() {
+ var $selection = $pear.add($('#fruits li').get());
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur after the current selection', function() {
+ var $selection = $apple.add($('.orange, .pear').get());
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur within the current selection', function() {
+ var $selection = $fruits.add($('#fruits li').get());
+
+ expect($selection).to.have.length(4);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($apple[0]);
+ expect($selection[2]).to.be($orange[0]);
+ expect($selection[3]).to.be($pear[0]);
+ });
+ });
+
+ /**
+ * Element order is undefined in this case, so it should not be asserted
+ * here.
+ *
+ * > If the collection consists of elements from different documents or
+ * > ones not in any document, the sort order is undefined.
+ *
+ * http://api.jquery.com/add/
+ */
+ it('(html) : correctly parses and adds the new elements', function() {
+ var $selection = $apple.add('banana');
+
+ expect($selection).to.have.length(2);
+ expect($selection.is('.apple')).to.be(true);
+ expect($selection.is('.banana')).to.be(true);
+ });
+
+ describe('(selection) :', function() {
+ describe('element in selection', function() {
+ it('occurs before current selection', function() {
+ var $selection = $orange.add($('.apple'));
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('is identical to the current selection', function() {
+ var $selection = $orange.add($('.orange'));
+
+ expect($selection).to.have.length(1);
+ expect($selection[0]).to.be($orange[0]);
+ });
+ it('occurs after current selection', function() {
+ var $selection = $orange.add($('.pear'));
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($orange[0]);
+ expect($selection[1]).to.be($pear[0]);
+ });
+ it('contains the current selection', function() {
+ var $selection = $orange.add($('#fruits'));
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ it('is a child of the current selection', function() {
+ var $selection = $fruits.add($('.orange'));
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($orange[0]);
+ });
+ });
+ describe('elements in the selection', function() {
+ it('occur before the current selection', function() {
+ var $selection = $pear.add($('.apple, .orange'));
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('include the current selection', function() {
+ var $selection = $pear.add($('#fruits li'));
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur after the current selection', function() {
+ var $selection = $apple.add($('.orange, .pear'));
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($apple[0]);
+ expect($selection[1]).to.be($orange[0]);
+ expect($selection[2]).to.be($pear[0]);
+ });
+ it('occur within the current selection', function() {
+ var $selection = $fruits.add($('#fruits li'));
+
+ expect($selection).to.have.length(4);
+ expect($selection[0]).to.be($fruits[0]);
+ expect($selection[1]).to.be($apple[0]);
+ expect($selection[2]).to.be($orange[0]);
+ expect($selection[3]).to.be($pear[0]);
+ });
+ });
+ });
+ });
+
+ describe('.addBack', function() {
+ describe('() : ', function() {
+ it('includes siblings and self', function() {
+ var $selection = $('.orange').siblings().addBack();
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($('.apple')[0]);
+ expect($selection[1]).to.be($('.orange')[0]);
+ expect($selection[2]).to.be($('.pear')[0]);
+ });
+ it('includes children and self', function() {
+ var $selection = $('#fruits').children().addBack();
+
+ expect($selection).to.have.length(4);
+ expect($selection[0]).to.be($('#fruits')[0]);
+ expect($selection[1]).to.be($('.apple')[0]);
+ expect($selection[2]).to.be($('.orange')[0]);
+ expect($selection[3]).to.be($('.pear')[0]);
+ });
+ it('includes parent and self', function() {
+ var $selection = $('.apple').parent().addBack();
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($('#fruits')[0]);
+ expect($selection[1]).to.be($('.apple')[0]);
+ });
+ it('includes parents and self', function() {
+ var $ = cheerio.load(food);
+ var $selection = $('.apple').parents().addBack();
+
+ expect($selection).to.have.length(3);
+ expect($selection[0]).to.be($('#food')[0]);
+ expect($selection[1]).to.be($('#fruits')[0]);
+ expect($selection[2]).to.be($('.apple')[0]);
+ });
+ });
+ it('(filter) : filters the previous selection', function() {
+ var $selection = $('li').eq(1).addBack('.apple');
+
+ expect($selection).to.have.length(2);
+ expect($selection[0]).to.be($('.apple')[0]);
+ expect($selection[1]).to.be($('.orange')[0]);
+ });
+ });
+});
diff --git a/node_modules/cheerio/test/api/utils.js b/node_modules/cheerio/test/api/utils.js
new file mode 100644
index 00000000..2ece35b2
--- /dev/null
+++ b/node_modules/cheerio/test/api/utils.js
@@ -0,0 +1,211 @@
+var expect = require('expect.js'),
+ fixtures = require('../fixtures'),
+ cheerio = require('../..');
+
+describe('cheerio', function() {
+
+ describe('.html', function() {
+
+ it('() : should return innerHTML; $.html(obj) should return outerHTML', function() {
+ var $div = cheerio('div', 'foobar
');
+ var span = $div.children()[1];
+ expect(cheerio(span).html()).to.equal('bar');
+ expect(cheerio.html(span)).to.equal('bar');
+ });
+
+ it('() : should accept an object, an array, or a cheerio object', function() {
+ var $span = cheerio('foo');
+ expect(cheerio.html($span[0])).to.equal('foo');
+ expect(cheerio.html($span)).to.equal('foo');
+ });
+
+ it('() : should be able to set to an empty string', function() {
+ var $elem = cheerio('foo').html('');
+ expect(cheerio.html($elem)).to.equal('');
+ });
+
+ it('() : of empty cheerio object should return null', function() {
+ expect(cheerio().html()).to.be(null);
+ });
+
+ it('(selector) : should return the outerHTML of the selected element', function() {
+ var $ = cheerio.load(fixtures.fruits);
+ expect($.html('.pear')).to.equal('Pear');
+ });
+ });
+
+
+
+ describe('.load', function() {
+
+ it('(html) : should retain original root after creating a new node', function() {
+ var $html = cheerio.load('');
+ expect($html('body')).to.have.length(1);
+ $html('