import { fromJS } from 'immutable'; import type { StatusLike } from '../hashtag_bar'; import { computeHashtagBarForStatus } from '../hashtag_bar'; function createStatus( content: string, hashtags: string[], hasMedia = false, spoilerText?: string, ) { return fromJS({ tags: hashtags.map((name) => ({ name })), contentHtml: content, media_attachments: hasMedia ? ['fakeMedia'] : [], spoiler_text: spoilerText, }) as unknown as StatusLike; // need to force the type here, as it is not properly defined } describe('computeHashtagBarForStatus', () => { it('does nothing when there are no tags', () => { const status = createStatus('

Simple text

', []); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Simple text

"`, ); }); it('displays out of band hashtags in the bar', () => { const status = createStatus( '

Simple text #hashtag

', ['hashtag', 'test'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual(['test']); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Simple text #hashtag

"`, ); }); it('does not truncate the contents when the last child is a text node', () => { const status = createStatus( 'this is a #test. Some more text', ['test'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"this is a #test. Some more text"`, ); }); it('extract tags from the last line', () => { const status = createStatus( '

Simple text

#hashtag

', ['hashtag'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual(['hashtag']); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Simple text

"`, ); }); it('does not include tags from content', () => { const status = createStatus( '

Simple text with a #hashtag

#hashtag

', ['hashtag'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Simple text with a #hashtag

"`, ); }); it('works with one line status and hashtags', () => { const status = createStatus( '

#test. And another #hashtag

', ['hashtag', 'test'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

#test. And another #hashtag

"`, ); }); it('de-duplicate accentuated characters with case differences', () => { const status = createStatus( '

Text

#éaa #Éaa

', ['éaa'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual(['Éaa']); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Text

"`, ); }); it('handles server-side normalized tags with accentuated characters', () => { const status = createStatus( '

Text

#éaa #Éaa

', ['eaa'], // The server may normalize the hashtags in the `tags` attribute ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual(['Éaa']); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Text

"`, ); }); it('does not display in bar a hashtag in content with a case difference', () => { const status = createStatus( '

Text #Éaa

#éaa

', ['éaa'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

Text #Éaa

"`, ); }); it('does not modify a status with a line of hashtags only', () => { const status = createStatus( '

#test #hashtag

', ['test', 'hashtag'], ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

#test #hashtag

"`, ); }); it('puts the hashtags in the bar if a status content has hashtags in the only line and has a media', () => { const status = createStatus( '

This is my content! #hashtag

', ['hashtag'], true, ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

This is my content! #hashtag

"`, ); }); it('puts the hashtags in the bar if a status content is only hashtags and has a media', () => { const status = createStatus( '

#test #hashtag

', ['test', 'hashtag'], true, ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual(['test', 'hashtag']); expect(statusContentProps.statusContent).toMatchInlineSnapshot(`""`); }); it('does not use the hashtag bar if the status content is only hashtags, has a CW and a media', () => { const status = createStatus( '

#test #hashtag

', ['test', 'hashtag'], true, 'My CW text', ); const { hashtagsInBar, statusContentProps } = computeHashtagBarForStatus(status); expect(hashtagsInBar).toEqual([]); expect(statusContentProps.statusContent).toMatchInlineSnapshot( `"

#test #hashtag

"`, ); }); });