Commit 3183f0be authored by Mike Greiling's avatar Mike Greiling

Merge branch 'issuable-award-fuzzy-search' into 'master'

Use fuzzy matching for issuable awards

See merge request gitlab-org/gitlab!42674
parents a0127b6b 1e58e447
......@@ -572,7 +572,7 @@ export class AwardsHandler {
}
findMatchingEmojiElements(query) {
const emojiMatches = this.emoji.filterEmojiNamesByAlias(query);
const emojiMatches = this.emoji.queryEmojiNames(query);
const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]');
const $matchingElements = $emojiElements.filter(
(i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0,
......
import { uniq } from 'lodash';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import emojiAliases from 'emojis/aliases.json';
import axios from '../lib/utils/axios_utils';
......@@ -62,13 +63,18 @@ export function isEmojiNameValid(name) {
return validEmojiNames.indexOf(name) >= 0;
}
export function filterEmojiNames(filter) {
const match = filter.toLowerCase();
return validEmojiNames.filter(name => name.indexOf(match) >= 0);
}
export function filterEmojiNamesByAlias(filter) {
return uniq(filterEmojiNames(filter).map(name => normalizeEmojiName(name)));
/**
* Search emoji by name or alias. Returns a normalized, deduplicated list of
* names.
*
* Calling with an empty filter returns an empty array.
*
* @param {String}
* @returns {Array}
*/
export function queryEmojiNames(filter) {
const matches = fuzzaldrinPlus.filter(validEmojiNames, filter);
return uniq(matches.map(name => normalizeEmojiName(name)));
}
let emojiCategoryMap;
......
---
title: Use fuzzy matching for issuable awards
merge_request: 42674
author: Ethan Reesor (@firelizzard)
type: added
......@@ -309,6 +309,16 @@ describe('AwardsHandler', () => {
expect($('[data-name=alien]').is(':visible')).toBe(true);
expect($('.js-emoji-menu-search').val()).toBe('');
});
it('should fuzzy filter the emoji', async () => {
await openAndWaitForEmojiMenu();
awardsHandler.searchEmojis('sgls');
expect($('[data-name=angel]').is(':visible')).toBe(false);
expect($('[data-name=anger]').is(':visible')).toBe(false);
expect($('[data-name=sunglasses]').is(':visible')).toBe(true);
});
});
describe('emoji menu', () => {
......
import MockAdapter from 'axios-mock-adapter';
import { trimText } from 'helpers/text_helper';
import axios from '~/lib/utils/axios_utils';
import { initEmojiMap, glEmojiTag, EMOJI_VERSION } from '~/emoji';
import { initEmojiMap, glEmojiTag, queryEmojiNames, EMOJI_VERSION } from '~/emoji';
import isEmojiUnicodeSupported, {
isFlagEmoji,
isRainbowFlagEmoji,
......@@ -57,8 +57,15 @@ describe('gl_emoji', () => {
let mock;
beforeEach(() => {
const emojiData = Object.fromEntries(
Object.values(emojiFixtureMap).map(m => {
const { name: n, moji: e, unicodeVersion: u, category: c, description: d } = m;
return [n, { c, e, d, u }];
}),
);
mock = new MockAdapter(axios);
mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200);
mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(emojiData));
return initEmojiMap().catch(() => {});
});
......@@ -378,4 +385,15 @@ describe('gl_emoji', () => {
expect(isSupported).toBeFalsy();
});
});
describe('queryEmojiNames', () => {
const contains = (e, term) => {
const names = queryEmojiNames(term);
expect(names.indexOf(e.name) >= 0).toBe(true);
};
it('should match by name', () => contains(emojiFixtureMap.grey_question, 'grey_question'));
it('should match by partial name', () => contains(emojiFixtureMap.grey_question, 'question'));
it('should fuzzy match by name', () => contains(emojiFixtureMap.grey_question, 'grqtn'));
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment