Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/gfm_auto_complete_spec.js')
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js117
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>`);
+ });
+ });
+ });
});