| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677 |
- import { describe, it, expect, beforeEach } from 'vitest';
- import { load, type CheerioAPI } from '../index.js';
- import { Cheerio } from '../cheerio.js';
- import { type AnyNode, type Element, type Text, isText } from 'domhandler';
- import {
- cheerio,
- food,
- fruits,
- eleven,
- drinks,
- text,
- forms,
- mixedText,
- vegetables,
- } from '../__fixtures__/fixtures.js';
- function getText(el: Cheerio<Element>) {
- if (el.length === 0) return undefined;
- const [firstChild] = el[0].childNodes;
- return isText(firstChild) ? firstChild.data : undefined;
- }
- describe('$(...)', () => {
- let $: CheerioAPI;
- beforeEach(() => {
- $ = load(fruits);
- });
- describe('.load', () => {
- it('should throw a TypeError if given invalid input', () => {
- expect(() => {
- (load as any)();
- }).toThrow('cheerio.load() expects a string');
- });
- });
- describe('.find', () => {
- it('() : should find nothing', () => {
- expect($('ul').find()).toHaveLength(0);
- });
- it('(single) : should find one descendant', () => {
- expect($('#fruits').find('.apple')[0].attribs).toHaveProperty(
- 'class',
- 'apple',
- );
- });
- // #1679 - text tags not filtered
- it('(single) : should filter out text nodes', () => {
- const $root = $(`<html>\n${fruits.replace(/></g, '>\n<')}\n</html>`);
- expect($root.find('.apple')[0].attribs).toHaveProperty('class', 'apple');
- });
- it('(many) : should find all matching descendant', () => {
- expect($('#fruits').find('li')).toHaveLength(3);
- });
- it('(many) : should merge all selected elems with matching descendants', () => {
- expect($('#fruits, #food', food).find('.apple')).toHaveLength(1);
- });
- it('(invalid single) : should return empty if cant find', () => {
- expect($('ul').find('blah')).toHaveLength(0);
- });
- it('(invalid single) : should query descendants only', () => {
- expect($('#fruits').find('ul')).toHaveLength(0);
- });
- it('should return empty if search already empty result', () => {
- expect($('#not-fruits').find('li')).toHaveLength(0);
- });
- it('should lowercase selectors', () => {
- expect($('#fruits').find('LI')).toHaveLength(3);
- });
- it('should query immediate descendant only', () => {
- const q = load('<foo><bar><bar></bar><bar></bar></bar></foo>');
- expect(q('foo').find('> bar')).toHaveLength(1);
- });
- it('should find siblings', () => {
- const q = load('<p class=a><p class=b></p>');
- expect(q('.a').find('+.b')).toHaveLength(1);
- expect(q('.a').find('~.b')).toHaveLength(1);
- expect(q('.a').find('+.a')).toHaveLength(0);
- expect(q('.a').find('~.a')).toHaveLength(0);
- });
- it('should query case-sensitively when in xml mode', () => {
- const q = load('<caseSenSitive allTheWay>', { xml: true });
- expect(q('caseSenSitive')).toHaveLength(1);
- expect(q('[allTheWay]')).toHaveLength(1);
- expect(q('casesensitive')).toHaveLength(0);
- expect(q('[alltheway]')).toHaveLength(0);
- });
- it('should throw an Error if given an invalid selector', () => {
- expect(() => {
- $('#fruits').find(':bah');
- }).toThrow('Unknown pseudo-class :bah');
- });
- it('should respect the `lowerCaseTags` option (#3495)', () => {
- const q = load(
- `<parentTag class="myClass">
- <firstTag> <child> blah </child> </firstTag>
- <secondTag> <child> blah </child> </secondTag>
- </parentTag> `,
- {
- xml: {
- xmlMode: true,
- decodeEntities: false,
- lowerCaseTags: true,
- lowerCaseAttributeNames: false,
- recognizeSelfClosing: true,
- },
- },
- );
- expect(q('.myClass').find('firstTag > child')).toHaveLength(1);
- });
- describe('(cheerio object) :', () => {
- it('returns only those nodes contained within the current selection', () => {
- const q = load(food);
- const $selection = q('#fruits').find(q('li'));
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe(q('.apple')[0]);
- expect($selection[1]).toBe(q('.orange')[0]);
- expect($selection[2]).toBe(q('.pear')[0]);
- });
- it('returns only those nodes contained within any element in the current selection', () => {
- const q = load(food);
- const $selection = q('.apple, #vegetables').find(q('li'));
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe(q('.carrot')[0]);
- expect($selection[1]).toBe(q('.sweetcorn')[0]);
- });
- });
- describe('(node) :', () => {
- it('returns node when contained within the current selection', () => {
- const q = load(food);
- const $selection = q('#fruits').find(q('.apple')[0]);
- expect($selection).toHaveLength(1);
- expect($selection[0]).toBe(q('.apple')[0]);
- });
- it('returns node when contained within any element the current selection', () => {
- const q = load(food);
- const $selection = q('#fruits, #vegetables').find(q('.carrot')[0]);
- expect($selection).toHaveLength(1);
- expect($selection[0]).toBe(q('.carrot')[0]);
- });
- it('does not return node that is not contained within the current selection', () => {
- const q = load(food);
- const $selection = q('#fruits').find(q('.carrot')[0]);
- expect($selection).toHaveLength(0);
- });
- });
- });
- describe('.children', () => {
- it('() : should get all children', () => {
- expect($('ul').children()).toHaveLength(3);
- });
- it('() : should skip text nodes', () => {
- expect($(mixedText).children()).toHaveLength(0);
- });
- it('() : should return children of all matched elements', () => {
- expect($('ul ul', food).children()).toHaveLength(5);
- });
- it('(selector) : should return children matching selector', () => {
- const { attribs } = $('ul').children('.orange')[0];
- expect(attribs).toHaveProperty('class', 'orange');
- });
- it('(invalid selector) : should return empty', () => {
- expect($('ul').children('.lulz')).toHaveLength(0);
- });
- it('should only match immediate children, not ancestors', () => {
- expect($(food).children('li')).toHaveLength(0);
- });
- });
- describe('.contents', () => {
- beforeEach(() => {
- $ = load(text);
- });
- it('() : should get all contents', () => {
- expect($('p').contents()).toHaveLength(5);
- });
- it('() : should skip text nodes', () => {
- expect($(mixedText).contents()).toHaveLength(2);
- });
- it('() : should include text nodes', () => {
- expect($('p').contents().first()[0].type).toBe('text');
- });
- it('() : should include comment nodes', () => {
- expect($('p').contents().last()[0].type).toBe('comment');
- });
- });
- describe('.next', () => {
- it('() : should return next element', () => {
- const { attribs } = $('.orange').next()[0];
- expect(attribs).toHaveProperty('class', 'pear');
- });
- it('() : should skip text nodes', () => {
- expect($(mixedText).next()[0]).toHaveProperty('name', 'b');
- });
- it('(no next) : should return empty for last child', () => {
- expect($('.pear').next()).toHaveLength(0);
- });
- it('(next on empty object) : should return empty', () => {
- expect($('.banana').next()).toHaveLength(0);
- });
- it('() : should operate over all elements in the selection', () => {
- expect($('.apple, .orange', food).next()).toHaveLength(2);
- });
- it('() : should return elements in order', () => {
- const result = load(eleven)('.red').next();
- expect(result).toHaveLength(2);
- expect(result.eq(0).text()).toBe('Six');
- expect(result.eq(1).text()).toBe('Ten');
- });
- it('should reject elements that violate the filter', () => {
- expect($('.apple').next('.non-existent')).toHaveLength(0);
- });
- it('should accept elements that satisify the filter', () => {
- expect($('.apple').next('.orange')).toHaveLength(1);
- });
- describe('(selector) :', () => {
- it('should reject elements that violate the filter', () => {
- expect($('.apple').next('.non-existent')).toHaveLength(0);
- });
- it('should accept elements that satisify the filter', () => {
- expect($('.apple').next('.orange')).toHaveLength(1);
- });
- });
- });
- describe('.nextAll', () => {
- it('() : should return all following siblings', () => {
- const elems = $('.apple').nextAll();
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- expect(elems[1].attribs).toHaveProperty('class', 'pear');
- });
- it('(no next) : should return empty for last child', () => {
- expect($('.pear').nextAll()).toHaveLength(0);
- });
- it('(nextAll on empty object) : should return empty', () => {
- expect($('.banana').nextAll()).toHaveLength(0);
- });
- it('() : should operate over all elements in the selection', () => {
- expect($('.apple, .carrot', food).nextAll()).toHaveLength(3);
- });
- it('() : should not contain duplicate elements', () => {
- const elems = $('.apple, .orange', food);
- expect(elems.nextAll()).toHaveLength(2);
- });
- it('() : should not contain text elements', () => {
- const elems = $('.apple', fruits.replace(/></g, '>\n<'));
- expect(elems.nextAll()).toHaveLength(2);
- });
- describe('(selector) :', () => {
- it('should filter according to the provided selector', () => {
- expect($('.apple').nextAll('.pear')).toHaveLength(1);
- });
- it("should not consider siblings' contents when filtering", () => {
- expect($('#fruits', food).nextAll('li')).toHaveLength(0);
- });
- });
- });
- describe('.nextUntil', () => {
- it('() : should return all following siblings if no selector specified', () => {
- const elems = $('.apple', food).nextUntil();
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- expect(elems[1].attribs).toHaveProperty('class', 'pear');
- });
- it('() : should filter out non-element nodes', () => {
- const elems = $('<div><div></div><!-- comment -->text<div></div></div>');
- const div = elems.children().eq(0);
- expect(div.nextUntil()).toHaveLength(1);
- });
- it('() : should operate over all elements in the selection', () => {
- const elems = $('.apple, .carrot', food);
- expect(elems.nextUntil()).toHaveLength(3);
- });
- it('() : should not contain duplicate elements', () => {
- const elems = $('.apple, .orange', food);
- expect(elems.nextUntil()).toHaveLength(2);
- });
- it('(selector) : should return all following siblings until selector', () => {
- const elems = $('.apple', food).nextUntil('.pear');
- expect(elems).toHaveLength(1);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- });
- it('(selector) : should support selector matching multiple elements', () => {
- const elems = $('#disabled', forms).nextUntil('option, #unnamed');
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('id', 'submit');
- expect(elems[1].attribs).toHaveProperty('id', 'select');
- });
- it('(selector not sibling) : should return all following siblings', () => {
- const elems = $('.apple').nextUntil('#vegetables');
- expect(elems).toHaveLength(2);
- });
- it('(selector, filterString) : should return all following siblings until selector, filtered by filter', () => {
- const elems = $('.beer', drinks).nextUntil('.water', '.milk');
- expect(elems).toHaveLength(1);
- expect(elems[0].attribs).toHaveProperty('class', 'milk');
- });
- it('(null, filterString) : should return all following siblings until selector, filtered by filter', () => {
- const elems = $('<ul><li></li><li><p></p></li></ul>');
- const empty = elems.find('li').eq(0).nextUntil(null, 'p');
- expect(empty).toHaveLength(0);
- });
- it('() : should return an empty object for last child', () => {
- expect($('.pear').nextUntil()).toHaveLength(0);
- });
- it('() : should return an empty object when called on an empty object', () => {
- expect($('.banana').nextUntil()).toHaveLength(0);
- });
- it('(node) : should return all following siblings until the node', () => {
- const $fruits = $('#fruits').children();
- const elems = $fruits.eq(0).nextUntil($fruits[2]);
- expect(elems).toHaveLength(1);
- });
- it('(cheerio object) : should return all following siblings until any member of the cheerio object', () => {
- const $drinks = $(drinks).children();
- const $until = $([$drinks[4], $drinks[3]]);
- const elems = $drinks.eq(0).nextUntil($until);
- expect(elems).toHaveLength(2);
- });
- });
- describe('.prev', () => {
- it('() : should return previous element', () => {
- const { attribs } = $('.orange').prev()[0];
- expect(attribs).toHaveProperty('class', 'apple');
- });
- it('() : should skip text nodes', () => {
- expect($($(mixedText)[2]).prev()[0]).toHaveProperty('name', 'a');
- });
- it('(no prev) : should return empty for first child', () => {
- expect($('.apple').prev()).toHaveLength(0);
- });
- it('(prev on empty object) : should return empty', () => {
- expect($('.banana').prev()).toHaveLength(0);
- });
- it('() : should operate over all elements in the selection', () => {
- expect($('.orange, .pear', food).prev()).toHaveLength(2);
- });
- it('() : should maintain elements order', () => {
- const sel = load(eleven)('.sel');
- expect(sel).toHaveLength(3);
- expect(sel.eq(0).text()).toBe('Three');
- expect(sel.eq(1).text()).toBe('Nine');
- expect(sel.eq(2).text()).toBe('Eleven');
- // Swap last elements
- const el = sel[2];
- sel[2] = sel[1];
- sel[1] = el;
- const result = sel.prev();
- expect(result).toHaveLength(3);
- expect(result.eq(0).text()).toBe('Two');
- expect(result.eq(1).text()).toBe('Ten');
- expect(result.eq(2).text()).toBe('Eight');
- });
- describe('(selector) :', () => {
- it('should reject elements that violate the filter', () => {
- expect($('.orange').prev('.non-existent')).toHaveLength(0);
- });
- it('should accept elements that satisify the filter', () => {
- expect($('.orange').prev('.apple')).toHaveLength(1);
- });
- it('(selector) : should reject elements that violate the filter', () => {
- expect($('.orange').prev('.non-existent')).toHaveLength(0);
- });
- it('(selector) : should accept elements that satisify the filter', () => {
- expect($('.orange').prev('.apple')).toHaveLength(1);
- });
- });
- });
- describe('.prevAll', () => {
- it('() : should return all preceding siblings', () => {
- const elems = $('.pear').prevAll();
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- expect(elems[1].attribs).toHaveProperty('class', 'apple');
- });
- it('() : should not contain text elements', () => {
- const elems = $('.pear', fruits.replace(/></g, '>\n<'));
- expect(elems.prevAll()).toHaveLength(2);
- });
- it('(no prev) : should return empty for first child', () => {
- expect($('.apple').prevAll()).toHaveLength(0);
- });
- it('(prevAll on empty object) : should return empty', () => {
- expect($('.banana').prevAll()).toHaveLength(0);
- });
- it('() : should operate over all elements in the selection', () => {
- expect($('.orange, .sweetcorn', food).prevAll()).toHaveLength(2);
- });
- it('() : should not contain duplicate elements', () => {
- const elems = $('.orange, .pear', food);
- expect(elems.prevAll()).toHaveLength(2);
- });
- describe('(selector) :', () => {
- it('should filter returned elements', () => {
- const elems = $('.pear').prevAll('.apple');
- expect(elems).toHaveLength(1);
- });
- it("should not consider siblings's descendents", () => {
- const elems = $('#vegetables', food).prevAll('li');
- expect(elems).toHaveLength(0);
- });
- });
- });
- describe('.prevUntil', () => {
- it('() : should return all preceding siblings if no selector specified', () => {
- const elems = $('.pear').prevUntil();
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- expect(elems[1].attribs).toHaveProperty('class', 'apple');
- });
- it('() : should filter out non-element nodes', () => {
- const elems = $(
- '<div class="1"><div class="2"></div><!-- comment -->text<div class="3"></div></div>',
- );
- const div = elems.children().last();
- expect(div.prevUntil()).toHaveLength(1);
- });
- it('() : should operate over all elements in the selection', () => {
- const elems = $('.pear, .sweetcorn', food);
- expect(elems.prevUntil()).toHaveLength(3);
- });
- it('() : should not contain duplicate elements', () => {
- const elems = $('.orange, .pear', food);
- expect(elems.prevUntil()).toHaveLength(2);
- });
- it('(selector) : should return all preceding siblings until selector', () => {
- const elems = $('.pear').prevUntil('.apple');
- expect(elems).toHaveLength(1);
- expect(elems[0].attribs).toHaveProperty('class', 'orange');
- });
- it('(selector) : should support selector matching multiple elements', () => {
- const elems = $('#unnamed', forms).prevUntil('option, #disabled');
- expect(elems).toHaveLength(2);
- expect(elems[0].attribs).toHaveProperty('id', 'select');
- expect(elems[1].attribs).toHaveProperty('id', 'submit');
- });
- it('(selector not sibling) : should return all preceding siblings', () => {
- const elems = $('.sweetcorn', food).prevUntil('#fruits');
- expect(elems).toHaveLength(1);
- expect(elems[0].attribs).toHaveProperty('class', 'carrot');
- });
- it('(selector, filterString) : should return all preceding siblings until selector, filtered by filter', () => {
- const elems = $('.cider', drinks).prevUntil('.juice', '.water');
- expect(elems).toHaveLength(1);
- expect(elems[0].attribs).toHaveProperty('class', 'water');
- });
- it('(selector, filterString) : should return all preceding siblings until selector', () => {
- const elems = $('<ul><li><p></p></li><li></li></ul>');
- const empty = elems.find('li').eq(1).prevUntil(null, 'p');
- expect(empty).toHaveLength(0);
- });
- it('() : should return an empty object for first child', () => {
- expect($('.apple').prevUntil()).toHaveLength(0);
- });
- it('() : should return an empty object when called on an empty object', () => {
- expect($('.banana').prevUntil()).toHaveLength(0);
- });
- it('(node) : should return all previous siblings until the node', () => {
- const $fruits = $('#fruits').children();
- const elems = $fruits.eq(2).prevUntil($fruits[0]);
- expect(elems).toHaveLength(1);
- });
- it('(cheerio object) : should return all previous siblings until any member of the cheerio object', () => {
- const $drinks = $(drinks).children();
- const $until = $([$drinks[0], $drinks[1]]);
- const elems = $drinks.eq(4).prevUntil($until);
- expect(elems).toHaveLength(2);
- });
- });
- describe('.siblings', () => {
- it('() : should get all the siblings', () => {
- expect($('.orange').siblings()).toHaveLength(2);
- expect($('#fruits').siblings()).toHaveLength(0);
- expect($('.apple, .carrot', food).siblings()).toHaveLength(3);
- });
- it('(selector) : should get all siblings that match the selector', () => {
- expect($('.orange').siblings('.apple')).toHaveLength(1);
- expect($('.orange').siblings('.peach')).toHaveLength(0);
- });
- it('(selector) : should throw an Error if given an invalid selector', () => {
- expect(() => {
- $('.orange').siblings(':bah');
- }).toThrow('Unknown pseudo-class :bah');
- });
- it('(selector) : does not consider the contents of siblings when filtering (GH-374)', () => {
- expect($('#fruits', food).siblings('li')).toHaveLength(0);
- });
- it('() : when two elements are siblings to each other they have to be included', () => {
- const result = load(eleven)('.sel').siblings();
- expect(result).toHaveLength(7);
- expect(result.eq(0).text()).toBe('One');
- expect(result.eq(1).text()).toBe('Two');
- expect(result.eq(2).text()).toBe('Four');
- expect(result.eq(3).text()).toBe('Eight');
- expect(result.eq(4).text()).toBe('Nine');
- expect(result.eq(5).text()).toBe('Ten');
- expect(result.eq(6).text()).toBe('Eleven');
- });
- it('(selector) : when two elements are siblings to each other they have to be included', () => {
- const result = load(eleven)('.sel').siblings('.red');
- expect(result).toHaveLength(2);
- expect(result.eq(0).text()).toBe('Four');
- expect(result.eq(1).text()).toBe('Nine');
- });
- it('(cheerio) : test filtering with cheerio object', () => {
- const doc = load(eleven);
- const result = doc('.sel').siblings(doc(':not([class])'));
- expect(result).toHaveLength(4);
- expect(result.eq(0).text()).toBe('One');
- expect(result.eq(1).text()).toBe('Two');
- expect(result.eq(2).text()).toBe('Eight');
- expect(result.eq(3).text()).toBe('Ten');
- });
- });
- describe('.parents', () => {
- beforeEach(() => {
- $ = load(food);
- });
- it('() : should get all of the parents in logical order', () => {
- const orange = $('.orange').parents();
- expect(orange).toHaveLength(4);
- expect(orange[0].attribs).toHaveProperty('id', 'fruits');
- expect(orange[1].attribs).toHaveProperty('id', 'food');
- expect(orange[2].tagName).toBe('body');
- expect(orange[3].tagName).toBe('html');
- const fruits = $('#fruits').parents();
- expect(fruits).toHaveLength(3);
- expect(fruits[0].attribs).toHaveProperty('id', 'food');
- expect(fruits[1].tagName).toBe('body');
- expect(fruits[2].tagName).toBe('html');
- });
- it('(selector) : should get all of the parents that match the selector in logical order', () => {
- const fruits = $('.orange').parents('#fruits');
- expect(fruits).toHaveLength(1);
- expect(fruits[0].attribs).toHaveProperty('id', 'fruits');
- const uls = $('.orange').parents('ul');
- expect(uls).toHaveLength(2);
- expect(uls[0].attribs).toHaveProperty('id', 'fruits');
- expect(uls[1].attribs).toHaveProperty('id', 'food');
- });
- it('() : should not break if the selector does not have any results', () => {
- const result = $('.saladbar').parents();
- expect(result).toHaveLength(0);
- });
- it('() : should return an empty set for top-level elements', () => {
- const result = $('html').parents();
- expect(result).toHaveLength(0);
- });
- it('() : should return the parents of every element in the *reveresed* collection, omitting duplicates', () => {
- const $parents = $('li').parents();
- expect($parents).toHaveLength(5);
- expect($parents[0]).toBe($('#vegetables')[0]);
- expect($parents[1]).toBe($('#fruits')[0]);
- expect($parents[2]).toBe($('#food')[0]);
- expect($parents[3]).toBe($('body')[0]);
- expect($parents[4]).toBe($('html')[0]);
- });
- });
- describe('.parentsUntil', () => {
- beforeEach(() => {
- $ = load(food);
- });
- it('() : should get all of the parents in logical order', () => {
- const result = $('.orange').parentsUntil();
- expect(result).toHaveLength(4);
- expect(result[0].attribs).toHaveProperty('id', 'fruits');
- expect(result[1].attribs).toHaveProperty('id', 'food');
- expect(result[2].tagName).toBe('body');
- expect(result[3].tagName).toBe('html');
- });
- it('() : should get all of the parents in reversed order, omitting duplicates', () => {
- const result = $('.apple, .sweetcorn').parentsUntil();
- expect(result).toHaveLength(5);
- expect(result[0]).toBe($('#vegetables')[0]);
- expect(result[1]).toBe($('#fruits')[0]);
- expect(result[2]).toBe($('#food')[0]);
- expect(result[3]).toBe($('body')[0]);
- expect(result[4]).toBe($('html')[0]);
- });
- it('(selector) : should get all of the parents until selector', () => {
- const food = $('.orange').parentsUntil('#food');
- expect(food).toHaveLength(1);
- expect(food[0].attribs).toHaveProperty('id', 'fruits');
- const fruits = $('.orange').parentsUntil('#fruits');
- expect(fruits).toHaveLength(0);
- });
- it('(selector) : Less simple parentsUntil check with selector', () => {
- const result = $('#fruits').parentsUntil('html, body');
- expect(result.eq(0).attr('id')).toBe('food');
- });
- it('(selector not parent) : should return all parents', () => {
- const result = $('.orange').parentsUntil('.apple');
- expect(result).toHaveLength(4);
- expect(result[0].attribs).toHaveProperty('id', 'fruits');
- expect(result[1].attribs).toHaveProperty('id', 'food');
- expect(result[2].tagName).toBe('body');
- expect(result[3].tagName).toBe('html');
- });
- it('(selector, filter) : should get all of the parents that match the filter', () => {
- const result = $('.apple, .sweetcorn').parentsUntil(
- '.saladbar',
- '#vegetables',
- );
- expect(result).toHaveLength(1);
- expect(result[0].attribs).toHaveProperty('id', 'vegetables');
- });
- it('(selector, filter) : Multiple-filtered parentsUntil check', () => {
- const result = $('.orange').parentsUntil('html', 'ul,body');
- expect(result).toHaveLength(3);
- expect(result.eq(0).attr('id')).toBe('fruits');
- expect(result.eq(1).attr('id')).toBe('food');
- expect(result.eq(2).prop('tagName')).toBe('BODY');
- });
- it('() : should return empty object when called on an empty object', () => {
- const result = $('.saladbar').parentsUntil();
- expect(result).toHaveLength(0);
- });
- it('() : should return an empty set for top-level elements', () => {
- const result = $('html').parentsUntil();
- expect(result).toHaveLength(0);
- });
- it('(cheerio object) : should return all parents until any member of the cheerio object', () => {
- const $fruits = $('#fruits');
- const $until = $('#food');
- const result = $fruits.children().eq(1).parentsUntil($until);
- expect(result).toHaveLength(1);
- expect(result[0].attribs).toHaveProperty('id', 'fruits');
- });
- it('(cheerio object) : should return all parents until body element', () => {
- const body = $('body')[0];
- const result = $('.carrot').parentsUntil(body);
- expect(result).toHaveLength(2);
- expect(result.eq(0).is('ul#vegetables')).toBe(true);
- });
- });
- describe('.parent', () => {
- it('() : should return the parent of each matched element', () => {
- let result = $('.orange').parent();
- expect(result).toHaveLength(1);
- expect(result[0].attribs).toHaveProperty('id', 'fruits');
- result = $('li', food).parent();
- expect(result).toHaveLength(2);
- expect(result[0].attribs).toHaveProperty('id', 'fruits');
- expect(result[1].attribs).toHaveProperty('id', 'vegetables');
- });
- it('(undefined) : should not throw an exception', () => {
- expect(() => {
- $('li').parent(undefined);
- }).not.toThrow();
- });
- it('() : should return an empty object for top-level elements', () => {
- const result = $('html').parent();
- expect(result).toHaveLength(0);
- });
- it('() : should not contain duplicate elements', () => {
- const result = $('li').parent();
- expect(result).toHaveLength(1);
- });
- it('(selector) : should filter the matched parent elements by the selector', () => {
- const parents = $('.orange').parent();
- expect(parents).toHaveLength(1);
- expect(parents[0].attribs).toHaveProperty('id', 'fruits');
- const fruits = $('li', food).parent('#fruits');
- expect(fruits).toHaveLength(1);
- expect(fruits[0].attribs).toHaveProperty('id', 'fruits');
- });
- });
- describe('.closest', () => {
- it('() : should return an empty array', () => {
- const result = $('.orange').closest();
- expect(result).toHaveLength(0);
- expect(result).toBeInstanceOf(Cheerio);
- });
- it('(selector) : should find the closest element that matches the selector, searching through its ancestors and itself', () => {
- expect($('.orange').closest('.apple')).toHaveLength(0);
- expect(
- ($('.orange', food).closest('#food')[0] as Element).attribs,
- ).toHaveProperty('id', 'food');
- expect(
- ($('.orange', food).closest('ul')[0] as Element).attribs,
- ).toHaveProperty('id', 'fruits');
- expect(
- ($('.orange', food).closest('li')[0] as Element).attribs,
- ).toHaveProperty('class', 'orange');
- });
- it('(selector) : should find the closest element of each item, removing duplicates', () => {
- const result = $('li', food).closest('ul');
- expect(result).toHaveLength(2);
- });
- it('() : should not break if the selector does not have any results', () => {
- const result = $('.saladbar', food).closest('ul');
- expect(result).toHaveLength(0);
- });
- it('(selector) : should find closest element for text nodes', () => {
- const textNode = $('.apple', food).contents().first();
- const result = textNode.closest('#food') as Cheerio<Element>;
- expect(result[0].attribs).toHaveProperty('id', 'food');
- });
- });
- describe('.each', () => {
- it('( (i, elem) -> ) : should loop selected returning fn with (i, elem)', () => {
- const items: Element[] = [];
- const classes = ['apple', 'orange', 'pear'];
- $('li').each(function (idx, elem) {
- items[idx] = elem;
- expect(this.attribs).toHaveProperty('class', classes[idx]);
- });
- expect(items[0].attribs).toHaveProperty('class', 'apple');
- expect(items[1].attribs).toHaveProperty('class', 'orange');
- expect(items[2].attribs).toHaveProperty('class', 'pear');
- });
- it('( (i, elem) -> ) : should break iteration when the iterator function returns false', () => {
- let iterationCount = 0;
- $('li').each((idx) => {
- iterationCount++;
- return idx < 1;
- });
- expect(iterationCount).toBe(2);
- });
- });
- if (typeof Symbol !== 'undefined') {
- describe('[Symbol.iterator]', () => {
- it('should yield each element', () => {
- // The equivalent of: for (const element of $('li')) ...
- const $li = $('li');
- const iterator = $li[Symbol.iterator]();
- expect(iterator.next().value.attribs).toHaveProperty('class', 'apple');
- expect(iterator.next().value.attribs).toHaveProperty('class', 'orange');
- expect(iterator.next().value.attribs).toHaveProperty('class', 'pear');
- expect(iterator.next().done).toBe(true);
- });
- });
- }
- describe('.map', () => {
- it('(fn) : should be invoked with the correct arguments and context', () => {
- const $fruits = $('li');
- const args: [number, AnyNode][] = [];
- const thisVals: AnyNode[] = [];
- $fruits.map(function (...myArgs) {
- args.push(myArgs);
- thisVals.push(this);
- return undefined;
- });
- expect(args).toStrictEqual([
- [0, $fruits[0]],
- [1, $fruits[1]],
- [2, $fruits[2]],
- ]);
- expect(thisVals).toStrictEqual([$fruits[0], $fruits[1], $fruits[2]]);
- });
- it('(fn) : should return an Cheerio object wrapping the returned items', () => {
- const $fruits = $('li');
- const $mapped = $fruits.map((i) => $fruits[2 - i]);
- expect($mapped).toHaveLength(3);
- expect($mapped[0]).toBe($fruits[2]);
- expect($mapped[1]).toBe($fruits[1]);
- expect($mapped[2]).toBe($fruits[0]);
- });
- it('(fn) : should ignore `null` and `undefined` returned by iterator', () => {
- const $fruits = $('li');
- const retVals = [null, undefined, $fruits[1]];
- const $mapped = $fruits.map((i) => retVals[i]);
- expect($mapped).toHaveLength(1);
- expect($mapped[0]).toBe($fruits[1]);
- });
- it('(fn) : should preform a shallow merge on arrays returned by iterator', () => {
- const $fruits = $('li');
- const $mapped = $fruits.map(() => [1, [3, 4]]);
- expect($mapped.get()).toStrictEqual([1, [3, 4], 1, [3, 4], 1, [3, 4]]);
- });
- it('(fn) : should tolerate `null` and `undefined` when flattening arrays returned by iterator', () => {
- const $fruits = $('li');
- const $mapped = $fruits.map(() => [null, undefined]);
- expect($mapped.get()).toStrictEqual([
- null,
- undefined,
- null,
- undefined,
- null,
- undefined,
- ]);
- });
- });
- describe('.filter', () => {
- it('(selector) : should reduce the set of matched elements to those that match the selector', () => {
- const pear = $('li').filter('.pear').text();
- expect(pear).toBe('Pear');
- });
- it('(selector) : should not consider nested elements', () => {
- const lis = $('#fruits').filter('li');
- expect(lis).toHaveLength(0);
- });
- it('(selection) : should reduce the set of matched elements to those that are contained in the provided selection', () => {
- const $fruits = $('li');
- const $pear = $fruits.filter('.pear, .apple');
- expect($fruits.filter($pear)).toHaveLength(2);
- });
- it('(element) : should reduce the set of matched elements to those that specified directly', () => {
- const $fruits = $('li');
- const pear = $fruits.filter('.pear')[0];
- expect($fruits.filter(pear)).toHaveLength(1);
- });
- it("(fn) : should reduce the set of matched elements to those that pass the function's test", () => {
- const orange = $('li')
- .filter(function (i, el) {
- expect(this).toBe(el);
- expect(el.tagName).toBe('li');
- expect(typeof i).toBe('number');
- return $(this).attr('class') === 'orange';
- })
- .text();
- expect(orange).toBe('Orange');
- });
- it('should also iterate over text nodes (#1867)', () => {
- const text = $('<a>a</a>b<c></c>').filter((_, el): el is Text =>
- isText(el),
- );
- expect(text[0].data).toBe('b');
- });
- });
- describe('.not', () => {
- it('(selector) : should reduce the set of matched elements to those that do not match the selector', () => {
- const $fruits = $('li');
- const $notPear = $fruits.not('.pear');
- expect($notPear).toHaveLength(2);
- expect($notPear[0]).toBe($fruits[0]);
- expect($notPear[1]).toBe($fruits[1]);
- });
- it('(selector) : should not consider nested elements', () => {
- const lis = $('#fruits').not('li');
- expect(lis).toHaveLength(1);
- });
- it('(selection) : should reduce the set of matched elements to those that are mot contained in the provided selection', () => {
- const $fruits = $('li');
- const $orange = $('.orange');
- const $notOrange = $fruits.not($orange);
- expect($notOrange).toHaveLength(2);
- expect($notOrange[0]).toBe($fruits[0]);
- expect($notOrange[1]).toBe($fruits[2]);
- });
- it('(element) : should reduce the set of matched elements to those that specified directly', () => {
- const $fruits = $('li');
- const apple = $('.apple')[0];
- const $notApple = $fruits.not(apple);
- expect($notApple).toHaveLength(2);
- expect($notApple[0]).toBe($fruits[1]);
- expect($notApple[1]).toBe($fruits[2]);
- });
- it("(fn) : should reduce the set of matched elements to those that do not pass the function's test", () => {
- const $fruits = $('li');
- const $notOrange = $fruits.not(function (i, el) {
- expect(this).toBe(el);
- expect(el).toHaveProperty('name', 'li');
- expect(typeof i).toBe('number');
- return $(this).attr('class') === 'orange';
- });
- expect($notOrange).toHaveLength(2);
- expect($notOrange[0]).toBe($fruits[0]);
- expect($notOrange[1]).toBe($fruits[2]);
- });
- });
- describe('.has', () => {
- beforeEach(() => {
- $ = load(food);
- });
- it('(selector) : should reduce the set of matched elements to those with descendants that match the selector', () => {
- const $fruits = $('#fruits,#vegetables').has('.pear');
- expect($fruits).toHaveLength(1);
- expect($fruits[0]).toBe($('#fruits')[0]);
- });
- it('(selector) : should only consider nested elements', () => {
- const $empty = $('#fruits').has('#fruits');
- expect($empty).toHaveLength(0);
- });
- it('(element) : should reduce the set of matched elements to those that are ancestors of the provided element', () => {
- const $fruits = $('#fruits,#vegetables').has($('.pear')[0]);
- expect($fruits).toHaveLength(1);
- expect($fruits[0]).toBe($('#fruits')[0]);
- });
- it('(element) : should only consider nested elements', () => {
- const $fruits = $('#fruits');
- const fruitsEl = $fruits[0];
- const $empty = $fruits.has(fruitsEl);
- expect($empty).toHaveLength(0);
- });
- });
- describe('.first', () => {
- it('() : should return the first item', () => {
- const $src = $(
- '<span>foo</span><span>bar</span><span>baz</span>',
- ) as Cheerio<Element>;
- const $elem = $src.first();
- expect($elem.length).toBe(1);
- expect($elem[0].childNodes[0]).toHaveProperty('data', 'foo');
- });
- it('() : should return an empty object for an empty object', () => {
- const $src = $();
- const $first = $src.first();
- expect($first.length).toBe(0);
- expect($first[0]).toBeUndefined();
- });
- });
- describe('.last', () => {
- it('() : should return the last element', () => {
- const $src = $(
- '<span>foo</span><span>bar</span><span>baz</span>',
- ) as Cheerio<Element>;
- const $elem = $src.last();
- expect($elem.length).toBe(1);
- expect($elem[0].childNodes[0]).toHaveProperty('data', 'baz');
- });
- it('() : should return an empty object for an empty object', () => {
- const $src = $();
- const $last = $src.last();
- expect($last.length).toBe(0);
- expect($last[0]).toBeUndefined();
- });
- });
- describe('.first & .last', () => {
- it('() : should return equivalent collections if only one element', () => {
- const $src = $('<span>bar</span>') as Cheerio<Element>;
- const $first = $src.first();
- const $last = $src.last();
- expect($first.length).toBe(1);
- expect($first[0].childNodes[0]).toHaveProperty('data', 'bar');
- expect($last.length).toBe(1);
- expect($last[0].childNodes[0]).toHaveProperty('data', 'bar');
- expect($first[0]).toBe($last[0]);
- });
- });
- describe('.eq', () => {
- it('(i) : should return the element at the specified index', () => {
- expect(getText($('li').eq(0))).toBe('Apple');
- expect(getText($('li').eq(1))).toBe('Orange');
- expect(getText($('li').eq(2))).toBe('Pear');
- expect(getText($('li').eq(3))).toBeUndefined();
- expect(getText($('li').eq(-1))).toBe('Pear');
- });
- });
- describe('.get', () => {
- it('(i) : should return the element at the specified index', () => {
- const children = $('#fruits').children();
- expect(children.get(0)).toBe(children[0]);
- expect(children.get(1)).toBe(children[1]);
- expect(children.get(2)).toBe(children[2]);
- });
- it('(-1) : should return the element indexed from the end of the collection', () => {
- const children = $('#fruits').children();
- expect(children.get(-1)).toBe(children[2]);
- expect(children.get(-2)).toBe(children[1]);
- expect(children.get(-3)).toBe(children[0]);
- });
- it('() : should return an array containing all of the collection', () => {
- const children = $('#fruits').children();
- const all = children.get();
- expect(Array.isArray(all)).toBe(true);
- expect(all).toStrictEqual([children[0], children[1], children[2]]);
- });
- });
- describe('.index', () => {
- describe('() :', () => {
- it('returns the index of a child amongst its siblings', () => {
- expect($('.orange').index()).toBe(1);
- });
- it('returns -1 when the selection has no parent', () => {
- expect($('<div/>').index()).toBe(-1);
- });
- });
- describe('(selector) :', () => {
- it('returns the index of the first element in the set matched by `selector`', () => {
- expect($('.apple').index('#fruits, li')).toBe(1);
- });
- it('returns -1 when the item is not present in the set matched by `selector`', () => {
- expect($('.apple').index('#fuits')).toBe(-1);
- });
- it('returns -1 when the first element in the set has no parent', () => {
- expect($('<div/>').index('*')).toBe(-1);
- });
- });
- describe('(node) :', () => {
- it('returns the index of the given node within the current selection', () => {
- const $lis = $('li');
- expect($lis.index($lis.get(1))).toBe(1);
- });
- it('returns the index of the given node within the current selection when the current selection has no parent', () => {
- const $apple = $('.apple').remove();
- expect($apple.index($apple.get(0))).toBe(0);
- });
- it('returns -1 when the given node is not present in the current selection', () => {
- expect($('li').index($('#fruits').get(0))).toBe(-1);
- });
- it('returns -1 when the current selection is empty', () => {
- expect($('.not-fruit').index($('#fruits').get(0))).toBe(-1);
- });
- });
- describe('(selection) :', () => {
- it('returns the index of the first node in the provided selection within the current selection', () => {
- const $lis = $('li');
- expect($lis.index($('.orange, .pear'))).toBe(1);
- });
- it('returns -1 when the given node is not present in the current selection', () => {
- expect($('li').index($('#fruits'))).toBe(-1);
- });
- it('returns -1 when the current selection is empty', () => {
- expect($('.not-fruit').index($('#fruits'))).toBe(-1);
- });
- });
- });
- describe('.slice', () => {
- it('(start) : should return all elements after the given index', () => {
- const sliced = $('li').slice(1);
- expect(sliced).toHaveLength(2);
- expect(getText(sliced.eq(0))).toBe('Orange');
- expect(getText(sliced.eq(1))).toBe('Pear');
- });
- it('(start, end) : should return all elements matching the given range', () => {
- const sliced = $('li').slice(1, 2);
- expect(sliced).toHaveLength(1);
- expect(getText(sliced.eq(0))).toBe('Orange');
- });
- it('(-start) : should return element matching the offset from the end', () => {
- const sliced = $('li').slice(-1);
- expect(sliced).toHaveLength(1);
- expect(getText(sliced.eq(0))).toBe('Pear');
- });
- });
- describe('.end() :', () => {
- let $fruits: Cheerio<Element>;
- beforeEach(() => {
- $fruits = $('#fruits').children();
- });
- it('returns an empty object at the end of the chain', () => {
- expect($fruits.end().end().end()).toBeTruthy();
- expect($fruits.end().end().end()).toHaveLength(0);
- });
- it('find', () => {
- expect($fruits.find('.apple').end()).toBe($fruits);
- });
- it('filter', () => {
- expect($fruits.filter('.apple').end()).toBe($fruits);
- });
- it('map', () => {
- expect(
- $fruits
- .map(function () {
- return this;
- })
- .end(),
- ).toBe($fruits);
- });
- it('contents', () => {
- expect($fruits.contents().end()).toBe($fruits);
- });
- it('eq', () => {
- expect($fruits.eq(1).end()).toBe($fruits);
- });
- it('first', () => {
- expect($fruits.first().end()).toBe($fruits);
- });
- it('last', () => {
- expect($fruits.last().end()).toBe($fruits);
- });
- it('slice', () => {
- expect($fruits.slice(1).end()).toBe($fruits);
- });
- it('children', () => {
- expect($fruits.children().end()).toBe($fruits);
- });
- it('parent', () => {
- expect($fruits.parent().end()).toBe($fruits);
- });
- it('parents', () => {
- expect($fruits.parents().end()).toBe($fruits);
- });
- it('closest', () => {
- expect($fruits.closest('ul').end()).toBe($fruits);
- });
- it('siblings', () => {
- expect($fruits.siblings().end()).toBe($fruits);
- });
- it('next', () => {
- expect($fruits.next().end()).toBe($fruits);
- });
- it('nextAll', () => {
- expect($fruits.nextAll().end()).toBe($fruits);
- });
- it('prev', () => {
- expect($fruits.prev().end()).toBe($fruits);
- });
- it('prevAll', () => {
- expect($fruits.prevAll().end()).toBe($fruits);
- });
- it('clone', () => {
- expect($fruits.clone().end()).toBe($fruits);
- });
- });
- describe('.add()', () => {
- let $fruits: Cheerio<AnyNode>;
- let $apple: Cheerio<Element>;
- let $orange: Cheerio<Element>;
- let $pear: Cheerio<Element>;
- beforeEach(() => {
- $ = load(food);
- $fruits = $('#fruits');
- $apple = $('.apple');
- $orange = $('.orange');
- $pear = $('.pear');
- });
- describe('(selector) matched element :', () => {
- it('occurs before current selection', () => {
- const $selection = $orange.add('.apple');
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('is identical to the current selection', () => {
- const $selection = $orange.add('.orange');
- expect($selection).toHaveLength(1);
- expect($selection[0]).toBe($orange[0]);
- });
- it('occurs after current selection', () => {
- const $selection = $orange.add('.pear');
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($orange[0]);
- expect($selection[1]).toBe($pear[0]);
- });
- it('contains the current selection', () => {
- const $selection = $orange.add('#fruits');
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('is a child of the current selection', () => {
- const $selection = $fruits.add('.orange');
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('is root object preserved', () => {
- const $selection = $('<div></div>').add('#fruits');
- expect($selection).toHaveLength(2);
- expect($selection.eq(0).is('div')).toBe(true);
- expect($selection.eq(1).is($fruits.eq(0))).toBe(true);
- });
- });
- describe('(selector) matched elements :', () => {
- it('occur before the current selection', () => {
- const $selection = $pear.add('.apple, .orange');
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('include the current selection', () => {
- const $selection = $pear.add('#fruits li');
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur after the current selection', () => {
- const $selection = $apple.add('.orange, .pear');
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur within the current selection', () => {
- const $selection = $fruits.add('#fruits li');
- expect($selection).toHaveLength(4);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($apple[0]);
- expect($selection[2]).toBe($orange[0]);
- expect($selection[3]).toBe($pear[0]);
- });
- });
- describe('(selector, context) :', () => {
- it(', context)', () => {
- const $selection = $fruits.add('li', '#vegetables');
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($('.carrot')[0]);
- expect($selection[2]).toBe($('.sweetcorn')[0]);
- });
- });
- describe('(element) honors document order when element occurs :', () => {
- it('before the current selection', () => {
- const $selection = $orange.add($apple[0]);
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('after the current selection', () => {
- const $selection = $orange.add($pear[0]);
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($orange[0]);
- expect($selection[1]).toBe($pear[0]);
- });
- it('within the current selection', () => {
- const $selection = $fruits.add($orange[0]);
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('as an ancestor of the current selection', () => {
- const $selection = $orange.add($fruits[0]);
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('does not insert an element already contained within the current selection', () => {
- const $selection = $apple.add($apple[0]);
- expect($selection).toHaveLength(1);
- expect($selection[0]).toBe($apple[0]);
- });
- });
- describe('([elements]) : elements', () => {
- it('occur before the current selection', () => {
- const $selection = $pear.add($('.apple, .orange').get());
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('include the current selection', () => {
- const $selection = $pear.add($('#fruits li').get());
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur after the current selection', () => {
- const $selection = $apple.add($('.orange, .pear').get());
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur within the current selection', () => {
- const $selection = $fruits.add($('#fruits li').get());
- expect($selection).toHaveLength(4);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($apple[0]);
- expect($selection[2]).toBe($orange[0]);
- expect($selection[3]).toBe($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.
- *
- * @see {@link https://api.jquery.com/add/}
- */
- it('(html) : correctly parses and adds the new elements', () => {
- const $selection = $apple.add('<li class="banana">banana</li>');
- expect($selection).toHaveLength(2);
- expect($selection.is('.apple')).toBe(true);
- expect($selection.is('.banana')).toBe(true);
- });
- describe('(selection) element in selection :', () => {
- it('occurs before current selection', () => {
- const $selection = $orange.add($('.apple'));
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('is identical to the current selection', () => {
- const $selection = $orange.add($('.orange'));
- expect($selection).toHaveLength(1);
- expect($selection[0]).toBe($orange[0]);
- });
- it('occurs after current selection', () => {
- const $selection = $orange.add($('.pear'));
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($orange[0]);
- expect($selection[1]).toBe($pear[0]);
- });
- it('contains the current selection', () => {
- const $selection = $orange.add($('#fruits'));
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- it('is a child of the current selection', () => {
- const $selection = $fruits.add($('.orange'));
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($orange[0]);
- });
- });
- describe('(selection) elements in the selection :', () => {
- it('occur before the current selection', () => {
- const $selection = $pear.add($('.apple, .orange'));
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('include the current selection', () => {
- const $selection = $pear.add($('#fruits li'));
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur after the current selection', () => {
- const $selection = $apple.add($('.orange, .pear'));
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($apple[0]);
- expect($selection[1]).toBe($orange[0]);
- expect($selection[2]).toBe($pear[0]);
- });
- it('occur within the current selection', () => {
- const $selection = $fruits.add($('#fruits li'));
- expect($selection).toHaveLength(4);
- expect($selection[0]).toBe($fruits[0]);
- expect($selection[1]).toBe($apple[0]);
- expect($selection[2]).toBe($orange[0]);
- expect($selection[3]).toBe($pear[0]);
- });
- });
- describe('(selection) :', () => {
- it('modifying nested selections should not impact the parent [#834]', () => {
- const apple_pear = $apple.add($pear);
- // Applies red to apple and pear
- apple_pear.addClass('red');
- expect($apple.hasClass('red')).toBe(true); // This is true
- expect($pear.hasClass('red')).toBe(true); // This is true
- // Applies green to pear... AND should not affect apple
- $pear.addClass('green');
- expect($pear.hasClass('green')).toBe(true); // Currently this is true
- expect($apple.hasClass('green')).toBe(false); // And this should be false!
- });
- });
- });
- describe('.addBack', () => {
- describe('() :', () => {
- it('includes siblings and self', () => {
- const $selection = $('.orange').siblings().addBack();
- expect($selection).toHaveLength(3);
- expect($selection[0]).toBe($('.apple')[0]);
- expect($selection[1]).toBe($('.orange')[0]);
- expect($selection[2]).toBe($('.pear')[0]);
- });
- it('includes children and self', () => {
- const $selection = $('#fruits').children().addBack();
- expect($selection).toHaveLength(4);
- expect($selection[0]).toBe($('#fruits')[0]);
- expect($selection[1]).toBe($('.apple')[0]);
- expect($selection[2]).toBe($('.orange')[0]);
- expect($selection[3]).toBe($('.pear')[0]);
- });
- it('includes parent and self', () => {
- const $selection = $('.apple').parent().addBack();
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($('#fruits')[0]);
- expect($selection[1]).toBe($('.apple')[0]);
- });
- it('includes parents and self', () => {
- const q = load(food);
- const $selection = q('.apple').parents().addBack();
- expect($selection).toHaveLength(5);
- expect($selection[0]).toBe(q('html')[0]);
- expect($selection[1]).toBe(q('body')[0]);
- expect($selection[2]).toBe(q('#food')[0]);
- expect($selection[3]).toBe(q('#fruits')[0]);
- expect($selection[4]).toBe(q('.apple')[0]);
- });
- });
- it('(filter) : filters the previous selection', () => {
- const $selection = $('li').eq(1).addBack('.apple');
- expect($selection).toHaveLength(2);
- expect($selection[0]).toBe($('.apple')[0]);
- expect($selection[1]).toBe($('.orange')[0]);
- });
- it('() : fails gracefully when no args are passed', () => {
- const $div = cheerio('<div>');
- expect($div.addBack()).toBe($div);
- });
- });
- describe('.is', () => {
- it('() : should return false', () => {
- expect($('li.apple').is()).toBe(false);
- });
- it('(true selector) : should return true', () => {
- expect(cheerio('#vegetables', vegetables).is('ul')).toBe(true);
- });
- it('(false selector) : should return false', () => {
- expect(cheerio('#vegetables', vegetables).is('div')).toBe(false);
- });
- it('(true selection) : should return true', () => {
- const $vegetables = cheerio('li', vegetables);
- expect($vegetables.is($vegetables.eq(1))).toBe(true);
- });
- it('(false selection) : should return false', () => {
- const $vegetableList = cheerio(vegetables);
- const $vegetables = $vegetableList.find('li');
- expect($vegetables.is($vegetableList)).toBe(false);
- });
- it('(true element) : should return true', () => {
- const $vegetables = cheerio('li', vegetables);
- expect($vegetables.is($vegetables[0])).toBe(true);
- });
- it('(false element) : should return false', () => {
- const $vegetableList = cheerio(vegetables);
- const $vegetables = $vegetableList.find('li');
- expect($vegetables.is($vegetableList[0])).toBe(false);
- });
- it('(true predicate) : should return true', () => {
- const result = $('li').is(function () {
- return this.tagName === 'li' && $(this).hasClass('pear');
- });
- expect(result).toBe(true);
- });
- it('(false predicate) : should return false', () => {
- const result = $('li')
- .last()
- .is(function () {
- return this.tagName === 'ul';
- });
- expect(result).toBe(false);
- });
- });
- });
|