Merge branch '32563-remove-duplicated-config-code-for-filtered-search-dropdowns' into 'master'
Resolve "Remove duplicated config code for filtered search dropdowns" Closes #32563 See merge request !11512
This commit is contained in:
commit
6cbc69aa7e
|
@ -13,13 +13,17 @@ export default {
|
|||
required: false,
|
||||
default: true,
|
||||
},
|
||||
allowedKeys: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
processedItems() {
|
||||
return this.items.map((item) => {
|
||||
const { tokens, searchToken }
|
||||
= gl.FilteredSearchTokenizer.processTokens(item);
|
||||
= gl.FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
|
||||
|
||||
const resultantTokens = tokens.map(token => ({
|
||||
prefix: `${token.key}:`,
|
||||
|
|
|
@ -2,14 +2,18 @@ import Filter from '~/droplab/plugins/filter';
|
|||
import './filtered_search_dropdown';
|
||||
|
||||
class DropdownHint extends gl.FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter) {
|
||||
constructor(droplab, dropdown, input, tokenKeys, filter) {
|
||||
super(droplab, dropdown, input, filter);
|
||||
this.config = {
|
||||
Filter: {
|
||||
template: 'hint',
|
||||
filterFunction: gl.DropdownUtils.filterHint.bind(null, input),
|
||||
filterFunction: gl.DropdownUtils.filterHint.bind(null, {
|
||||
input,
|
||||
allowedKeys: tokenKeys.getKeys(),
|
||||
}),
|
||||
},
|
||||
};
|
||||
this.tokenKeys = tokenKeys;
|
||||
}
|
||||
|
||||
itemClicked(e) {
|
||||
|
@ -52,20 +56,13 @@ class DropdownHint extends gl.FilteredSearchDropdown {
|
|||
}
|
||||
|
||||
renderContent() {
|
||||
const dropdownData = [];
|
||||
|
||||
[].forEach.call(this.input.closest('.filtered-search-box-input-container').querySelectorAll('.dropdown-menu'), (dropdownMenu) => {
|
||||
const { icon, hint, tag, type } = dropdownMenu.dataset;
|
||||
if (icon && hint && tag) {
|
||||
dropdownData.push(
|
||||
Object.assign({
|
||||
icon: `fa-${icon}`,
|
||||
hint,
|
||||
tag: `<${tag}>`,
|
||||
}, type && { type }),
|
||||
);
|
||||
}
|
||||
});
|
||||
const dropdownData = gl.FilteredSearchTokenKeys.get()
|
||||
.map(tokenKey => ({
|
||||
icon: `fa-${tokenKey.icon}`,
|
||||
hint: tokenKey.key,
|
||||
tag: `<${tokenKey.symbol}${tokenKey.key}>`,
|
||||
type: tokenKey.type,
|
||||
}));
|
||||
|
||||
this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config);
|
||||
this.droplab.setData(this.hookId, dropdownData);
|
||||
|
|
|
@ -5,7 +5,7 @@ import Filter from '~/droplab/plugins/filter';
|
|||
import './filtered_search_dropdown';
|
||||
|
||||
class DropdownNonUser extends gl.FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter, endpoint, symbol) {
|
||||
constructor(droplab, dropdown, input, tokenKeys, filter, endpoint, symbol) {
|
||||
super(droplab, dropdown, input, filter);
|
||||
this.symbol = symbol;
|
||||
this.config = {
|
||||
|
|
|
@ -4,7 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter';
|
|||
import './filtered_search_dropdown';
|
||||
|
||||
class DropdownUser extends gl.FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter) {
|
||||
constructor(droplab, dropdown, input, tokenKeys, filter) {
|
||||
super(droplab, dropdown, input, filter);
|
||||
this.config = {
|
||||
AjaxFilter: {
|
||||
|
@ -25,6 +25,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
|
|||
},
|
||||
},
|
||||
};
|
||||
this.tokenKeys = tokenKeys;
|
||||
}
|
||||
|
||||
itemClicked(e) {
|
||||
|
@ -43,7 +44,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
|
|||
|
||||
getSearchInput() {
|
||||
const query = gl.DropdownUtils.getSearchInput(this.input);
|
||||
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query);
|
||||
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
|
||||
|
||||
let value = lastToken || '';
|
||||
|
||||
|
|
|
@ -50,10 +50,12 @@ class DropdownUtils {
|
|||
return updatedItem;
|
||||
}
|
||||
|
||||
static filterHint(input, item) {
|
||||
static filterHint(config, item) {
|
||||
const { input, allowedKeys } = config;
|
||||
const updatedItem = item;
|
||||
const searchInput = gl.DropdownUtils.getSearchQuery(input);
|
||||
const { lastToken, tokens } = gl.FilteredSearchTokenizer.processTokens(searchInput);
|
||||
const { lastToken, tokens } =
|
||||
gl.FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
|
||||
const lastKey = lastToken.key || lastToken || '';
|
||||
const allowMultiple = item.type === 'array';
|
||||
const itemInExistingTokens = tokens.some(t => t.key === item.hint);
|
||||
|
|
|
@ -2,10 +2,10 @@ import DropLab from '~/droplab/drop_lab';
|
|||
import FilteredSearchContainer from './container';
|
||||
|
||||
class FilteredSearchDropdownManager {
|
||||
constructor(baseEndpoint = '', page) {
|
||||
constructor(baseEndpoint = '', tokenizer, page) {
|
||||
this.container = FilteredSearchContainer.container;
|
||||
this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
|
||||
this.tokenizer = gl.FilteredSearchTokenizer;
|
||||
this.tokenizer = tokenizer;
|
||||
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
|
||||
this.filteredSearchInput = this.container.querySelector('.filtered-search');
|
||||
this.page = page;
|
||||
|
@ -98,7 +98,8 @@ class FilteredSearchDropdownManager {
|
|||
|
||||
if (!mappingKey.reference) {
|
||||
const dl = this.droplab;
|
||||
const defaultArguments = [null, dl, element, this.filteredSearchInput, key];
|
||||
const defaultArguments =
|
||||
[null, dl, element, this.filteredSearchInput, this.filteredSearchTokenKeys, key];
|
||||
const glArguments = defaultArguments.concat(mappingKey.extraArguments || []);
|
||||
|
||||
// Passing glArguments to `new gl[glClass](<arguments>)`
|
||||
|
@ -141,7 +142,8 @@ class FilteredSearchDropdownManager {
|
|||
|
||||
setDropdown() {
|
||||
const query = gl.DropdownUtils.getSearchQuery(true);
|
||||
const { lastToken, searchToken } = this.tokenizer.processTokens(query);
|
||||
const { lastToken, searchToken } =
|
||||
this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys());
|
||||
|
||||
if (this.currentDropdown) {
|
||||
this.updateCurrentDropdownOffset();
|
||||
|
|
|
@ -15,6 +15,7 @@ class FilteredSearchManager {
|
|||
|
||||
this.recentSearchesStore = new RecentSearchesStore({
|
||||
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
|
||||
allowedKeys: this.filteredSearchTokenKeys.getKeys(),
|
||||
});
|
||||
const searchHistoryDropdownElement = document.querySelector('.js-filtered-search-history-dropdown');
|
||||
const projectPath = searchHistoryDropdownElement ?
|
||||
|
@ -46,7 +47,7 @@ class FilteredSearchManager {
|
|||
|
||||
if (this.filteredSearchInput) {
|
||||
this.tokenizer = gl.FilteredSearchTokenizer;
|
||||
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page);
|
||||
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', this.tokenizer, page);
|
||||
|
||||
this.recentSearchesRoot = new RecentSearchesRoot(
|
||||
this.recentSearchesStore,
|
||||
|
@ -318,7 +319,7 @@ class FilteredSearchManager {
|
|||
handleInputVisualToken() {
|
||||
const input = this.filteredSearchInput;
|
||||
const { tokens, searchToken }
|
||||
= gl.FilteredSearchTokenizer.processTokens(input.value);
|
||||
= this.tokenizer.processTokens(input.value, this.filteredSearchTokenKeys.getKeys());
|
||||
const { isLastVisualTokenValid }
|
||||
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
||||
|
||||
|
@ -444,7 +445,7 @@ class FilteredSearchManager {
|
|||
this.saveCurrentSearchQuery();
|
||||
|
||||
const { tokens, searchToken }
|
||||
= this.tokenizer.processTokens(searchQuery);
|
||||
= this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys());
|
||||
const currentState = gl.utils.getParameterByName('state') || 'opened';
|
||||
paths.push(`state=${currentState}`);
|
||||
|
||||
|
|
|
@ -3,21 +3,25 @@ const tokenKeys = [{
|
|||
type: 'string',
|
||||
param: 'username',
|
||||
symbol: '@',
|
||||
icon: 'pencil',
|
||||
}, {
|
||||
key: 'assignee',
|
||||
type: 'string',
|
||||
param: 'username',
|
||||
symbol: '@',
|
||||
icon: 'user',
|
||||
}, {
|
||||
key: 'milestone',
|
||||
type: 'string',
|
||||
param: 'title',
|
||||
symbol: '%',
|
||||
icon: 'clock-o',
|
||||
}, {
|
||||
key: 'label',
|
||||
type: 'array',
|
||||
param: 'name[]',
|
||||
symbol: '~',
|
||||
icon: 'tag',
|
||||
}];
|
||||
|
||||
const alternativeTokenKeys = [{
|
||||
|
@ -56,6 +60,10 @@ class FilteredSearchTokenKeys {
|
|||
return tokenKeys;
|
||||
}
|
||||
|
||||
static getKeys() {
|
||||
return tokenKeys.map(i => i.key);
|
||||
}
|
||||
|
||||
static getAlternatives() {
|
||||
return alternativeTokenKeys;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import './filtered_search_token_keys';
|
||||
|
||||
class FilteredSearchTokenizer {
|
||||
static processTokens(input) {
|
||||
const allowedKeys = gl.FilteredSearchTokenKeys.get().map(i => i.key);
|
||||
static processTokens(input, allowedKeys) {
|
||||
// Regex extracts `(token):(symbol)(value)`
|
||||
// Values that start with a double quote must end in a double quote (same for single)
|
||||
const tokenRegex = new RegExp(`(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, 'g');
|
||||
|
|
|
@ -37,6 +37,7 @@ class RecentSearchesRoot {
|
|||
<recent-searches-dropdown-content
|
||||
:items="recentSearches"
|
||||
:is-local-storage-available="isLocalStorageAvailable"
|
||||
:allowed-keys="allowedKeys"
|
||||
/>
|
||||
`,
|
||||
components: {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import _ from 'underscore';
|
||||
|
||||
class RecentSearchesStore {
|
||||
constructor(initialState = {}) {
|
||||
constructor(initialState = {}, allowedKeys) {
|
||||
this.state = Object.assign({
|
||||
isLocalStorageAvailable: true,
|
||||
recentSearches: [],
|
||||
allowedKeys,
|
||||
}, initialState);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
{{hint}}
|
||||
%span.js-filter-tag.dropdown-light-content
|
||||
{{tag}}
|
||||
#js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'pencil', hint: 'author', tag: '@author' } }
|
||||
#js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu
|
||||
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
|
||||
%li.filter-dropdown-item
|
||||
%button.btn.btn-link.dropdown-user
|
||||
|
@ -55,7 +55,7 @@
|
|||
{{name}}
|
||||
%span.dropdown-light-content
|
||||
@{{username}}
|
||||
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'user', hint: 'assignee', tag: '@assignee' } }
|
||||
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
|
||||
%ul{ data: { dropdown: true } }
|
||||
%li.filter-dropdown-item{ data: { value: 'none' } }
|
||||
%button.btn.btn-link
|
||||
|
@ -70,7 +70,7 @@
|
|||
{{name}}
|
||||
%span.dropdown-light-content
|
||||
@{{username}}
|
||||
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'clock-o', hint: 'milestone', tag: '%milestone' } }
|
||||
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
|
||||
%ul{ data: { dropdown: true } }
|
||||
%li.filter-dropdown-item{ data: { value: 'none' } }
|
||||
%button.btn.btn-link
|
||||
|
@ -86,7 +86,7 @@
|
|||
%li.filter-dropdown-item
|
||||
%button.btn.btn-link.js-data-value
|
||||
{{title}}
|
||||
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'tag', hint: 'label', tag: '~label', type: 'array' } }
|
||||
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
|
||||
%ul{ data: { dropdown: true } }
|
||||
%li.filter-dropdown-item{ data: { value: 'none' } }
|
||||
%button.btn.btn-link
|
||||
|
|
|
@ -2,6 +2,8 @@ import Vue from 'vue';
|
|||
import eventHub from '~/filtered_search/event_hub';
|
||||
import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content';
|
||||
|
||||
require('~/filtered_search/filtered_search_token_keys');
|
||||
|
||||
const createComponent = (propsData) => {
|
||||
const Component = Vue.extend(RecentSearchesDropdownContent);
|
||||
|
||||
|
@ -17,12 +19,14 @@ const trimMarkupWhitespace = text => text.replace(/(\n|\s)+/gm, ' ').trim();
|
|||
describe('RecentSearchesDropdownContent', () => {
|
||||
const propsDataWithoutItems = {
|
||||
items: [],
|
||||
allowedKeys: gl.FilteredSearchTokenKeys.getKeys(),
|
||||
};
|
||||
const propsDataWithItems = {
|
||||
items: [
|
||||
'foo',
|
||||
'author:@root label:~foo bar',
|
||||
],
|
||||
allowedKeys: gl.FilteredSearchTokenKeys.getKeys(),
|
||||
};
|
||||
|
||||
let vm;
|
||||
|
|
|
@ -12,7 +12,7 @@ describe('Dropdown User', () => {
|
|||
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
|
||||
spyOn(gl.DropdownUtils, 'getSearchInput').and.callFake(() => {});
|
||||
|
||||
dropdownUser = new gl.DropdownUser();
|
||||
dropdownUser = new gl.DropdownUser(null, null, null, gl.FilteredSearchTokenKeys);
|
||||
});
|
||||
|
||||
it('should not return the double quote found in value', () => {
|
||||
|
|
|
@ -122,6 +122,7 @@ describe('Dropdown Utils', () => {
|
|||
|
||||
describe('filterHint', () => {
|
||||
let input;
|
||||
let allowedKeys;
|
||||
|
||||
beforeEach(() => {
|
||||
setFixtures(`
|
||||
|
@ -133,30 +134,38 @@ describe('Dropdown Utils', () => {
|
|||
`);
|
||||
|
||||
input = document.getElementById('test');
|
||||
allowedKeys = gl.FilteredSearchTokenKeys.getKeys();
|
||||
});
|
||||
|
||||
function config() {
|
||||
return {
|
||||
input,
|
||||
allowedKeys,
|
||||
};
|
||||
}
|
||||
|
||||
it('should filter', () => {
|
||||
input.value = 'l';
|
||||
let updatedItem = gl.DropdownUtils.filterHint(input, {
|
||||
let updatedItem = gl.DropdownUtils.filterHint(config(), {
|
||||
hint: 'label',
|
||||
});
|
||||
expect(updatedItem.droplab_hidden).toBe(false);
|
||||
|
||||
input.value = 'o';
|
||||
updatedItem = gl.DropdownUtils.filterHint(input, {
|
||||
updatedItem = gl.DropdownUtils.filterHint(config(), {
|
||||
hint: 'label',
|
||||
});
|
||||
expect(updatedItem.droplab_hidden).toBe(true);
|
||||
});
|
||||
|
||||
it('should return droplab_hidden false when item has no hint', () => {
|
||||
const updatedItem = gl.DropdownUtils.filterHint(input, {}, '');
|
||||
const updatedItem = gl.DropdownUtils.filterHint(config(), {}, '');
|
||||
expect(updatedItem.droplab_hidden).toBe(false);
|
||||
});
|
||||
|
||||
it('should allow multiple if item.type is array', () => {
|
||||
input.value = 'label:~first la';
|
||||
const updatedItem = gl.DropdownUtils.filterHint(input, {
|
||||
const updatedItem = gl.DropdownUtils.filterHint(config(), {
|
||||
hint: 'label',
|
||||
type: 'array',
|
||||
});
|
||||
|
@ -165,12 +174,12 @@ describe('Dropdown Utils', () => {
|
|||
|
||||
it('should prevent multiple if item.type is not array', () => {
|
||||
input.value = 'milestone:~first mile';
|
||||
let updatedItem = gl.DropdownUtils.filterHint(input, {
|
||||
let updatedItem = gl.DropdownUtils.filterHint(config(), {
|
||||
hint: 'milestone',
|
||||
});
|
||||
expect(updatedItem.droplab_hidden).toBe(true);
|
||||
|
||||
updatedItem = gl.DropdownUtils.filterHint(input, {
|
||||
updatedItem = gl.DropdownUtils.filterHint(config(), {
|
||||
hint: 'milestone',
|
||||
type: 'string',
|
||||
});
|
||||
|
|
|
@ -80,6 +80,7 @@ describe('Filtered Search Manager', () => {
|
|||
expect(RecentSearchesService.isAvailable).toHaveBeenCalled();
|
||||
expect(recentSearchesStoreSrc.default).toHaveBeenCalledWith({
|
||||
isLocalStorageAvailable,
|
||||
allowedKeys: gl.FilteredSearchTokenKeys.getKeys(),
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ import '~/filtered_search/filtered_search_token_keys';
|
|||
import '~/filtered_search/filtered_search_tokenizer';
|
||||
|
||||
describe('Filtered Search Tokenizer', () => {
|
||||
const allowedKeys = gl.FilteredSearchTokenKeys.getKeys();
|
||||
|
||||
describe('processTokens', () => {
|
||||
it('returns for input containing only search value', () => {
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('searchTerm');
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('searchTerm', allowedKeys);
|
||||
expect(results.searchToken).toBe('searchTerm');
|
||||
expect(results.tokens.length).toBe(0);
|
||||
expect(results.lastToken).toBe(results.searchToken);
|
||||
|
@ -13,7 +15,7 @@ describe('Filtered Search Tokenizer', () => {
|
|||
|
||||
it('returns for input containing only tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer
|
||||
.processTokens('author:@root label:~"Very Important" milestone:%v1.0 assignee:none');
|
||||
.processTokens('author:@root label:~"Very Important" milestone:%v1.0 assignee:none', allowedKeys);
|
||||
expect(results.searchToken).toBe('');
|
||||
expect(results.tokens.length).toBe(4);
|
||||
expect(results.tokens[3]).toBe(results.lastToken);
|
||||
|
@ -37,7 +39,7 @@ describe('Filtered Search Tokenizer', () => {
|
|||
|
||||
it('returns for input starting with search value and ending with tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer
|
||||
.processTokens('searchTerm anotherSearchTerm milestone:none');
|
||||
.processTokens('searchTerm anotherSearchTerm milestone:none', allowedKeys);
|
||||
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
|
||||
expect(results.tokens.length).toBe(1);
|
||||
expect(results.tokens[0]).toBe(results.lastToken);
|
||||
|
@ -48,7 +50,7 @@ describe('Filtered Search Tokenizer', () => {
|
|||
|
||||
it('returns for input starting with tokens and ending with search value', () => {
|
||||
const results = gl.FilteredSearchTokenizer
|
||||
.processTokens('assignee:@user searchTerm');
|
||||
.processTokens('assignee:@user searchTerm', allowedKeys);
|
||||
|
||||
expect(results.searchToken).toBe('searchTerm');
|
||||
expect(results.tokens.length).toBe(1);
|
||||
|
@ -60,7 +62,7 @@ describe('Filtered Search Tokenizer', () => {
|
|||
|
||||
it('returns for input containing search value wrapped between tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer
|
||||
.processTokens('author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none');
|
||||
.processTokens('author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none', allowedKeys);
|
||||
|
||||
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
|
||||
expect(results.tokens.length).toBe(3);
|
||||
|
@ -81,7 +83,7 @@ describe('Filtered Search Tokenizer', () => {
|
|||
|
||||
it('returns for input containing search value in between tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer
|
||||
.processTokens('author:@root searchTerm assignee:none anotherSearchTerm label:~Doing');
|
||||
.processTokens('author:@root searchTerm assignee:none anotherSearchTerm label:~Doing', allowedKeys);
|
||||
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
|
||||
expect(results.tokens.length).toBe(3);
|
||||
expect(results.tokens[2]).toBe(results.lastToken);
|
||||
|
@ -100,14 +102,14 @@ describe('Filtered Search Tokenizer', () => {
|
|||
});
|
||||
|
||||
it('returns search value for invalid tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('fake:token');
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('fake:token', allowedKeys);
|
||||
expect(results.lastToken).toBe('fake:token');
|
||||
expect(results.searchToken).toBe('fake:token');
|
||||
expect(results.tokens.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('returns search value and token for mix of valid and invalid tokens', () => {
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('label:real fake:token');
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('label:real fake:token', allowedKeys);
|
||||
expect(results.tokens.length).toEqual(1);
|
||||
expect(results.tokens[0].key).toBe('label');
|
||||
expect(results.tokens[0].value).toBe('real');
|
||||
|
@ -117,13 +119,13 @@ describe('Filtered Search Tokenizer', () => {
|
|||
});
|
||||
|
||||
it('returns search value for invalid symbols', () => {
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('std::includes');
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('std::includes', allowedKeys);
|
||||
expect(results.lastToken).toBe('std::includes');
|
||||
expect(results.searchToken).toBe('std::includes');
|
||||
});
|
||||
|
||||
it('removes duplicated values', () => {
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('label:~foo label:~foo');
|
||||
const results = gl.FilteredSearchTokenizer.processTokens('label:~foo label:~foo', allowedKeys);
|
||||
expect(results.tokens.length).toBe(1);
|
||||
expect(results.tokens[0].key).toBe('label');
|
||||
expect(results.tokens[0].value).toBe('foo');
|
||||
|
|
Loading…
Reference in New Issue