|
|
|
@ -1,10 +1,22 @@
|
|
|
|
|
import AjaxCache from '~/lib/utils/ajax_cache';
|
|
|
|
|
import UsersCache from '~/lib/utils/users_cache';
|
|
|
|
|
|
|
|
|
|
import '~/filtered_search/filtered_search_visual_tokens';
|
|
|
|
|
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
|
|
|
|
|
|
|
|
|
|
describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
const subject = gl.FilteredSearchVisualTokens;
|
|
|
|
|
|
|
|
|
|
const findElements = (tokenElement) => {
|
|
|
|
|
const tokenNameElement = tokenElement.querySelector('.name');
|
|
|
|
|
const tokenValueContainer = tokenElement.querySelector('.value-container');
|
|
|
|
|
const tokenValueElement = tokenValueContainer.querySelector('.value');
|
|
|
|
|
return { tokenNameElement, tokenValueContainer, tokenValueElement };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let tokensContainer;
|
|
|
|
|
let authorToken;
|
|
|
|
|
let bugLabelToken;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
setFixtures(`
|
|
|
|
@ -13,12 +25,15 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
</ul>
|
|
|
|
|
`);
|
|
|
|
|
tokensContainer = document.querySelector('.tokens-container');
|
|
|
|
|
|
|
|
|
|
authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '@user');
|
|
|
|
|
bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~bug');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getLastVisualTokenBeforeInput', () => {
|
|
|
|
|
it('returns when there are no visual tokens', () => {
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken).toEqual(null);
|
|
|
|
|
expect(isLastVisualTokenValid).toEqual(true);
|
|
|
|
@ -27,11 +42,11 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
describe('input is the last item in tokensContainer', () => {
|
|
|
|
|
it('returns when there is one visual token', () => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
|
|
|
|
|
FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug'),
|
|
|
|
|
bugLabelToken.outerHTML,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
|
|
|
|
|
expect(isLastVisualTokenValid).toEqual(true);
|
|
|
|
@ -43,7 +58,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
|
|
|
|
|
expect(isLastVisualTokenValid).toEqual(false);
|
|
|
|
@ -51,13 +66,13 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
it('returns when there are multiple visual tokens', () => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '@root')}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
const items = document.querySelectorAll('.tokens-container .js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true);
|
|
|
|
@ -66,13 +81,13 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
it('returns when there are multiple visual tokens and an incomplete visual token', () => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')}
|
|
|
|
|
${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('assignee')}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
const items = document.querySelectorAll('.tokens-container .js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true);
|
|
|
|
@ -83,13 +98,13 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
describe('input is a middle item in tokensContainer', () => {
|
|
|
|
|
it('returns last token before input', () => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
${FilteredSearchSpecHelper.createInputHTML()}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '@root')}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
|
|
|
|
|
expect(isLastVisualTokenValid).toEqual(true);
|
|
|
|
@ -103,7 +118,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
const { lastVisualToken, isLastVisualTokenValid }
|
|
|
|
|
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
|
= subject.getLastVisualTokenBeforeInput();
|
|
|
|
|
|
|
|
|
|
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
|
|
|
|
|
expect(isLastVisualTokenValid).toEqual(false);
|
|
|
|
@ -114,7 +129,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
describe('unselectTokens', () => {
|
|
|
|
|
it('does nothing when there are no tokens', () => {
|
|
|
|
|
const beforeHTML = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.unselectTokens();
|
|
|
|
|
subject.unselectTokens();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.innerHTML).toEqual(beforeHTML);
|
|
|
|
|
});
|
|
|
|
@ -128,7 +143,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
const selected = tokensContainer.querySelector('.js-visual-token .selected');
|
|
|
|
|
expect(selected.classList.contains('selected')).toEqual(true);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.unselectTokens();
|
|
|
|
|
subject.unselectTokens();
|
|
|
|
|
|
|
|
|
|
expect(selected.classList.contains('selected')).toEqual(false);
|
|
|
|
|
});
|
|
|
|
@ -137,7 +152,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
describe('selectToken', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~awesome')}
|
|
|
|
|
`);
|
|
|
|
@ -147,7 +162,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
const firstTokenButton = tokensContainer.querySelector('.js-visual-token .selectable');
|
|
|
|
|
firstTokenButton.classList.add('selected');
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.selectToken(firstTokenButton);
|
|
|
|
|
subject.selectToken(firstTokenButton);
|
|
|
|
|
|
|
|
|
|
expect(firstTokenButton.classList.contains('selected')).toEqual(false);
|
|
|
|
|
});
|
|
|
|
@ -156,7 +171,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
it('adds selected class', () => {
|
|
|
|
|
const firstTokenButton = tokensContainer.querySelector('.js-visual-token .selectable');
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.selectToken(firstTokenButton);
|
|
|
|
|
subject.selectToken(firstTokenButton);
|
|
|
|
|
|
|
|
|
|
expect(firstTokenButton.classList.contains('selected')).toEqual(true);
|
|
|
|
|
});
|
|
|
|
@ -165,7 +180,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
const tokenButtons = tokensContainer.querySelectorAll('.js-visual-token .selectable');
|
|
|
|
|
tokenButtons[1].classList.add('selected');
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.selectToken(tokenButtons[0]);
|
|
|
|
|
subject.selectToken(tokenButtons[0]);
|
|
|
|
|
|
|
|
|
|
expect(tokenButtons[0].classList.contains('selected')).toEqual(true);
|
|
|
|
|
expect(tokenButtons[1].classList.contains('selected')).toEqual(false);
|
|
|
|
@ -181,7 +196,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.removeSelectedToken();
|
|
|
|
|
subject.removeSelectedToken();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
|
|
|
|
|
});
|
|
|
|
@ -193,7 +208,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .selectable')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.removeSelectedToken();
|
|
|
|
|
subject.removeSelectedToken();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .selectable')).toEqual(null);
|
|
|
|
|
});
|
|
|
|
@ -205,7 +220,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
setFixtures(`
|
|
|
|
|
<div class="test-area">
|
|
|
|
|
${gl.FilteredSearchVisualTokens.createVisualTokenElementHTML()}
|
|
|
|
|
${subject.createVisualTokenElementHTML()}
|
|
|
|
|
</div>
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
@ -245,7 +260,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
describe('addVisualTokenElement', () => {
|
|
|
|
|
it('renders search visual tokens', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addVisualTokenElement('search term', null, true);
|
|
|
|
|
subject.addVisualTokenElement('search term', null, true);
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-term')).toEqual(true);
|
|
|
|
@ -254,7 +269,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders filter visual token name', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addVisualTokenElement('milestone');
|
|
|
|
|
subject.addVisualTokenElement('milestone');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-token')).toEqual(true);
|
|
|
|
@ -263,7 +278,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders filter visual token name and value', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addVisualTokenElement('label', 'Frontend');
|
|
|
|
|
subject.addVisualTokenElement('label', 'Frontend');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-token')).toEqual(true);
|
|
|
|
@ -274,7 +289,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
it('inserts visual token before input', () => {
|
|
|
|
|
tokensContainer.appendChild(FilteredSearchSpecHelper.createFilterVisualToken('assignee', '@root'));
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.addVisualTokenElement('label', 'Frontend');
|
|
|
|
|
subject.addVisualTokenElement('label', 'Frontend');
|
|
|
|
|
const tokens = tokensContainer.querySelectorAll('.js-visual-token');
|
|
|
|
|
const labelToken = tokens[0];
|
|
|
|
|
const assigneeToken = tokens[1];
|
|
|
|
@ -296,7 +311,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const original = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
subject.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
|
|
|
|
|
expect(original).toEqual(tokensContainer.innerHTML);
|
|
|
|
|
});
|
|
|
|
@ -308,7 +323,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
const original = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
subject.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
|
|
|
|
|
expect(original).toEqual(tokensContainer.innerHTML);
|
|
|
|
|
});
|
|
|
|
@ -319,7 +334,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const original = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
subject.addValueToPreviousVisualTokenElement('value');
|
|
|
|
|
const updatedToken = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(updatedToken.querySelector('.name').innerText).toEqual('label');
|
|
|
|
@ -330,7 +345,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
describe('addFilterVisualToken', () => {
|
|
|
|
|
it('creates visual token with just tokenName', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('milestone');
|
|
|
|
|
subject.addFilterVisualToken('milestone');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-token')).toEqual(true);
|
|
|
|
@ -339,8 +354,8 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('creates visual token with just tokenValue', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('milestone');
|
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('%8.17');
|
|
|
|
|
subject.addFilterVisualToken('milestone');
|
|
|
|
|
subject.addFilterVisualToken('%8.17');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-token')).toEqual(true);
|
|
|
|
@ -349,7 +364,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('creates full visual token', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addFilterVisualToken('assignee', '@john');
|
|
|
|
|
subject.addFilterVisualToken('assignee', '@john');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-token')).toEqual(true);
|
|
|
|
@ -360,7 +375,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
describe('addSearchVisualToken', () => {
|
|
|
|
|
it('creates search visual token', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.addSearchVisualToken('search term');
|
|
|
|
|
subject.addSearchVisualToken('search term');
|
|
|
|
|
const token = tokensContainer.querySelector('.js-visual-token');
|
|
|
|
|
|
|
|
|
|
expect(token.classList.contains('filtered-search-term')).toEqual(true);
|
|
|
|
@ -374,7 +389,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search term')}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.addSearchVisualToken('append this');
|
|
|
|
|
subject.addSearchVisualToken('append this');
|
|
|
|
|
const token = tokensContainer.querySelector('.filtered-search-term');
|
|
|
|
|
|
|
|
|
|
expect(token.querySelector('.name').innerText).toEqual('search term append this');
|
|
|
|
@ -386,10 +401,26 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
it('should get last token value', () => {
|
|
|
|
|
const value = '~bug';
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
|
|
|
|
|
FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', value),
|
|
|
|
|
bugLabelToken.outerHTML,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial()).toEqual(value);
|
|
|
|
|
expect(subject.getLastTokenPartial()).toEqual(value);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should get last token original value if available', () => {
|
|
|
|
|
const originalValue = '@user';
|
|
|
|
|
const valueContainer = authorToken.querySelector('.value-container');
|
|
|
|
|
valueContainer.dataset.originalValue = originalValue;
|
|
|
|
|
const avatar = document.createElement('img');
|
|
|
|
|
const valueElement = valueContainer.querySelector('.value');
|
|
|
|
|
valueElement.insertAdjacentElement('afterbegin', avatar);
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
|
|
|
|
|
authorToken.outerHTML,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const lastTokenValue = subject.getLastTokenPartial();
|
|
|
|
|
|
|
|
|
|
expect(lastTokenValue).toEqual(originalValue);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should get last token name if there is no value', () => {
|
|
|
|
@ -398,11 +429,11 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
FilteredSearchSpecHelper.createNameFilterVisualTokenHTML(name),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial()).toEqual(name);
|
|
|
|
|
expect(subject.getLastTokenPartial()).toEqual(name);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return empty when there are no tokens', () => {
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.getLastTokenPartial()).toEqual('');
|
|
|
|
|
expect(subject.getLastTokenPartial()).toEqual('');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -414,7 +445,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .value')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
|
|
|
|
subject.removeLastTokenPartial();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .value')).toEqual(null);
|
|
|
|
|
});
|
|
|
|
@ -426,14 +457,14 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .name')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
|
|
|
|
subject.removeLastTokenPartial();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.js-visual-token .name')).toEqual(null);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should not remove anything when there are no tokens', () => {
|
|
|
|
|
const html = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
|
|
|
|
subject.removeLastTokenPartial();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.innerHTML).toEqual(html);
|
|
|
|
|
});
|
|
|
|
@ -442,7 +473,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
describe('tokenizeInput', () => {
|
|
|
|
|
it('does not do anything if there is no input', () => {
|
|
|
|
|
const original = tokensContainer.innerHTML;
|
|
|
|
|
gl.FilteredSearchVisualTokens.tokenizeInput();
|
|
|
|
|
subject.tokenizeInput();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.innerHTML).toEqual(original);
|
|
|
|
|
});
|
|
|
|
@ -454,7 +485,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
const input = document.querySelector('.filtered-search');
|
|
|
|
|
input.value = 'some value';
|
|
|
|
|
gl.FilteredSearchVisualTokens.tokenizeInput();
|
|
|
|
|
subject.tokenizeInput();
|
|
|
|
|
|
|
|
|
|
const newToken = tokensContainer.querySelector('.filtered-search-term');
|
|
|
|
|
|
|
|
|
@ -470,7 +501,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
const input = document.querySelector('.filtered-search');
|
|
|
|
|
input.value = '@john';
|
|
|
|
|
gl.FilteredSearchVisualTokens.tokenizeInput();
|
|
|
|
|
subject.tokenizeInput();
|
|
|
|
|
|
|
|
|
|
const updatedToken = tokensContainer.querySelector('.filtered-search-token');
|
|
|
|
|
|
|
|
|
@ -497,29 +528,39 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
|
|
|
|
|
it('tokenize\'s existing input', () => {
|
|
|
|
|
input.value = 'some text';
|
|
|
|
|
spyOn(gl.FilteredSearchVisualTokens, 'tokenizeInput').and.callThrough();
|
|
|
|
|
spyOn(subject, 'tokenizeInput').and.callThrough();
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.tokenizeInput).toHaveBeenCalled();
|
|
|
|
|
expect(subject.tokenizeInput).toHaveBeenCalled();
|
|
|
|
|
expect(input.value).not.toEqual('some text');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('moves input to the token position', () => {
|
|
|
|
|
expect(tokensContainer.children[3].querySelector('.filtered-search')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.children[1].querySelector('.filtered-search')).not.toEqual(null);
|
|
|
|
|
expect(tokensContainer.children[3].querySelector('.filtered-search')).toEqual(null);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('input contains the visual token value', () => {
|
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(input.value).toEqual('none');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('input contains the original value if present', () => {
|
|
|
|
|
const originalValue = '@user';
|
|
|
|
|
const valueContainer = token.querySelector('.value-container');
|
|
|
|
|
valueContainer.dataset.originalValue = originalValue;
|
|
|
|
|
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(input.value).toEqual(originalValue);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('selected token is a search term token', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
token = document.querySelector('.filtered-search-term');
|
|
|
|
@ -528,7 +569,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
it('token is removed', () => {
|
|
|
|
|
expect(tokensContainer.querySelector('.filtered-search-term')).not.toEqual(null);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.querySelector('.filtered-search-term')).toEqual(null);
|
|
|
|
|
});
|
|
|
|
@ -536,7 +577,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
it('input has the same value as removed token', () => {
|
|
|
|
|
expect(input.value).toEqual('');
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.editToken(token);
|
|
|
|
|
subject.editToken(token);
|
|
|
|
|
|
|
|
|
|
expect(input.value).toEqual('search');
|
|
|
|
|
});
|
|
|
|
@ -549,25 +590,25 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', 'none'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
spyOn(gl.FilteredSearchVisualTokens, 'tokenizeInput').and.callFake(() => {});
|
|
|
|
|
spyOn(gl.FilteredSearchVisualTokens, 'getLastVisualTokenBeforeInput').and.callThrough();
|
|
|
|
|
spyOn(subject, 'tokenizeInput').and.callFake(() => {});
|
|
|
|
|
spyOn(subject, 'getLastVisualTokenBeforeInput').and.callThrough();
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
|
subject.moveInputToTheRight();
|
|
|
|
|
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.tokenizeInput).toHaveBeenCalled();
|
|
|
|
|
expect(gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput).not.toHaveBeenCalled();
|
|
|
|
|
expect(subject.tokenizeInput).toHaveBeenCalled();
|
|
|
|
|
expect(subject.getLastVisualTokenBeforeInput).not.toHaveBeenCalled();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('tokenize\'s input', () => {
|
|
|
|
|
tokensContainer.innerHTML = `
|
|
|
|
|
${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('label')}
|
|
|
|
|
${FilteredSearchSpecHelper.createInputHTML()}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
document.querySelector('.filtered-search').value = 'none';
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
|
subject.moveInputToTheRight();
|
|
|
|
|
const value = tokensContainer.querySelector('.js-visual-token .value');
|
|
|
|
|
|
|
|
|
|
expect(value.innerText).toEqual('none');
|
|
|
|
@ -577,12 +618,12 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
tokensContainer.innerHTML = `
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', 'none')}
|
|
|
|
|
${FilteredSearchSpecHelper.createInputHTML()}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
document.querySelector('.filtered-search').value = 'test';
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
|
subject.moveInputToTheRight();
|
|
|
|
|
const searchValue = tokensContainer.querySelector('.filtered-search-term .name');
|
|
|
|
|
|
|
|
|
|
expect(searchValue.innerText).toEqual('test');
|
|
|
|
@ -592,10 +633,10 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
tokensContainer.innerHTML = `
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', 'none')}
|
|
|
|
|
${FilteredSearchSpecHelper.createInputHTML()}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
|
subject.moveInputToTheRight();
|
|
|
|
|
|
|
|
|
|
expect(tokensContainer.children[2].querySelector('.filtered-search')).not.toEqual(null);
|
|
|
|
|
});
|
|
|
|
@ -607,7 +648,7 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
${FilteredSearchSpecHelper.createInputHTML('', '~bug')}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.moveInputToTheRight();
|
|
|
|
|
subject.moveInputToTheRight();
|
|
|
|
|
|
|
|
|
|
const token = tokensContainer.children[1];
|
|
|
|
|
expect(token.querySelector('.value').innerText).toEqual('~bug');
|
|
|
|
@ -615,42 +656,144 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('renderVisualTokenValue', () => {
|
|
|
|
|
let searchTokens;
|
|
|
|
|
const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
|
|
|
|
|
const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken('milestone', 'upcoming');
|
|
|
|
|
|
|
|
|
|
let updateLabelTokenColorSpy;
|
|
|
|
|
let updateUserTokenAppearanceSpy;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', 'none')}
|
|
|
|
|
${FilteredSearchSpecHelper.createSearchVisualTokenHTML('search')}
|
|
|
|
|
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', 'upcoming')}
|
|
|
|
|
${authorToken.outerHTML}
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
|
${keywordToken.outerHTML}
|
|
|
|
|
${milestoneToken.outerHTML}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
searchTokens = document.querySelectorAll('.filtered-search-token');
|
|
|
|
|
spyOn(subject, 'updateLabelTokenColor');
|
|
|
|
|
updateLabelTokenColorSpy = subject.updateLabelTokenColor;
|
|
|
|
|
|
|
|
|
|
spyOn(subject, 'updateUserTokenAppearance');
|
|
|
|
|
updateUserTokenAppearanceSpy = subject.updateUserTokenAppearance;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders a token value element', () => {
|
|
|
|
|
spyOn(gl.FilteredSearchVisualTokens, 'updateLabelTokenColor');
|
|
|
|
|
const updateLabelTokenColorSpy = gl.FilteredSearchVisualTokens.updateLabelTokenColor;
|
|
|
|
|
it('renders a author token value element', () => {
|
|
|
|
|
const { tokenNameElement, tokenValueContainer, tokenValueElement } =
|
|
|
|
|
findElements(authorToken);
|
|
|
|
|
const tokenName = tokenNameElement.innerText;
|
|
|
|
|
const tokenValue = 'new value';
|
|
|
|
|
|
|
|
|
|
expect(searchTokens.length).toBe(2);
|
|
|
|
|
Array.prototype.forEach.call(searchTokens, (token) => {
|
|
|
|
|
updateLabelTokenColorSpy.calls.reset();
|
|
|
|
|
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
|
|
|
|
|
|
|
|
|
|
const tokenName = token.querySelector('.name').innerText;
|
|
|
|
|
const tokenValue = 'new value';
|
|
|
|
|
gl.FilteredSearchVisualTokens.renderVisualTokenValue(token, tokenName, tokenValue);
|
|
|
|
|
expect(tokenValueElement.innerText).toBe(tokenValue);
|
|
|
|
|
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
|
|
|
|
|
const expectedArgs = [tokenValueContainer, tokenValueElement, tokenValue];
|
|
|
|
|
expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const tokenValueElement = token.querySelector('.value');
|
|
|
|
|
it('renders a label token value element', () => {
|
|
|
|
|
const { tokenNameElement, tokenValueContainer, tokenValueElement } =
|
|
|
|
|
findElements(bugLabelToken);
|
|
|
|
|
const tokenName = tokenNameElement.innerText;
|
|
|
|
|
const tokenValue = 'new value';
|
|
|
|
|
|
|
|
|
|
subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
|
|
|
|
|
|
|
|
|
|
expect(tokenValueElement.innerText).toBe(tokenValue);
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
|
|
|
|
|
const expectedArgs = [tokenValueContainer, tokenValue];
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
|
|
|
|
|
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders a milestone token value element', () => {
|
|
|
|
|
const { tokenNameElement, tokenValueElement } = findElements(milestoneToken);
|
|
|
|
|
const tokenName = tokenNameElement.innerText;
|
|
|
|
|
const tokenValue = 'new value';
|
|
|
|
|
|
|
|
|
|
subject.renderVisualTokenValue(milestoneToken, tokenName, tokenValue);
|
|
|
|
|
|
|
|
|
|
expect(tokenValueElement.innerText).toBe(tokenValue);
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
|
|
|
|
|
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateUserTokenAppearance', () => {
|
|
|
|
|
let usersCacheSpy;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignores special value "none"', (done) => {
|
|
|
|
|
usersCacheSpy = (username) => {
|
|
|
|
|
expect(username).toBe('none');
|
|
|
|
|
done.fail('Should not resolve "none"!');
|
|
|
|
|
};
|
|
|
|
|
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
|
|
|
|
|
|
|
|
|
|
subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, 'none')
|
|
|
|
|
.then(done)
|
|
|
|
|
.catch(done.fail);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignores error if UsersCache throws', (done) => {
|
|
|
|
|
spyOn(window, 'Flash');
|
|
|
|
|
const dummyError = new Error('Earth rotated backwards');
|
|
|
|
|
const { 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 { 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);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (tokenName.toLowerCase() === 'label') {
|
|
|
|
|
const tokenValueContainer = token.querySelector('.value-container');
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
|
|
|
|
|
const expectedArgs = [tokenValueContainer, tokenValue];
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
|
|
|
|
|
} else {
|
|
|
|
|
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
it('replaces author token with avatar and display name', (done) => {
|
|
|
|
|
const dummyUser = {
|
|
|
|
|
name: 'Important Person',
|
|
|
|
|
avatar_url: 'https://host.invalid/mypics/avatar.png',
|
|
|
|
|
};
|
|
|
|
|
const { 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);
|
|
|
|
|
})
|
|
|
|
|
.then(done)
|
|
|
|
|
.catch(done.fail);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -659,21 +802,16 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
const dummyEndpoint = '/dummy/endpoint';
|
|
|
|
|
|
|
|
|
|
preloadFixtures(jsonFixtureName);
|
|
|
|
|
const labelData = getJSONFixture(jsonFixtureName);
|
|
|
|
|
const findLabel = tokenValue => labelData.find(
|
|
|
|
|
label => tokenValue === `~${gl.DropdownUtils.getEscapedText(label.title)}`,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const bugLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~bug');
|
|
|
|
|
let labelData;
|
|
|
|
|
|
|
|
|
|
beforeAll(() => {
|
|
|
|
|
labelData = getJSONFixture(jsonFixtureName);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~doesnotexist');
|
|
|
|
|
const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~"some space"');
|
|
|
|
|
|
|
|
|
|
const parseColor = (color) => {
|
|
|
|
|
const dummyElement = document.createElement('div');
|
|
|
|
|
dummyElement.style.color = color;
|
|
|
|
|
return dummyElement.style.color;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
|
|
|
|
|
${bugLabelToken.outerHTML}
|
|
|
|
@ -688,28 +826,60 @@ describe('Filtered Search Visual Tokens', () => {
|
|
|
|
|
AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const testCase = (token, done) => {
|
|
|
|
|
const tokenValueContainer = token.querySelector('.value-container');
|
|
|
|
|
const tokenValue = token.querySelector('.value').innerText;
|
|
|
|
|
const label = findLabel(tokenValue);
|
|
|
|
|
|
|
|
|
|
gl.FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue)
|
|
|
|
|
.then(() => {
|
|
|
|
|
if (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));
|
|
|
|
|
} else {
|
|
|
|
|
expect(token).toBe(missingLabelToken);
|
|
|
|
|
expect(tokenValueContainer.getAttribute('style')).toBe(null);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.then(done)
|
|
|
|
|
.catch(fail);
|
|
|
|
|
const parseColor = (color) => {
|
|
|
|
|
const dummyElement = document.createElement('div');
|
|
|
|
|
dummyElement.style.color = color;
|
|
|
|
|
return dummyElement.style.color;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
it('updates the color of a label token', done => testCase(bugLabelToken, done));
|
|
|
|
|
it('updates the color of a label token with spaces', done => testCase(spaceLabelToken, done));
|
|
|
|
|
it('does not change color of a missing label', done => testCase(missingLabelToken, done));
|
|
|
|
|
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 === `~${gl.DropdownUtils.getEscapedText(label.title)}`,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
it('updates the color of a label token', (done) => {
|
|
|
|
|
const { 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 { 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 { 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);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|