import { describe, it, expect, afterEach } from 'vitest' import truncate from '../src/truncate' import cheerio, { AnyNode, Cheerio } from 'cheerio' describe('Truncate html', () => { describe('should works well when false params are given', () => { it('should NOT truncate a string if no string provided', () => { // @ts-expect-error test for null expect(truncate(null)).toBe(null) }) it('should NOT truncate a string if NO length provided', () => { const html = 'string' expect(truncate(html)).toBe(html) }) it("should NOT truncate a empty string", () => { const html = ""; expect(truncate(html, 10)).toBe(html); }); it("should NOT truncate a empty string instance", () => { const html = ""; // third parameter for removing the document wrapper const $ = cheerio.load(html, {}, false); expect(truncate($)).toBe(''); }); it("should NOT truncate a comment string", () => { const html = ""; expect(truncate(html, 2)).toBe(''); }); it('should NOT truncate a string if NO length provided $', () => { const html = 'string' const $ = cheerio.load(html) expect(truncate($)).toBe('
string') }) it('should NOT truncate a string if length is less than or equal to zero', () => { const html = 'string' expect(truncate(html, 0)).toBe(html) }) it('should NOT truncate a string if length is less than or equal to zero $', () => { const html = 'string' const $ = cheerio.load(html) expect(truncate($, 0)).toBe('string') }) }) describe('truncate with options.length', () => { it('should truncate a string', () => { const test = '123456789' const expected = '12345...' expect(truncate(test, 5)).toBe(expected) }) it('should truncate a string $', () => { const test = '123456789' const expected = '12345...' const $ = cheerio.load(test, null, false) expect(truncate($, 5)).toBe(expected) }) it('should truncate a string with tags', () => { const test = '123456789
' const expected = '123456...
' expect(truncate(test, { length: 6 })).toBe(expected) }) it('should kepp all the string if length logger than the origin string', () => { const test = '123456789
' const expected = '123456789
' expect(truncate(test, { length: 100 })).toBe(expected) }) it('should truncate a string with characters outside of tags', () => { const test = '12345
6789' const expected = '12345
678...' expect(truncate(test, 8)).toBe(expected) }) it('should works well when truncate at tag boundary', () => { const test = 'Hello world' const expected = 'Hello ...' expect(truncate(test, 6)).toBe(expected) }) it('should works well when truncate at tag boundary-2', () => { const test = 'Hello world' const expected = 'Hello world' expect(truncate(test, 11)).toBe(expected) }) it('should truncate a string two sets of tags', () => { const test = '12345
6789
' const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) it('should truncate a string two sets of tags $', () => { const test = cheerio.load('12345
6789
', null, false) const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) it('should keep empty tag', () => { const test = '12345
6789
reset text ' const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) it('should keep empty tag $', () => { const test = cheerio.load('12345
6789
reset text ', null, false) const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) it('should remove comment', () => { const test = '12345
6789
' const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) it('should remove comment in tag', () => { const test = '12345
6789
' const expected = '12345
67...
' expect(truncate(test, 7)).toBe(expected) }) describe('works with options.reserveLastWord', () => { it('should reserve the last word', () => { const test = '12345
6789
' const expected = '12345
6789
' expect( truncate(test, 7, { reserveLastWord: true }) ).toBe(expected) }) it('should reserve the last word(i18n)', () => { const test = 'internationalization
' const expected = 'internationalization
' expect( truncate(test, 7, { reserveLastWord: 20 // exceed 20 letters }) ).toBe(expected) }) it('should cut at the last word(i18n)', () => { const test = 'internationalization
' const expected = 'internationalizat...
' expect( truncate(test, 7, { reserveLastWord: true // exceed 10 letters }) ).toBe(expected) }) it('should reserve the last word if only one word', () => { const test = 'internationalization
' const expected = 'internationalizat...
' expect( truncate(test, 7, { reserveLastWord: -1 // exceed 10 letters }) ).toBe(expected) }) it('should remove the last word if the edge if not the only one word', () => { const test = 'abc internationalization
' const expected = 'abc ...
' expect( truncate(test, 7, { reserveLastWord: -1 // exceed 10 letters }) ).toBe(expected) }) it('should cut the only word if trimTheOnlyWord true', () => { const test = 'internationalization
' const expected = 'interna...
' expect( truncate(test, 7, { reserveLastWord: -1, // exceed 10 letters trimTheOnlyWord: true }) ).toBe(expected) }) it('should reserve the last word if only one word $', () => { const test = cheerio.load('internationalization
', null, false) const expected = 'internationalizat...
' expect( truncate(test, 7, { reserveLastWord: true // exceed 10 letters }) ).toBe(expected) }) it('should reserve the last word if at the boundary', () => { const test = 'Hello world from earth
' const expected = 'Hello world...
' expect( truncate(test, 11, { reserveLastWord: -1 // exceed 10 letters }) ).toBe(expected) }) it('should reserve the last word if at the boundary even trimTheOnlyWord is true ', () => { const test = 'Hello world from earth
' const expected = 'Hello world...
' expect( truncate(test, 11, { reserveLastWord: -1, // exceed 10 letters trimTheOnlyWord: true }) ).toBe(expected) }) // from issue #24 it('should cut correctly if string\'s length is equal to the truncation length', () => { const test = 'a b c d ef
' const expected = 'a b c d ef
' expect( truncate(test, 10, { reserveLastWord: -1 // exceed 10 letters }) ).toBe(expected) }) it('should remove the last word if more than one(i18n, reserveLastWord negative)', () => { const test = 'hello internationalization
' const expected = 'hello ...
' expect( truncate(test, 7, { reserveLastWord: -1 // exceed 10 letters }) ).toBe(expected) }) }) }) describe('with self-close tags', () => { it('should truncate a string with an image tag', () => { const html = '
This is a string
This is a ...
This
is a string
This
is a ...
This
This is a string do
This is a string...
This is a string do
This is a string do
This is a string do
This is a string do
This is a string do
This is a...
This is a string
This is a...
This is a string
This is a...
Hello image.
This is a string
Hello image.
This is ...
Hello image.
This is a string
Hello image.
This is...
This is a string
This is a string
This is a string
This is a ~
This is a string
This is a string
This is a string
This is a ...
' const options = { length: 10, excludes: 'img' } expect(truncate(html, options)).toBe(expected) }) it('should exclude multiple elements by selector', () => { const html = '
This is a string
This is a string
for...' const options = { length: 20, excludes: ['img', '.something-unwanted'] } expect(truncate(html, options)).toBe(expected) }) }) describe('with options.decodeEntities', () => { it('should handle encoded characters', () => { const html = 'test for <p> encoded string
' const expected = 'test for <p> encode...
' const options = { length: 20, decodeEntities: true } expect(truncate(html, options)).toBe(expected) }) // it('should leave encoded characters as is', () => { // const html = 'test for <p> encoded string
' // const expected = 'test for <p...
' // const options = { // length: 20, // decodeEntities: false // this is the default value // } // expect(truncate(html, options)).toBe(expected) // }) it('should leave encoded characters as is', () => { const html = 'test for <p> encoded string
' const expected = 'test for <p> encode...
' const options = { length: 20, decodeEntities: false // this is the default value } expect(truncate(html, options)).toBe(expected) }) it('should works with CJK when decodeEntities is true', () => { const html = 'test for <p>@ 中文 string
' const expected = 'test for <p>@ 中文 st...
' const options = { length: 20, decodeEntities: true } expect(truncate(html, options)).toBe(expected) }) it('should convert CJK from encoded with decodeEntities to false', () => { const html = 'test for <p> 中文 string
' const expected = 'test for <p> 中文 str...
' const options = { length: 20, decodeEntities: true } expect(truncate(html, options)).toBe(expected) }) it('should convert CJK from encoded with decodeEntities to false', () => { const html = 'test for <p>@ 中文 string
' const expected = 'test for <p>@ 中文 st...
' const options = { length: 20, decodeEntities: false } expect(truncate(html, options)).toBe(expected) }) }) describe('with truncate.setup', () => { afterEach(function () { truncate.setup({ byWords: false, stripTags: false, ellipsis: "...", // @ts-expect-error only for test length: null, decodeEntities: false, keepWhitespaces: false, excludes: "", reserveLastWord: false, }); }) it('should works well if setup with empty', () => { // @ts-expect-error only for test truncate.setup() const test = 'hello from earth' const expected = 'hello from e...' expect(truncate(test, 12)).toBe(expected) }) it('should use default length', () => { truncate.setup({ length: 5 }) const test = '123456789' const expected = '12345...' expect(truncate(test)).toBe(expected) }) it('should use default byWords settings', () => { truncate.setup({ byWords: true }) const test = 'hello from earth' const expected = 'hello from...' expect(truncate(test, 2)).toBe(expected) }) it('should use default reserveLastWord settings', () => { truncate.setup({ reserveLastWord: true }) const test = 'hello from earth' const expected = 'hello from earth' expect(truncate(test, 12)).toBe(expected) }) }) describe('should correcty handle text with emoji characters', () => { afterEach(function () { truncate.setup({ byWords: false, stripTags: false, ellipsis: "...", // @ts-expect-error only for test length: null, decodeEntities: false, keepWhitespaces: false, excludes: "", reserveLastWord: false, }); }) it('emojis with character length more than 1', () => { const test = '💩💩💩💩💩' const expected = '💩💩💩...' expect(truncate(test, 3)).toEqual(expected) }) it('emojis with text', () => { const test = 'Hello there, how are you?? 👍👍👍' const expected = 'Hello there, how are you?? 👍👍...' expect(truncate(test, 29)).toEqual(expected) }) it('emojis with reservedLastWord setting', () => { truncate.setup({ reserveLastWord: true }) const test = 'Hello there 😎😎😎' const expected = 'Hello there 😎...' expect(truncate(test, 13)).toEqual(expected) }) it('emojis with byWords setting, with keepWhitespaces false', () => { truncate.setup({ byWords: true, keepWhitespaces: false }) const test = 'Hello there, how are you?? 😎😎😎' const expected = 'Hello there, how are you?? 😎😎😎' expect(truncate(test, 20)).toEqual(expected) }) it('emojis with keepWhitespaces setting', () => { truncate.setup({ keepWhitespaces: true }) const test = 'Hello there 💩 💩 💩' const expected = 'Hello there 💩 💩 💩' expect(truncate(test, 20)).toEqual(expected) }) it("emojis with byWords setting", () => { truncate.setup({ byWords: true }) const test = 'Hello there, 👋 how are you??' const expected = 'Hello there, 👋...' expect(truncate(test, 3)).toEqual(expected) }); }) describe('customNodeStrategy', () => { it('should works with customNodeStrategy is Keep', () => { const test = '123456789abcefghijk
' const expected = '123456789abcefg...
' const customNodeStrategy = (node: Cheerio123456789abcefghijk
"; const expected = "123456789efg...
"; const customNodeStrategy = (node: Cheerio