summaryrefslogtreecommitdiff
path: root/spec/javascripts/filtered_search
diff options
context:
space:
mode:
Diffstat (limited to 'spec/javascripts/filtered_search')
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js374
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js580
-rw-r--r--spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js152
-rw-r--r--spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js148
-rw-r--r--spec/javascripts/filtered_search/recent_searches_root_spec.js30
-rw-r--r--spec/javascripts/filtered_search/services/recent_searches_service_spec.js158
-rw-r--r--spec/javascripts/filtered_search/visual_token_value_spec.js389
7 files changed, 0 insertions, 1831 deletions
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
deleted file mode 100644
index 6eda4f391a4..00000000000
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ /dev/null
@@ -1,374 +0,0 @@
-import DropdownUtils from '~/filtered_search/dropdown_utils';
-import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-
-describe('Dropdown Utils', () => {
- const issueListFixture = 'issues/issue_list.html';
- preloadFixtures(issueListFixture);
-
- describe('getEscapedText', () => {
- it('should return same word when it has no space', () => {
- const escaped = DropdownUtils.getEscapedText('textWithoutSpace');
-
- expect(escaped).toBe('textWithoutSpace');
- });
-
- it('should escape with double quotes', () => {
- let escaped = DropdownUtils.getEscapedText('text with space');
-
- expect(escaped).toBe('"text with space"');
-
- escaped = DropdownUtils.getEscapedText("won't fix");
-
- expect(escaped).toBe('"won\'t fix"');
- });
-
- it('should escape with single quotes', () => {
- const escaped = DropdownUtils.getEscapedText('won"t fix');
-
- expect(escaped).toBe("'won\"t fix'");
- });
-
- it('should escape with single quotes by default', () => {
- const escaped = DropdownUtils.getEscapedText('won"t\' fix');
-
- expect(escaped).toBe("'won\"t' fix'");
- });
- });
-
- describe('filterWithSymbol', () => {
- let input;
- const item = {
- title: '@root',
- };
-
- beforeEach(() => {
- setFixtures(`
- <input type="text" id="test" />
- `);
-
- input = document.getElementById('test');
- });
-
- it('should filter without symbol', () => {
- input.value = 'roo';
-
- const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with symbol', () => {
- input.value = '@roo';
-
- const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- describe('filters multiple word title', () => {
- const multipleWordItem = {
- title: 'Community Contributions',
- };
-
- it('should filter with double quote', () => {
- input.value = '"';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote and symbol', () => {
- input.value = '~"';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote and multiple words', () => {
- input.value = '"community con';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with double quote, symbol and multiple words', () => {
- input.value = '~"community con';
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote', () => {
- input.value = "'";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote and symbol', () => {
- input.value = "~'";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote and multiple words', () => {
- input.value = "'community con";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should filter with single quote, symbol and multiple words', () => {
- input.value = "~'community con";
-
- const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
- });
- });
-
- describe('filterHint', () => {
- let input;
- let allowedKeys;
-
- beforeEach(() => {
- setFixtures(`
- <ul class="tokens-container">
- <li class="input-token">
- <input class="filtered-search" type="text" id="test" />
- </li>
- </ul>
- `);
-
- input = document.getElementById('test');
- allowedKeys = IssuableFilteredSearchTokenKeys.getKeys();
- });
-
- function config() {
- return {
- input,
- allowedKeys,
- };
- }
-
- it('should filter', () => {
- input.value = 'l';
- let updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'label',
- });
-
- expect(updatedItem.droplab_hidden).toBe(false);
-
- input.value = 'o';
- updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'label',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
- });
-
- it('should return droplab_hidden false when item has no hint', () => {
- const updatedItem = 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 = DropdownUtils.filterHint(config(), {
- hint: 'label',
- type: 'array',
- });
-
- expect(updatedItem.droplab_hidden).toBe(false);
- });
-
- it('should prevent multiple if item.type is not array', () => {
- input.value = 'milestone:~first mile';
- let updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'milestone',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
-
- updatedItem = DropdownUtils.filterHint(config(), {
- hint: 'milestone',
- type: 'string',
- });
-
- expect(updatedItem.droplab_hidden).toBe(true);
- });
- });
-
- describe('setDataValueIfSelected', () => {
- beforeEach(() => {
- spyOn(FilteredSearchDropdownManager, 'addWordToInput').and.callFake(() => {});
- });
-
- it('calls addWordToInput when dataValue exists', () => {
- const selected = {
- getAttribute: () => 'value',
- hasAttribute: () => false,
- };
-
- DropdownUtils.setDataValueIfSelected(null, '=', selected);
-
- expect(FilteredSearchDropdownManager.addWordToInput.calls.count()).toEqual(1);
- });
-
- it('returns true when dataValue exists', () => {
- const selected = {
- getAttribute: () => 'value',
- hasAttribute: () => false,
- };
-
- const result = DropdownUtils.setDataValueIfSelected(null, '=', selected);
- const result2 = DropdownUtils.setDataValueIfSelected(null, '!=', selected);
-
- expect(result).toBe(true);
- expect(result2).toBe(true);
- });
-
- it('returns false when dataValue does not exist', () => {
- const selected = {
- getAttribute: () => null,
- };
-
- const result = DropdownUtils.setDataValueIfSelected(null, '=', selected);
- const result2 = DropdownUtils.setDataValueIfSelected(null, '!=', selected);
-
- expect(result).toBe(false);
- expect(result2).toBe(false);
- });
- });
-
- describe('getInputSelectionPosition', () => {
- describe('word with trailing spaces', () => {
- const value = 'label:none ';
-
- it('should return selectionStart when cursor is at the trailing space', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 11,
- value,
- });
-
- expect(left).toBe(11);
- expect(right).toBe(11);
- });
-
- it('should return input when cursor is at the start of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 0,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
-
- it('should return input when cursor is at the middle of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 7,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
-
- it('should return input when cursor is at the end of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 10,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(10);
- });
- });
-
- describe('multiple words', () => {
- const value = 'label:~"Community Contribution"';
-
- it('should return input when cursor is after the first word', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 17,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(31);
- });
-
- it('should return input when cursor is before the second word', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 18,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(31);
- });
- });
-
- describe('incomplete multiple words', () => {
- const value = 'label:~"Community Contribution';
-
- it('should return entire input when cursor is at the start of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 0,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(30);
- });
-
- it('should return entire input when cursor is at the end of input', () => {
- const { left, right } = DropdownUtils.getInputSelectionPosition({
- selectionStart: 30,
- value,
- });
-
- expect(left).toBe(0);
- expect(right).toBe(30);
- });
- });
- });
-
- describe('getSearchQuery', () => {
- let authorToken;
-
- beforeEach(() => {
- loadFixtures(issueListFixture);
-
- authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
- const searchTermToken = FilteredSearchSpecHelper.createSearchVisualToken('search term');
-
- const tokensContainer = document.querySelector('.tokens-container');
- tokensContainer.appendChild(searchTermToken);
- tokensContainer.appendChild(authorToken);
- });
-
- it('uses original value if present', () => {
- const originalValue = 'original dance';
- const valueContainer = authorToken.querySelector('.value-container');
- valueContainer.dataset.originalValue = originalValue;
-
- const searchQuery = DropdownUtils.getSearchQuery();
-
- expect(searchQuery).toBe(' search term author:=original dance');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
deleted file mode 100644
index d0b54a16747..00000000000
--- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js
+++ /dev/null
@@ -1,580 +0,0 @@
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import '~/lib/utils/common_utils';
-import DropdownUtils from '~/filtered_search/dropdown_utils';
-import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
-import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes';
-
-describe('Filtered Search Manager', function() {
- let input;
- let manager;
- let tokensContainer;
- const page = 'issues';
- const placeholder = 'Search or filter results...';
-
- function dispatchBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchDeleteEvent(element, eventType) {
- const event = new Event(eventType);
- event.keyCode = DELETE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchAltBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.altKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchCtrlBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.ctrlKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function dispatchMetaBackspaceEvent(element, eventType) {
- const event = new Event(eventType);
- event.metaKey = true;
- event.keyCode = BACKSPACE_KEY_CODE;
- element.dispatchEvent(event);
- }
-
- function getVisualTokens() {
- return tokensContainer.querySelectorAll('.js-visual-token');
- }
-
- beforeEach(() => {
- setFixtures(`
- <div class="filtered-search-box">
- <form>
- <ul class="tokens-container list-unstyled">
- ${FilteredSearchSpecHelper.createInputHTML(placeholder)}
- </ul>
- <button class="clear-search" type="button">
- <i class="fa fa-times"></i>
- </button>
- </form>
- </div>
- `);
-
- spyOn(FilteredSearchDropdownManager.prototype, 'setDropdown').and.callFake(() => {});
- });
-
- const initializeManager = () => {
- /* eslint-disable jasmine/no-unsafe-spy */
- spyOn(FilteredSearchManager.prototype, 'loadSearchParamsFromURL').and.callFake(() => {});
- spyOn(FilteredSearchManager.prototype, 'tokenChange').and.callFake(() => {});
- spyOn(FilteredSearchDropdownManager.prototype, 'updateDropdownOffset').and.callFake(() => {});
- spyOn(gl.utils, 'getParameterByName').and.returnValue(null);
- spyOn(FilteredSearchVisualTokens, 'unselectTokens').and.callThrough();
- /* eslint-enable jasmine/no-unsafe-spy */
-
- input = document.querySelector('.filtered-search');
- tokensContainer = document.querySelector('.tokens-container');
- manager = new FilteredSearchManager({ page });
- manager.setup();
- };
-
- afterEach(() => {
- manager.cleanup();
- });
-
- describe('class constructor', () => {
- const isLocalStorageAvailable = 'isLocalStorageAvailable';
- let RecentSearchesStoreSpy;
-
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(isLocalStorageAvailable);
- spyOn(RecentSearchesRoot.prototype, 'render');
- RecentSearchesStoreSpy = spyOnDependency(FilteredSearchManager, 'RecentSearchesStore');
- });
-
- it('should instantiate RecentSearchesStore with isLocalStorageAvailable', () => {
- manager = new FilteredSearchManager({ page });
-
- expect(RecentSearchesService.isAvailable).toHaveBeenCalled();
- expect(RecentSearchesStoreSpy).toHaveBeenCalledWith({
- isLocalStorageAvailable,
- allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(),
- });
- });
- });
-
- describe('setup', () => {
- beforeEach(() => {
- manager = new FilteredSearchManager({ page });
- });
-
- it('should not instantiate Flash if an RecentSearchesServiceError is caught', () => {
- spyOn(RecentSearchesService.prototype, 'fetch').and.callFake(() =>
- Promise.reject(new RecentSearchesServiceError()),
- );
- spyOn(window, 'Flash');
-
- manager.setup();
-
- expect(window.Flash).not.toHaveBeenCalled();
- });
- });
-
- describe('searchState', () => {
- beforeEach(() => {
- spyOn(FilteredSearchManager.prototype, 'search').and.callFake(() => {});
- initializeManager();
- });
-
- it('should blur button', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- },
- };
- spyOn(e.currentTarget, 'blur').and.callThrough();
- manager.searchState(e);
-
- expect(e.currentTarget.blur).toHaveBeenCalled();
- });
-
- it('should not call search if there is no state', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- },
- };
-
- manager.searchState(e);
-
- expect(FilteredSearchManager.prototype.search).not.toHaveBeenCalled();
- });
-
- it('should call search when there is state', () => {
- const e = {
- preventDefault: () => {},
- currentTarget: {
- blur: () => {},
- dataset: {
- state: 'opened',
- },
- },
- };
-
- manager.searchState(e);
-
- expect(FilteredSearchManager.prototype.search).toHaveBeenCalledWith('opened');
- });
- });
-
- describe('search', () => {
- const defaultParams = '?scope=all&utf8=%E2%9C%93&state=opened';
-
- beforeEach(() => {
- initializeManager();
- });
-
- it('should search with a single word', done => {
- input.value = 'searchTerm';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&search=searchTerm`);
- done();
- });
-
- manager.search();
- });
-
- it('should search with multiple words', done => {
- input.value = 'awesome search terms';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
- done();
- });
-
- manager.search();
- });
-
- it('should search with special characters', done => {
- input.value = '~!@#$%^&*()_+{}:<>,.?/';
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(
- `${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`,
- );
- done();
- });
-
- manager.search();
- });
-
- it('removes duplicated tokens', done => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
- ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
- `);
-
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
- expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
- done();
- });
-
- manager.search();
- });
- });
-
- describe('handleInputPlaceholder', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('should render placeholder when there is no input', () => {
- expect(input.placeholder).toEqual(placeholder);
- });
-
- it('should not render placeholder when there is input', () => {
- input.value = 'test words';
-
- const event = new Event('input');
- input.dispatchEvent(event);
-
- expect(input.placeholder).toEqual('');
- });
-
- it('should not render placeholder when there are tokens and no input', () => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
-
- const event = new Event('input');
- input.dispatchEvent(event);
-
- expect(input.placeholder).toEqual('');
- });
- });
-
- describe('checkForBackspace', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- describe('tokens and no input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes last token', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- dispatchBackspaceEvent(input, 'keyup');
- dispatchBackspaceEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
-
- it('sets the input', () => {
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
- dispatchDeleteEvent(input, 'keyup');
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.getLastTokenPartial).toHaveBeenCalled();
- expect(input.value).toEqual('~bug');
- });
- });
-
- it('does not remove token or change input when there is existing input', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
-
- input.value = 'text';
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
-
- it('does not remove previous token on single backspace press', () => {
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- spyOn(FilteredSearchVisualTokens, 'getLastTokenPartial').and.callThrough();
-
- input.value = 't';
- dispatchDeleteEvent(input, 'keyup');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(FilteredSearchVisualTokens.getLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('t');
- });
- });
-
- describe('checkForAltOrCtrlBackspace', () => {
- beforeEach(() => {
- initializeManager();
- spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough();
- });
-
- describe('tokens and no input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes last token via alt-backspace', () => {
- dispatchAltBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
-
- it('removes last token via ctrl-backspace', () => {
- dispatchCtrlBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled();
- });
- });
-
- describe('tokens and input', () => {
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('does not remove token or change input via alt-backspace when there is existing input', () => {
- input = manager.filteredSearchInput;
- input.value = 'text';
- dispatchAltBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
-
- it('does not remove token or change input via ctrl-backspace when there is existing input', () => {
- input = manager.filteredSearchInput;
- input.value = 'text';
- dispatchCtrlBackspaceEvent(input, 'keydown');
-
- expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled();
- expect(input.value).toEqual('text');
- });
- });
- });
-
- describe('checkForMetaBackspace', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'),
- );
- });
-
- it('removes all tokens and input', () => {
- spyOn(FilteredSearchManager.prototype, 'clearSearch').and.callThrough();
- dispatchMetaBackspaceEvent(input, 'keydown');
-
- expect(manager.clearSearch).toHaveBeenCalled();
- expect(manager.filteredSearchInput.value).toEqual('');
- expect(DropdownUtils.getSearchQuery()).toEqual('');
- });
- });
-
- describe('removeToken', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('removes token even when it is already selected', () => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none', true),
- );
-
- tokensContainer.querySelector('.js-visual-token .remove-token').click();
-
- expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
- });
-
- describe('unselected token', () => {
- beforeEach(() => {
- spyOn(FilteredSearchManager.prototype, 'removeSelectedToken').and.callThrough();
-
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none'),
- );
- tokensContainer.querySelector('.js-visual-token .remove-token').click();
- });
-
- it('removes token when remove button is selected', () => {
- expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
- });
-
- it('calls removeSelectedToken', () => {
- expect(manager.removeSelectedToken).toHaveBeenCalled();
- });
- });
- });
-
- describe('removeSelectedTokenKeydown', () => {
- beforeEach(() => {
- initializeManager();
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
- FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', 'none', true),
- );
- });
-
- it('removes selected token when the backspace key is pressed', () => {
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('removes selected token when the delete key is pressed', () => {
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchDeleteEvent(document, 'keydown');
-
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('updates the input placeholder after removal', () => {
- manager.handleInputPlaceholder();
-
- expect(input.placeholder).toEqual('');
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(input.placeholder).not.toEqual('');
- expect(getVisualTokens().length).toEqual(0);
- });
-
- it('updates the clear button after removal', () => {
- manager.toggleClearSearchButton();
-
- const clearButton = document.querySelector('.clear-search');
-
- expect(clearButton.classList.contains('hidden')).toEqual(false);
- expect(getVisualTokens().length).toEqual(1);
-
- dispatchBackspaceEvent(document, 'keydown');
-
- expect(clearButton.classList.contains('hidden')).toEqual(true);
- expect(getVisualTokens().length).toEqual(0);
- });
- });
-
- describe('removeSelectedToken', () => {
- beforeEach(() => {
- spyOn(FilteredSearchVisualTokens, 'removeSelectedToken').and.callThrough();
- spyOn(FilteredSearchManager.prototype, 'handleInputPlaceholder').and.callThrough();
- spyOn(FilteredSearchManager.prototype, 'toggleClearSearchButton').and.callThrough();
- initializeManager();
- });
-
- it('calls FilteredSearchVisualTokens.removeSelectedToken', () => {
- manager.removeSelectedToken();
-
- expect(FilteredSearchVisualTokens.removeSelectedToken).toHaveBeenCalled();
- });
-
- it('calls handleInputPlaceholder', () => {
- manager.removeSelectedToken();
-
- expect(manager.handleInputPlaceholder).toHaveBeenCalled();
- });
-
- it('calls toggleClearSearchButton', () => {
- manager.removeSelectedToken();
-
- expect(manager.toggleClearSearchButton).toHaveBeenCalled();
- });
-
- it('calls update dropdown offset', () => {
- manager.removeSelectedToken();
-
- expect(manager.dropdownManager.updateDropdownOffset).toHaveBeenCalled();
- });
- });
-
- describe('Clearing search', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('Clicking the "x" clear button, clears the input', () => {
- const inputValue = 'label:=~bug';
- manager.filteredSearchInput.value = inputValue;
- manager.filteredSearchInput.dispatchEvent(new Event('input'));
-
- expect(DropdownUtils.getSearchQuery()).toEqual(inputValue);
-
- manager.clearSearchButton.click();
-
- expect(manager.filteredSearchInput.value).toEqual('');
- expect(DropdownUtils.getSearchQuery()).toEqual('');
- });
- });
-
- describe('toggleInputContainerFocus', () => {
- beforeEach(() => {
- initializeManager();
- });
-
- it('toggles on focus', () => {
- input.focus();
-
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
- true,
- );
- });
-
- it('toggles on blur', () => {
- input.blur();
-
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
- false,
- );
- });
- });
-
- describe('getAllParams', () => {
- beforeEach(() => {
- this.paramsArr = ['key=value', 'otherkey=othervalue'];
-
- initializeManager();
- });
-
- it('correctly modifies params when custom modifier is passed', () => {
- const modifedParams = manager.getAllParams.call(
- {
- modifyUrlParams: paramsArr => paramsArr.reverse(),
- },
- [].concat(this.paramsArr),
- );
-
- expect(modifedParams[0]).toBe(this.paramsArr[1]);
- });
-
- it('does not modify params when no custom modifier is passed', () => {
- const modifedParams = manager.getAllParams.call({}, this.paramsArr);
-
- expect(modifedParams[1]).toBe(this.paramsArr[1]);
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
deleted file mode 100644
index dec03e5ab93..00000000000
--- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchTokenizer from '~/filtered_search/filtered_search_tokenizer';
-
-describe('Filtered Search Tokenizer', () => {
- const allowedKeys = IssuableFilteredSearchTokenKeys.getKeys();
-
- describe('processTokens', () => {
- it('returns for input containing only search value', () => {
- const results = FilteredSearchTokenizer.processTokens('searchTerm', allowedKeys);
-
- expect(results.searchToken).toBe('searchTerm');
- expect(results.tokens.length).toBe(0);
- expect(results.lastToken).toBe(results.searchToken);
- });
-
- it('returns for input containing only tokens', () => {
- const results = FilteredSearchTokenizer.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);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('label');
- expect(results.tokens[1].value).toBe('"Very Important"');
- expect(results.tokens[1].symbol).toBe('~');
-
- expect(results.tokens[2].key).toBe('milestone');
- expect(results.tokens[2].value).toBe('v1.0');
- expect(results.tokens[2].symbol).toBe('%');
-
- expect(results.tokens[3].key).toBe('assignee');
- expect(results.tokens[3].value).toBe('none');
- expect(results.tokens[3].symbol).toBe('');
- });
-
- it('returns for input starting with search value and ending with tokens', () => {
- const results = FilteredSearchTokenizer.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);
- expect(results.tokens[0].key).toBe('milestone');
- expect(results.tokens[0].value).toBe('none');
- expect(results.tokens[0].symbol).toBe('');
- });
-
- it('returns for input starting with tokens and ending with search value', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'assignee:@user searchTerm',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm');
- expect(results.tokens.length).toBe(1);
- expect(results.tokens[0].key).toBe('assignee');
- expect(results.tokens[0].value).toBe('user');
- expect(results.tokens[0].symbol).toBe('@');
- expect(results.lastToken).toBe(results.searchToken);
- });
-
- it('returns for input containing search value wrapped between tokens', () => {
- const results = FilteredSearchTokenizer.processTokens(
- 'author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none',
- allowedKeys,
- );
-
- expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
- expect(results.tokens.length).toBe(3);
- expect(results.tokens[2]).toBe(results.lastToken);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('label');
- expect(results.tokens[1].value).toBe('"Won\'t fix"');
- expect(results.tokens[1].symbol).toBe('~');
-
- expect(results.tokens[2].key).toBe('milestone');
- expect(results.tokens[2].value).toBe('none');
- expect(results.tokens[2].symbol).toBe('');
- });
-
- it('returns for input containing search value in between tokens', () => {
- const results = FilteredSearchTokenizer.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);
-
- expect(results.tokens[0].key).toBe('author');
- expect(results.tokens[0].value).toBe('root');
- expect(results.tokens[0].symbol).toBe('@');
-
- expect(results.tokens[1].key).toBe('assignee');
- expect(results.tokens[1].value).toBe('none');
- expect(results.tokens[1].symbol).toBe('');
-
- expect(results.tokens[2].key).toBe('label');
- expect(results.tokens[2].value).toBe('Doing');
- expect(results.tokens[2].symbol).toBe('~');
- });
-
- it('returns search value for invalid tokens', () => {
- const results = 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 = 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');
- expect(results.tokens[0].symbol).toBe('');
- expect(results.lastToken).toBe('fake:token');
- expect(results.searchToken).toBe('fake:token');
- });
-
- it('returns search value for invalid symbols', () => {
- const results = FilteredSearchTokenizer.processTokens('std::includes', allowedKeys);
-
- expect(results.lastToken).toBe('std::includes');
- expect(results.searchToken).toBe('std::includes');
- });
-
- it('removes duplicated values', () => {
- const results = 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');
- expect(results.tokens[0].symbol).toBe('~');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js
deleted file mode 100644
index c7be900ba2c..00000000000
--- a/spec/javascripts/filtered_search/issues_filtered_search_token_keys_spec.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-
-describe('Issues Filtered Search Token Keys', () => {
- describe('get', () => {
- let tokenKeys;
-
- beforeEach(() => {
- tokenKeys = IssuableFilteredSearchTokenKeys.get();
- });
-
- it('should return tokenKeys', () => {
- expect(tokenKeys).not.toBeNull();
- });
-
- it('should return tokenKeys as an array', () => {
- expect(tokenKeys instanceof Array).toBe(true);
- });
-
- it('should always return the same array', () => {
- const tokenKeys2 = IssuableFilteredSearchTokenKeys.get();
-
- expect(tokenKeys).toEqual(tokenKeys2);
- });
-
- it('should return assignee as a string', () => {
- const assignee = tokenKeys.find(tokenKey => tokenKey.key === 'assignee');
-
- expect(assignee.type).toEqual('string');
- });
- });
-
- describe('getKeys', () => {
- it('should return keys', () => {
- const getKeys = IssuableFilteredSearchTokenKeys.getKeys();
- const keys = IssuableFilteredSearchTokenKeys.get().map(i => i.key);
-
- keys.forEach((key, i) => {
- expect(key).toEqual(getKeys[i]);
- });
- });
- });
-
- describe('getConditions', () => {
- let conditions;
-
- beforeEach(() => {
- conditions = IssuableFilteredSearchTokenKeys.getConditions();
- });
-
- it('should return conditions', () => {
- expect(conditions).not.toBeNull();
- });
-
- it('should return conditions as an array', () => {
- expect(conditions instanceof Array).toBe(true);
- });
- });
-
- describe('searchByKey', () => {
- it('should return null when key not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchByKey('notakey');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by key', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchByKey(tokenKeys[0].key);
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchBySymbol', () => {
- it('should return null when symbol not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchBySymbol('notasymbol');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by symbol', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchBySymbol(tokenKeys[0].symbol);
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchByKeyParam', () => {
- it('should return null when key param not found', () => {
- const tokenKey = IssuableFilteredSearchTokenKeys.searchByKeyParam('notakeyparam');
-
- expect(tokenKey).toBeNull();
- });
-
- it('should return tokenKey when found by key param', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.get();
- const result = IssuableFilteredSearchTokenKeys.searchByKeyParam(
- `${tokenKeys[0].key}_${tokenKeys[0].param}`,
- );
-
- expect(result).toEqual(tokenKeys[0]);
- });
-
- it('should return alternative tokenKey when found by key param', () => {
- const tokenKeys = IssuableFilteredSearchTokenKeys.getAlternatives();
- const result = IssuableFilteredSearchTokenKeys.searchByKeyParam(
- `${tokenKeys[0].key}_${tokenKeys[0].param}`,
- );
-
- expect(result).toEqual(tokenKeys[0]);
- });
- });
-
- describe('searchByConditionUrl', () => {
- it('should return null when condition url not found', () => {
- const condition = IssuableFilteredSearchTokenKeys.searchByConditionUrl(null);
-
- expect(condition).toBeNull();
- });
-
- it('should return condition when found by url', () => {
- const conditions = IssuableFilteredSearchTokenKeys.getConditions();
- const result = IssuableFilteredSearchTokenKeys.searchByConditionUrl(conditions[0].url);
-
- expect(result).toBe(conditions[0]);
- });
- });
-
- describe('searchByConditionKeyValue', () => {
- it('should return null when condition tokenKey and value not found', () => {
- const condition = IssuableFilteredSearchTokenKeys.searchByConditionKeyValue(null, null);
-
- expect(condition).toBeNull();
- });
-
- it('should return condition when found by tokenKey and value', () => {
- const conditions = IssuableFilteredSearchTokenKeys.getConditions();
- const result = IssuableFilteredSearchTokenKeys.searchByConditionKeyValue(
- conditions[0].tokenKey,
- conditions[0].operator,
- conditions[0].value,
- );
-
- expect(result).toEqual(conditions[0]);
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/recent_searches_root_spec.js b/spec/javascripts/filtered_search/recent_searches_root_spec.js
deleted file mode 100644
index 70dd4e9570d..00000000000
--- a/spec/javascripts/filtered_search/recent_searches_root_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-
-describe('RecentSearchesRoot', () => {
- describe('render', () => {
- let recentSearchesRoot;
- let data;
- let template;
- let VueSpy;
-
- beforeEach(() => {
- recentSearchesRoot = {
- store: {
- state: 'state',
- },
- };
-
- VueSpy = spyOnDependency(RecentSearchesRoot, 'Vue').and.callFake(options => {
- ({ data, template } = options);
- });
-
- RecentSearchesRoot.prototype.render.call(recentSearchesRoot);
- });
-
- it('should instantiate Vue', () => {
- expect(VueSpy).toHaveBeenCalled();
- expect(data()).toBe(recentSearchesRoot.store.state);
- expect(template).toContain(':is-local-storage-available="isLocalStorageAvailable"');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js b/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
deleted file mode 100644
index 188f83eca16..00000000000
--- a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-import AccessorUtilities from '~/lib/utils/accessor';
-
-describe('RecentSearchesService', () => {
- let service;
-
- beforeEach(() => {
- service = new RecentSearchesService();
- window.localStorage.removeItem(service.localStorageKey);
- });
-
- describe('fetch', () => {
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(true);
- });
-
- it('should default to empty array', done => {
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(items => {
- expect(items).toEqual([]);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should reject when unable to parse', done => {
- window.localStorage.setItem(service.localStorageKey, 'fail');
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(done.fail)
- .catch(error => {
- expect(error).toEqual(jasmine.any(SyntaxError));
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should reject when service is unavailable', done => {
- RecentSearchesService.isAvailable.and.returnValue(false);
-
- service
- .fetch()
- .then(done.fail)
- .catch(error => {
- expect(error).toEqual(jasmine.any(Error));
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should return items from localStorage', done => {
- window.localStorage.setItem(service.localStorageKey, '["foo", "bar"]');
- const fetchItemsPromise = service.fetch();
-
- fetchItemsPromise
- .then(items => {
- expect(items).toEqual(['foo', 'bar']);
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('if .isAvailable returns `false`', () => {
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(false);
-
- spyOn(window.localStorage, 'getItem');
- });
-
- it('should not call .getItem', done => {
- RecentSearchesService.prototype
- .fetch()
- .then(done.fail)
- .catch(err => {
- expect(err).toEqual(new RecentSearchesServiceError());
- expect(window.localStorage.getItem).not.toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('setRecentSearches', () => {
- beforeEach(() => {
- spyOn(RecentSearchesService, 'isAvailable').and.returnValue(true);
- });
-
- it('should save things in localStorage', () => {
- const items = ['foo', 'bar'];
- service.save(items);
- const newLocalStorageValue = window.localStorage.getItem(service.localStorageKey);
-
- expect(JSON.parse(newLocalStorageValue)).toEqual(items);
- });
- });
-
- describe('save', () => {
- beforeEach(() => {
- spyOn(window.localStorage, 'setItem');
- spyOn(RecentSearchesService, 'isAvailable');
- });
-
- describe('if .isAvailable returns `true`', () => {
- const searchesString = 'searchesString';
- const localStorageKey = 'localStorageKey';
- const recentSearchesService = {
- localStorageKey,
- };
-
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(true);
-
- spyOn(JSON, 'stringify').and.returnValue(searchesString);
- });
-
- it('should call .setItem', () => {
- RecentSearchesService.prototype.save.call(recentSearchesService);
-
- expect(window.localStorage.setItem).toHaveBeenCalledWith(localStorageKey, searchesString);
- });
- });
-
- describe('if .isAvailable returns `false`', () => {
- beforeEach(() => {
- RecentSearchesService.isAvailable.and.returnValue(false);
- });
-
- it('should not call .setItem', () => {
- RecentSearchesService.prototype.save();
-
- expect(window.localStorage.setItem).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('isAvailable', () => {
- let isAvailable;
-
- beforeEach(() => {
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.callThrough();
-
- isAvailable = RecentSearchesService.isAvailable();
- });
-
- it('should call .isLocalStorageAccessSafe', () => {
- expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
- });
-
- it('should return a boolean', () => {
- expect(typeof isAvailable).toBe('boolean');
- });
- });
-});
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
deleted file mode 100644
index 4469ade1874..00000000000
--- a/spec/javascripts/filtered_search/visual_token_value_spec.js
+++ /dev/null
@@ -1,389 +0,0 @@
-import { escape as esc } from 'lodash';
-import VisualTokenValue from '~/filtered_search/visual_token_value';
-import AjaxCache from '~/lib/utils/ajax_cache';
-import UsersCache from '~/lib/utils/users_cache';
-import DropdownUtils from '~/filtered_search//dropdown_utils';
-import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-
-describe('Filtered Search Visual Tokens', () => {
- const findElements = tokenElement => {
- const tokenNameElement = tokenElement.querySelector('.name');
- const tokenValueContainer = tokenElement.querySelector('.value-container');
- const tokenValueElement = tokenValueContainer.querySelector('.value');
- const tokenOperatorElement = tokenElement.querySelector('.operator');
- const tokenType = tokenNameElement.innerText.toLowerCase();
- const tokenValue = tokenValueElement.innerText;
- const tokenOperator = tokenOperatorElement.innerText;
- const subject = new VisualTokenValue(tokenValue, tokenType, tokenOperator);
- return { subject, tokenValueContainer, tokenValueElement };
- };
-
- let tokensContainer;
- let authorToken;
- let bugLabelToken;
-
- beforeEach(() => {
- setFixtures(`
- <ul class="tokens-container">
- ${FilteredSearchSpecHelper.createInputHTML()}
- </ul>
- `);
- tokensContainer = document.querySelector('.tokens-container');
-
- authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
- bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '=', '~bug');
- });
-
- describe('updateUserTokenAppearance', () => {
- let usersCacheSpy;
-
- beforeEach(() => {
- spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
- });
-
- it('ignores error if UsersCache throws', done => {
- spyOn(window, 'Flash');
- const dummyError = new Error('Earth rotated backwards');
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.reject(dummyError);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(window.Flash.calls.count()).toBe(0);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does nothing if user cannot be found', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(undefined);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText).toBe(tokenValue);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('replaces author token with avatar and display name', done => {
- const dummyUser = {
- name: 'Important Person',
- avatar_url: 'https://host.invalid/mypics/avatar.png',
- };
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- const avatar = tokenValueElement.querySelector('img.avatar');
-
- expect(avatar.src).toBe(dummyUser.avatar_url);
- expect(avatar.alt).toBe('');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('escapes user name when creating token', done => {
- const dummyUser = {
- name: '<script>',
- avatar_url: `${gl.TEST_HOST}/mypics/avatar.png`,
- };
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
- const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = username => {
- expect(`@${username}`).toBe(tokenValue);
- return Promise.resolve(dummyUser);
- };
-
- subject
- .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- tokenValueElement.querySelector('.avatar').remove();
-
- expect(tokenValueElement.innerHTML.trim()).toBe(esc(dummyUser.name));
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('updateLabelTokenColor', () => {
- const jsonFixtureName = 'labels/project_labels.json';
- const dummyEndpoint = '/dummy/endpoint';
-
- preloadFixtures(jsonFixtureName);
-
- let labelData;
-
- beforeAll(() => {
- labelData = getJSONFixture(jsonFixtureName);
- });
-
- const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '=',
- '~doesnotexist',
- );
- const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'label',
- '=',
- '~"some space"',
- );
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${bugLabelToken.outerHTML}
- ${missingLabelToken.outerHTML}
- ${spaceLabelToken.outerHTML}
- `);
-
- const filteredSearchInput = document.querySelector('.filtered-search');
- filteredSearchInput.dataset.runnerTagsEndpoint = `${dummyEndpoint}/admin/runners/tag_list`;
- filteredSearchInput.dataset.labelsEndpoint = `${dummyEndpoint}/-/labels`;
- filteredSearchInput.dataset.milestonesEndpoint = `${dummyEndpoint}/-/milestones`;
-
- AjaxCache.internalStorage = {};
- AjaxCache.internalStorage[`${filteredSearchInput.dataset.labelsEndpoint}.json`] = labelData;
- });
-
- const parseColor = color => {
- const dummyElement = document.createElement('div');
- dummyElement.style.color = color;
- return dummyElement.style.color;
- };
-
- const expectValueContainerStyle = (tokenValueContainer, label) => {
- expect(tokenValueContainer.getAttribute('style')).not.toBe(null);
- expect(tokenValueContainer.style.backgroundColor).toBe(parseColor(label.color));
- expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
- };
-
- const findLabel = tokenValue =>
- labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
-
- it('updates the color of a label token', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('updates the color of a label token with spaces', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expectValueContainerStyle(tokenValueContainer, matchingLabel);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('does not change color of a missing label', done => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
- const tokenValue = tokenValueElement.innerText;
- const matchingLabel = findLabel(tokenValue);
-
- expect(matchingLabel).toBe(undefined);
-
- subject
- .updateLabelTokenColor(tokenValueContainer, tokenValue)
- .then(() => {
- expect(tokenValueContainer.getAttribute('style')).toBe(null);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('setTokenStyle', () => {
- let originalTextColor;
-
- beforeEach(() => {
- originalTextColor = bugLabelToken.style.color;
- });
-
- it('should set backgroundColor', () => {
- const originalBackgroundColor = bugLabelToken.style.backgroundColor;
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'blue', 'white');
-
- expect(token.style.backgroundColor).toEqual('blue');
- expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
- });
-
- it('should set textColor', () => {
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'white', 'black');
-
- expect(token.style.color).toEqual('black');
- expect(token.style.color).not.toEqual(originalTextColor);
- });
-
- it('should add inverted class when textColor is #FFFFFF', () => {
- const token = VisualTokenValue.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
-
- expect(token.style.color).toEqual('rgb(255, 255, 255)');
- expect(token.style.color).not.toEqual(originalTextColor);
- expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
- });
- });
-
- describe('render', () => {
- const setupSpies = subject => {
- spyOn(subject, 'updateLabelTokenColor'); // eslint-disable-line jasmine/no-unsafe-spy
- const updateLabelTokenColorSpy = subject.updateLabelTokenColor;
-
- spyOn(subject, 'updateUserTokenAppearance'); // eslint-disable-line jasmine/no-unsafe-spy
- const updateUserTokenAppearanceSpy = subject.updateUserTokenAppearance;
-
- return { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy };
- };
-
- const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
- const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken(
- 'milestone',
- 'upcoming',
- );
-
- beforeEach(() => {
- tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
- ${authorToken.outerHTML}
- ${bugLabelToken.outerHTML}
- ${keywordToken.outerHTML}
- ${milestoneToken.outerHTML}
- `);
- });
-
- it('renders a author token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer, tokenValueElement];
-
- expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('renders a label token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
- const expectedArgs = [tokenValueContainer];
-
- expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('renders a milestone token value element', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(milestoneToken);
-
- const { updateLabelTokenColorSpy, updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `none` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'none';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `None` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'None';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update user token appearance for `any` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.tokenValue = 'any';
-
- const { updateUserTokenAppearanceSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `None` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'None';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `none` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'none';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
-
- it('does not update label token color for `any` filter', () => {
- const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
-
- subject.tokenValue = 'any';
-
- const { updateLabelTokenColorSpy } = setupSpies(subject);
- subject.render(tokenValueContainer, tokenValueElement);
-
- expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
- });
- });
-});