diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
commit | 48aff82709769b098321c738f3444b9bdaa694c6 (patch) | |
tree | e00c7c43e2d9b603a5a6af576b1685e400410dee /spec/frontend/gfm_auto_complete_spec.js | |
parent | 879f5329ee916a948223f8f43d77fba4da6cd028 (diff) | |
download | gitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz |
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'spec/frontend/gfm_auto_complete_spec.js')
-rw-r--r-- | spec/frontend/gfm_auto_complete_spec.js | 117 |
1 files changed, 115 insertions, 2 deletions
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js index 6c40b1ba3a7..8da4320d993 100644 --- a/spec/frontend/gfm_auto_complete_spec.js +++ b/spec/frontend/gfm_auto_complete_spec.js @@ -1,6 +1,7 @@ /* eslint no-param-reassign: "off" */ import $ from 'jquery'; +import { emojiFixtureMap, initEmojiMock, describeEmojiFields } from 'helpers/emoji'; import '~/lib/utils/jquery_at_who'; import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete'; @@ -119,7 +120,7 @@ describe('GfmAutoComplete', () => { const defaultMatcher = (context, flag, subtext) => gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext); - const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$', '+']; + const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$']; const otherFlags = ['/', ':']; const flags = flagsUseDefaultMatcher.concat(otherFlags); @@ -153,6 +154,7 @@ describe('GfmAutoComplete', () => { 'я', '.', "'", + '+', '-', '_', ]; @@ -416,8 +418,9 @@ describe('GfmAutoComplete', () => { let $textarea; beforeEach(() => { + setFixtures('<textarea></textarea>'); autocomplete = new GfmAutoComplete(dataSources); - $textarea = $('<textarea></textarea>'); + $textarea = $('textarea'); autocomplete.setup($textarea, { labels: true }); }); @@ -488,4 +491,114 @@ describe('GfmAutoComplete', () => { `('$input shows $output.length labels', expectLabels); }); }); + + describe('emoji', () => { + const { atom, heart, star } = emojiFixtureMap; + const assertInserted = ({ input, subject, emoji }) => + expect(subject).toBe(`:${emoji?.name || input}:`); + const assertTemplated = ({ input, subject, emoji, field }) => + expect(subject.replace(/\s+/g, ' ')).toBe( + `<li>${field || input} <gl-emoji data-name="${emoji?.name || input}"></gl-emoji> </li>`, + ); + + let mock; + + beforeEach(async () => { + mock = await initEmojiMock(); + + await new GfmAutoComplete({}).loadEmojiData({ atwho() {}, trigger() {} }, ':'); + if (!GfmAutoComplete.glEmojiTag) throw new Error('emoji not loaded'); + }); + + afterEach(() => { + mock.restore(); + }); + + describe.each` + name | inputFormat | assert + ${'insertTemplateFunction'} | ${name => ({ name })} | ${assertInserted} + ${'templateFunction'} | ${name => name} | ${assertTemplated} + `('Emoji.$name', ({ name, inputFormat, assert }) => { + const execute = (accessor, input, emoji) => + assert({ + input, + emoji, + field: accessor && accessor(emoji), + subject: GfmAutoComplete.Emoji[name](inputFormat(input)), + }); + + describeEmojiFields('for $field', ({ accessor }) => { + it('should work with lowercase', () => { + execute(accessor, accessor(atom), atom); + }); + + it('should work with uppercase', () => { + execute(accessor, accessor(atom).toUpperCase(), atom); + }); + + it('should work with partial value', () => { + execute(accessor, accessor(atom).slice(1), atom); + }); + }); + + it('should work with unicode value', () => { + execute(null, atom.moji, atom); + }); + + it('should pass through unknown value', () => { + execute(null, 'foo bar baz'); + }); + }); + + const expectEmojiOrder = (first, second) => { + const keys = Object.keys(emojiFixtureMap); + const firstIndex = keys.indexOf(first); + const secondIndex = keys.indexOf(second); + expect(firstIndex).toBeGreaterThanOrEqual(0); + expect(secondIndex).toBeGreaterThanOrEqual(0); + expect(firstIndex).toBeLessThan(secondIndex); + }; + + describe('Emoji.insertTemplateFunction', () => { + it('should map ":heart" to :heart: [regression]', () => { + // the bug mapped heart to black_heart because the latter sorted first + expectEmojiOrder('black_heart', 'heart'); + + const item = GfmAutoComplete.Emoji.insertTemplateFunction({ name: 'heart' }); + expect(item).toEqual(`:${heart.name}:`); + }); + + it('should map ":star" to :star: [regression]', () => { + // the bug mapped star to custard because the latter sorted first + expectEmojiOrder('custard', 'star'); + + const item = GfmAutoComplete.Emoji.insertTemplateFunction({ name: 'star' }); + expect(item).toEqual(`:${star.name}:`); + }); + }); + + describe('Emoji.templateFunction', () => { + it('should map ":heart" to ❤ [regression]', () => { + // the bug mapped heart to black_heart because the latter sorted first + expectEmojiOrder('black_heart', 'heart'); + + const item = GfmAutoComplete.Emoji.templateFunction('heart') + .replace(/(<gl-emoji)\s+(data-name)/, '$1 $2') + .replace(/>\s+|\s+</g, s => s.trim()); + expect(item).toEqual( + `<li>${heart.name}<gl-emoji data-name="${heart.name}"></gl-emoji></li>`, + ); + }); + + it('should map ":star" to ⭐ [regression]', () => { + // the bug mapped star to custard because the latter sorted first + expectEmojiOrder('custard', 'star'); + + const item = GfmAutoComplete.Emoji.templateFunction('star') + .replace(/(<gl-emoji)\s+(data-name)/, '$1 $2') + .replace(/>\s+|\s+</g, s => s.trim()); + expect(item).toEqual(`<li>${star.name}<gl-emoji data-name="${star.name}"></gl-emoji></li>`); + }); + }); + }); }); |