Commit 4c1dff36 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'himkp-jest-remaining' into 'master'

Migrate several specs to Jest

Closes #194291, #194272, and #27259

See merge request gitlab-org/gitlab!34016
parents 759bcf35 346ba81d
......@@ -95,7 +95,7 @@ export default class FilteredSearchVisualTokens {
const tokenType = tokenName.toLowerCase();
const tokenValueContainer = parentElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
tokenValueElement.innerText = tokenValue;
tokenValueElement.textContent = tokenValue;
const visualTokenValue = new VisualTokenValue(tokenValue, tokenType, tokenOperator);
......@@ -140,9 +140,9 @@ export default class FilteredSearchVisualTokens {
li.innerHTML = nameHTML + operatorHTML;
}
li.querySelector('.name').innerText = name;
li.querySelector('.name').textContent = name;
if (hasOperator) {
li.querySelector('.operator').innerText = operator;
li.querySelector('.operator').textContent = operator;
}
const tokensContainer = FilteredSearchContainer.container.querySelector('.tokens-container');
......@@ -162,8 +162,8 @@ export default class FilteredSearchVisualTokens {
lastVisualToken.innerHTML = FilteredSearchVisualTokens.createVisualTokenElementHTML({
hasOperator: Boolean(operator),
});
lastVisualToken.querySelector('.name').innerText = name;
lastVisualToken.querySelector('.operator').innerText = operator;
lastVisualToken.querySelector('.name').textContent = name;
lastVisualToken.querySelector('.operator').textContent = operator;
FilteredSearchVisualTokens.renderVisualTokenValue(lastVisualToken, name, value, operator);
}
}
......@@ -208,8 +208,8 @@ export default class FilteredSearchVisualTokens {
},
});
} else {
const previousTokenName = lastVisualToken.querySelector('.name').innerText;
const previousTokenOperator = lastVisualToken.querySelector('.operator').innerText;
const previousTokenName = lastVisualToken.querySelector('.name').textContent;
const previousTokenOperator = lastVisualToken.querySelector('.operator').textContent;
const tokensContainer = FilteredSearchContainer.container.querySelector('.tokens-container');
tokensContainer.removeChild(lastVisualToken);
......@@ -234,7 +234,7 @@ export default class FilteredSearchVisualTokens {
const { lastVisualToken } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (lastVisualToken && lastVisualToken.classList.contains('filtered-search-term')) {
lastVisualToken.querySelector('.name').innerText += ` ${searchTerm}`;
lastVisualToken.querySelector('.name').textContent += ` ${searchTerm}`;
} else {
FilteredSearchVisualTokens.addVisualTokenElement({
name: searchTerm,
......@@ -261,12 +261,12 @@ export default class FilteredSearchVisualTokens {
const value = lastVisualToken.querySelector('.value');
const name = lastVisualToken.querySelector('.name');
const valueText = value ? value.innerText : '';
const nameText = name ? name.innerText : '';
const valueText = value ? value.textContent : '';
const nameText = name ? name.textContent : '';
if (includeOperator) {
const operator = lastVisualToken.querySelector('.operator');
const operatorText = operator ? operator.innerText : '';
const operatorText = operator ? operator.textContent : '';
return valueText || operatorText || nameText;
}
......@@ -278,7 +278,7 @@ export default class FilteredSearchVisualTokens {
const operator = lastVisualToken && lastVisualToken.querySelector('.operator');
return operator?.innerText;
return operator?.textContent;
}
static removeLastTokenPartial() {
......@@ -346,8 +346,8 @@ export default class FilteredSearchVisualTokens {
if (token.classList.contains('filtered-search-token')) {
FilteredSearchVisualTokens.addFilterVisualToken(
nameElement.innerText,
operatorElement.innerText,
nameElement.textContent,
operatorElement.textContent,
null,
{
uppercaseTokenName: nameElement.classList.contains('text-uppercase'),
......@@ -359,13 +359,13 @@ export default class FilteredSearchVisualTokens {
if (!value) {
const valueElement = valueContainerElement.querySelector('.value');
value = valueElement.innerText;
value = valueElement.textContent;
}
}
// token is a search term
if (!value) {
value = nameElement.innerText;
value = nameElement.textContent;
}
input.value = value;
......
<script>
import '~/gl_dropdown';
import { GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import UsersSelect from '~/users_select';
......
......@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import AssigneeSelect from 'ee/boards/components/assignee_select.vue';
import { boardObj } from 'spec/boards/mock_data';
import { boardObj } from 'jest/boards/mock_data';
import axios from '~/lib/utils/axios_utils';
import boardsStore from '~/boards/stores/boards_store';
......@@ -51,7 +51,7 @@ describe('Assignee select component', () => {
},
}).$mount('.test-container');
setTimeout(done);
setImmediate(done);
});
describe('canEdit', () => {
......@@ -100,10 +100,12 @@ describe('Assignee select component', () => {
it('sets assignee', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
jest.runOnlyPendingTimers();
setImmediate(() => {
vm.$el.querySelectorAll('li a')[2].click();
setTimeout(() => {
setImmediate(() => {
expect(activeDropdownItem(0)).toEqual('second assignee');
expect(vm.board.assignee).toEqual(assignee2);
done();
......
......@@ -9,6 +9,7 @@ describe('BoardList Component', () => {
project: {
path: '/test',
},
real_path: '',
};
const componentProps = {
......
import Vue from 'vue';
import MockAdapater from 'axios-mock-adapter';
import MilestoneSelect from 'ee/boards/components/milestone_select.vue';
import { boardObj } from 'spec/boards/mock_data';
import { boardObj } from 'jest/boards/mock_data';
import axios from '~/lib/utils/axios_utils';
import IssuableContext from '~/issuable_context';
......@@ -45,7 +45,7 @@ describe('Milestone select component', () => {
},
}).$mount('.test-container');
setTimeout(done);
setImmediate(done);
});
describe('canEdit', () => {
......@@ -103,15 +103,18 @@ describe('Milestone select component', () => {
mock.restore();
});
it('sets Any milestone', done => {
it('sets Any milestone', async done => {
vm.board.milestone_id = 0;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
await vm.$nextTick();
jest.runOnlyPendingTimers();
setImmediate(() => {
vm.$el.querySelectorAll('li a')[0].click();
});
setTimeout(() => {
setImmediate(() => {
expect(activeDropdownItem(0)).toEqual('Any milestone');
expect(selectedText()).toEqual('Any milestone');
done();
......@@ -121,11 +124,13 @@ describe('Milestone select component', () => {
it('sets No milestone', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
jest.runOnlyPendingTimers();
setImmediate(() => {
vm.$el.querySelectorAll('li a')[1].click();
});
setTimeout(() => {
setImmediate(() => {
expect(activeDropdownItem(0)).toEqual('No milestone');
expect(selectedText()).toEqual('No milestone');
done();
......@@ -135,11 +140,13 @@ describe('Milestone select component', () => {
it('sets milestone', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
jest.runOnlyPendingTimers();
setImmediate(() => {
vm.$el.querySelectorAll('li a')[4].click();
});
setTimeout(() => {
setImmediate(() => {
expect(activeDropdownItem(0)).toEqual('first milestone');
expect(selectedText()).toEqual('first milestone');
expect(vm.board.milestone).toEqual(milestone);
......
......@@ -36,6 +36,11 @@ describe('AddIssuableForm', () => {
let wrapper;
afterEach(() => {
// Jest doesn't blur an item even if it is destroyed,
// so blur the input manually after each test
const input = findFormInput(wrapper);
if (input) input.blur();
wrapper.destroy();
});
......@@ -178,7 +183,7 @@ describe('AddIssuableForm', () => {
describe('when the form is submitted', () => {
it('emits an event with a "relates_to" link type when the "relates to" radio input selected', done => {
spyOn(wrapper.vm, '$emit');
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO;
wrapper.vm.onFormSubmit();
......@@ -193,7 +198,7 @@ describe('AddIssuableForm', () => {
});
it('emits an event with a "blocks" link type when the "blocks" radio input selected', done => {
spyOn(wrapper.vm, '$emit');
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS;
wrapper.vm.onFormSubmit();
......@@ -208,7 +213,7 @@ describe('AddIssuableForm', () => {
});
it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', done => {
spyOn(wrapper.vm, '$emit');
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY;
wrapper.vm.onFormSubmit();
......
......@@ -3,7 +3,8 @@ import { clone } from 'lodash';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Sidebar from '~/right_sidebar';
import timeoutPromise from './helpers/set_timeout_promise_helper';
import waitForPromises from './helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
describe('Issuable right sidebar collapsed todo toggle', () => {
const fixtureName = 'issues/open-issue.html';
......@@ -23,7 +24,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
mock = new MockAdapter(axios);
mock.onPost(`${gl.TEST_HOST}/frontend-fixtures/issues-project/todos`).reply(() => {
mock.onPost(`${TEST_HOST}/frontend-fixtures/issues-project/todos`).reply(() => {
const response = clone(todoData);
return [200, response];
......@@ -64,7 +65,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('toggle todo state', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
setImmediate(() => {
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
).not.toBeNull();
......@@ -82,7 +83,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('toggle todo state of expanded todo toggle', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
setImmediate(() => {
expect(
document.querySelector('.issuable-sidebar-header .js-issuable-todo').textContent.trim(),
).toBe('Mark as done');
......@@ -94,7 +95,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('toggles todo button tooltip', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
setImmediate(() => {
expect(
document
.querySelector('.js-issuable-todo.sidebar-collapsed-icon')
......@@ -108,7 +109,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('marks todo as done', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
timeoutPromise()
waitForPromises()
.then(() => {
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
......@@ -116,7 +117,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
})
.then(timeoutPromise)
.then(waitForPromises)
.then(() => {
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
......@@ -133,7 +134,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('updates aria-label to Mark as done', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
setImmediate(() => {
expect(
document
.querySelector('.js-issuable-todo.sidebar-collapsed-icon')
......@@ -147,7 +148,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
it('updates aria-label to add todo', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
timeoutPromise()
waitForPromises()
.then(() => {
expect(
document
......@@ -157,7 +158,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
})
.then(timeoutPromise)
.then(waitForPromises)
.then(() => {
expect(
document
......
import CommentTypeToggle from '~/comment_type_toggle';
import DropLab from '~/droplab/drop_lab';
import InputSetter from '~/droplab/plugins/input_setter';
describe('CommentTypeToggle', function() {
describe('class constructor', function() {
beforeEach(function() {
this.dropdownTrigger = {};
this.dropdownList = {};
this.noteTypeInput = {};
this.submitButton = {};
this.closeButton = {};
this.commentTypeToggle = new CommentTypeToggle({
dropdownTrigger: this.dropdownTrigger,
dropdownList: this.dropdownList,
noteTypeInput: this.noteTypeInput,
submitButton: this.submitButton,
closeButton: this.closeButton,
describe('CommentTypeToggle', () => {
const testContext = {};
describe('class constructor', () => {
beforeEach(() => {
testContext.dropdownTrigger = {};
testContext.dropdownList = {};
testContext.noteTypeInput = {};
testContext.submitButton = {};
testContext.closeButton = {};
testContext.commentTypeToggle = new CommentTypeToggle({
dropdownTrigger: testContext.dropdownTrigger,
dropdownList: testContext.dropdownList,
noteTypeInput: testContext.noteTypeInput,
submitButton: testContext.submitButton,
closeButton: testContext.closeButton,
});
});
it('should set .dropdownTrigger', function() {
expect(this.commentTypeToggle.dropdownTrigger).toBe(this.dropdownTrigger);
it('should set .dropdownTrigger', () => {
expect(testContext.commentTypeToggle.dropdownTrigger).toBe(testContext.dropdownTrigger);
});
it('should set .dropdownList', function() {
expect(this.commentTypeToggle.dropdownList).toBe(this.dropdownList);
it('should set .dropdownList', () => {
expect(testContext.commentTypeToggle.dropdownList).toBe(testContext.dropdownList);
});
it('should set .noteTypeInput', function() {
expect(this.commentTypeToggle.noteTypeInput).toBe(this.noteTypeInput);
it('should set .noteTypeInput', () => {
expect(testContext.commentTypeToggle.noteTypeInput).toBe(testContext.noteTypeInput);
});
it('should set .submitButton', function() {
expect(this.commentTypeToggle.submitButton).toBe(this.submitButton);
it('should set .submitButton', () => {
expect(testContext.commentTypeToggle.submitButton).toBe(testContext.submitButton);
});
it('should set .closeButton', function() {
expect(this.commentTypeToggle.closeButton).toBe(this.closeButton);
it('should set .closeButton', () => {
expect(testContext.commentTypeToggle.closeButton).toBe(testContext.closeButton);
});
it('should set .reopenButton', function() {
expect(this.commentTypeToggle.reopenButton).toBe(this.reopenButton);
it('should set .reopenButton', () => {
expect(testContext.commentTypeToggle.reopenButton).toBe(testContext.reopenButton);
});
});
describe('initDroplab', function() {
beforeEach(function() {
this.commentTypeToggle = {
describe('initDroplab', () => {
beforeEach(() => {
testContext.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
noteTypeInput: {},
......@@ -54,44 +57,38 @@ describe('CommentTypeToggle', function() {
closeButton: {},
setConfig: () => {},
};
this.config = {};
testContext.config = {};
this.droplab = jasmine.createSpyObj('droplab', ['init']);
jest.spyOn(DropLab.prototype, 'init').mockImplementation();
jest.spyOn(DropLab.prototype, 'constructor').mockImplementation();
this.droplabConstructor = spyOnDependency(CommentTypeToggle, 'DropLab').and.returnValue(
this.droplab,
);
spyOn(this.commentTypeToggle, 'setConfig').and.returnValue(this.config);
CommentTypeToggle.prototype.initDroplab.call(this.commentTypeToggle);
});
jest.spyOn(testContext.commentTypeToggle, 'setConfig').mockReturnValue(testContext.config);
it('should instantiate a DropLab instance', function() {
expect(this.droplabConstructor).toHaveBeenCalled();
CommentTypeToggle.prototype.initDroplab.call(testContext.commentTypeToggle);
});
it('should set .droplab', function() {
expect(this.commentTypeToggle.droplab).toBe(this.droplab);
it('should instantiate a DropLab instance and set .droplab', () => {
expect(testContext.commentTypeToggle.droplab instanceof DropLab).toBe(true);
});
it('should call .setConfig', function() {
expect(this.commentTypeToggle.setConfig).toHaveBeenCalled();
it('should call .setConfig', () => {
expect(testContext.commentTypeToggle.setConfig).toHaveBeenCalled();
});
it('should call DropLab.prototype.init', function() {
expect(this.droplab.init).toHaveBeenCalledWith(
this.commentTypeToggle.dropdownTrigger,
this.commentTypeToggle.dropdownList,
it('should call DropLab.prototype.init', () => {
expect(DropLab.prototype.init).toHaveBeenCalledWith(
testContext.commentTypeToggle.dropdownTrigger,
testContext.commentTypeToggle.dropdownList,
[InputSetter],
this.config,
testContext.config,
);
});
});
describe('setConfig', function() {
describe('if no .closeButton is provided', function() {
beforeEach(function() {
this.commentTypeToggle = {
describe('setConfig', () => {
describe('if no .closeButton is provided', () => {
beforeEach(() => {
testContext.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
noteTypeInput: {},
......@@ -99,26 +96,28 @@ describe('CommentTypeToggle', function() {
reopenButton: {},
};
this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle);
testContext.setConfig = CommentTypeToggle.prototype.setConfig.call(
testContext.commentTypeToggle,
);
});
it('should not add .closeButton related InputSetter config', function() {
expect(this.setConfig).toEqual({
it('should not add .closeButton related InputSetter config', () => {
expect(testContext.setConfig).toEqual({
InputSetter: [
{
input: this.commentTypeToggle.noteTypeInput,
input: testContext.commentTypeToggle.noteTypeInput,
valueAttribute: 'data-value',
},
{
input: this.commentTypeToggle.submitButton,
input: testContext.commentTypeToggle.submitButton,
valueAttribute: 'data-submit-text',
},
{
input: this.commentTypeToggle.reopenButton,
input: testContext.commentTypeToggle.reopenButton,
valueAttribute: 'data-reopen-text',
},
{
input: this.commentTypeToggle.reopenButton,
input: testContext.commentTypeToggle.reopenButton,
valueAttribute: 'data-reopen-text',
inputAttribute: 'data-alternative-text',
},
......@@ -127,9 +126,9 @@ describe('CommentTypeToggle', function() {
});
});
describe('if no .reopenButton is provided', function() {
beforeEach(function() {
this.commentTypeToggle = {
describe('if no .reopenButton is provided', () => {
beforeEach(() => {
testContext.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
noteTypeInput: {},
......@@ -137,26 +136,28 @@ describe('CommentTypeToggle', function() {
closeButton: {},
};
this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle);
testContext.setConfig = CommentTypeToggle.prototype.setConfig.call(
testContext.commentTypeToggle,
);
});
it('should not add .reopenButton related InputSetter config', function() {
expect(this.setConfig).toEqual({
it('should not add .reopenButton related InputSetter config', () => {
expect(testContext.setConfig).toEqual({
InputSetter: [
{
input: this.commentTypeToggle.noteTypeInput,
input: testContext.commentTypeToggle.noteTypeInput,
valueAttribute: 'data-value',
},
{
input: this.commentTypeToggle.submitButton,
input: testContext.commentTypeToggle.submitButton,
valueAttribute: 'data-submit-text',
},
{
input: this.commentTypeToggle.closeButton,
input: testContext.commentTypeToggle.closeButton,
valueAttribute: 'data-close-text',
},
{
input: this.commentTypeToggle.closeButton,
input: testContext.commentTypeToggle.closeButton,
valueAttribute: 'data-close-text',
inputAttribute: 'data-alternative-text',
},
......
import $ from 'jquery';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
describe('Filtered Search Dropdown Manager', () => {
let mock;
beforeEach(() => {
spyOn($, 'ajax');
mock = new MockAdapter(axios);
mock.onGet().reply(200);
});
describe('addWordToInput', () => {
......@@ -32,7 +36,7 @@ describe('Filtered Search Dropdown Manager', () => {
const token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('milestone');
expect(token.querySelector('.name').textContent).toBe('milestone');
expect(getInputValue()).toBe('');
});
......@@ -42,7 +46,7 @@ describe('Filtered Search Dropdown Manager', () => {
let token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('label');
expect(token.querySelector('.name').textContent).toBe('label');
expect(getInputValue()).toBe('');
FilteredSearchDropdownManager.addWordToInput({ tokenName: 'label', tokenOperator: '=' });
......@@ -50,8 +54,8 @@ describe('Filtered Search Dropdown Manager', () => {
token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('label');
expect(token.querySelector('.operator').innerText).toBe('=');
expect(token.querySelector('.name').textContent).toBe('label');
expect(token.querySelector('.operator').textContent).toBe('=');
expect(getInputValue()).toBe('');
FilteredSearchDropdownManager.addWordToInput({
......@@ -64,9 +68,9 @@ describe('Filtered Search Dropdown Manager', () => {
token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('label');
expect(token.querySelector('.operator').innerText).toBe('=');
expect(token.querySelector('.value').innerText).toBe('none');
expect(token.querySelector('.name').textContent).toBe('label');
expect(token.querySelector('.operator').textContent).toBe('=');
expect(token.querySelector('.value').textContent).toBe('none');
expect(getInputValue()).toBe('');
});
});
......@@ -79,7 +83,7 @@ describe('Filtered Search Dropdown Manager', () => {
const token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('author');
expect(token.querySelector('.name').textContent).toBe('author');
expect(getInputValue()).toBe('');
});
......@@ -97,9 +101,9 @@ describe('Filtered Search Dropdown Manager', () => {
const token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('author');
expect(token.querySelector('.operator').innerText).toBe('=');
expect(token.querySelector('.value').innerText).toBe('@root');
expect(token.querySelector('.name').textContent).toBe('author');
expect(token.querySelector('.operator').textContent).toBe('=');
expect(token.querySelector('.value').textContent).toBe('@root');
expect(getInputValue()).toBe('');
});
......@@ -116,9 +120,9 @@ describe('Filtered Search Dropdown Manager', () => {
const token = document.querySelector('.tokens-container .js-visual-token');
expect(token.classList.contains('filtered-search-token')).toEqual(true);
expect(token.querySelector('.name').innerText).toBe('label');
expect(token.querySelector('.operator').innerText).toBe('=');
expect(token.querySelector('.value').innerText).toBe('~\'"test me"\'');
expect(token.querySelector('.name').textContent).toBe('label');
expect(token.querySelector('.operator').textContent).toBe('=');
expect(token.querySelector('.value').textContent).toBe('~\'"test me"\'');
expect(getInputValue()).toBe('');
});
});
......
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
let mock;
const subject = FilteredSearchVisualTokens;
const findElements = tokenElement => {
......@@ -17,6 +20,9 @@ describe('Filtered Search Visual Tokens', () => {
let bugLabelToken;
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet().reply(200);
setFixtures(`
<ul class="tokens-container">
${FilteredSearchSpecHelper.createInputHTML()}
......@@ -248,15 +254,15 @@ describe('Filtered Search Visual Tokens', () => {
});
it('contains name div', () => {
expect(tokenElement.querySelector('.name')).toEqual(jasmine.anything());
expect(tokenElement.querySelector('.name')).toEqual(expect.anything());
});
it('contains value container div', () => {
expect(tokenElement.querySelector('.value-container')).toEqual(jasmine.anything());
expect(tokenElement.querySelector('.value-container')).toEqual(expect.anything());
});
it('contains value div', () => {
expect(tokenElement.querySelector('.value-container .value')).toEqual(jasmine.anything());
expect(tokenElement.querySelector('.value-container .value')).toEqual(expect.anything());
});
it('contains selectable class', () => {
......@@ -270,12 +276,12 @@ describe('Filtered Search Visual Tokens', () => {
describe('remove token', () => {
it('contains remove-token button', () => {
expect(tokenElement.querySelector('.value-container .remove-token')).toEqual(
jasmine.anything(),
expect.anything(),
);
});
it('contains fa-close icon', () => {
expect(tokenElement.querySelector('.remove-token .fa-close')).toEqual(jasmine.anything());
expect(tokenElement.querySelector('.remove-token .fa-close')).toEqual(expect.anything());
});
});
});
......@@ -453,7 +459,7 @@ describe('Filtered Search Visual Tokens', () => {
valueContainer.dataset.originalValue = originalValue;
const avatar = document.createElement('img');
const valueElement = valueContainer.querySelector('.value');
valueElement.insertAdjacentElement('afterbegin', avatar);
valueElement.appendChild(avatar);
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
authorToken.outerHTML,
);
......@@ -573,7 +579,7 @@ describe('Filtered Search Visual Tokens', () => {
it("tokenize's existing input", () => {
input.value = 'some text';
spyOn(subject, 'tokenizeInput').and.callThrough();
jest.spyOn(subject, 'tokenizeInput');
subject.editToken(token);
......@@ -635,8 +641,8 @@ describe('Filtered Search Visual Tokens', () => {
FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', 'none'),
);
spyOn(subject, 'tokenizeInput').and.callFake(() => {});
spyOn(subject, 'getLastVisualTokenBeforeInput').and.callThrough();
jest.spyOn(subject, 'tokenizeInput').mockImplementation(() => {});
jest.spyOn(subject, 'getLastVisualTokenBeforeInput');
subject.moveInputToTheRight();
......@@ -711,12 +717,16 @@ describe('Filtered Search Visual Tokens', () => {
it('renders a author token value element', () => {
const { tokenNameElement, tokenValueElement } = findElements(authorToken);
const tokenName = tokenNameElement.innerText;
const tokenName = tokenNameElement.textContent;
const tokenValue = 'new value';
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
expect(tokenValueElement.innerText).toBe(tokenValue);
jest.runOnlyPendingTimers();
setImmediate(() => {
expect(tokenValueElement.textContent).toBe(tokenValue);
});
});
});
});
......@@ -5,51 +5,56 @@ import '~/lib/utils/text_utility';
import '~/lib/utils/common_utils';
describe('GLForm', () => {
describe('when instantiated', function() {
const testContext = {};
describe('when instantiated', () => {
beforeEach(done => {
this.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
this.textarea = this.form.find('textarea');
spyOn($.prototype, 'off').and.returnValue(this.textarea);
spyOn($.prototype, 'on').and.returnValue(this.textarea);
spyOn($.prototype, 'css');
this.glForm = new GLForm(this.form, false);
setTimeout(() => {
$.prototype.off.calls.reset();
$.prototype.on.calls.reset();
$.prototype.css.calls.reset();
testContext.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
testContext.textarea = testContext.form.find('textarea');
jest.spyOn($.prototype, 'off').mockReturnValue(testContext.textarea);
jest.spyOn($.prototype, 'on').mockReturnValue(testContext.textarea);
jest.spyOn($.prototype, 'css').mockImplementation(() => {});
testContext.glForm = new GLForm(testContext.form, false);
setImmediate(() => {
$.prototype.off.mockClear();
$.prototype.on.mockClear();
$.prototype.css.mockClear();
done();
});
});
describe('setupAutosize', () => {
beforeEach(done => {
this.glForm.setupAutosize();
setTimeout(() => {
testContext.glForm.setupAutosize();
setImmediate(() => {
done();
});
});
it('should register an autosize event handler on the textarea', () => {
expect($.prototype.off).toHaveBeenCalledWith('autosize:resized');
expect($.prototype.on).toHaveBeenCalledWith('autosize:resized', jasmine.any(Function));
expect($.prototype.on).toHaveBeenCalledWith('autosize:resized', expect.any(Function));
});
it('should register a mouseup event handler on the textarea', () => {
expect($.prototype.off).toHaveBeenCalledWith('mouseup.autosize');
expect($.prototype.on).toHaveBeenCalledWith('mouseup.autosize', jasmine.any(Function));
expect($.prototype.on).toHaveBeenCalledWith('mouseup.autosize', expect.any(Function));
});
it('should set the resize css property to vertical', () => {
jest.runOnlyPendingTimers();
expect($.prototype.css).toHaveBeenCalledWith('resize', 'vertical');
});
});
describe('setHeightData', () => {
beforeEach(() => {
spyOn($.prototype, 'data');
spyOn($.prototype, 'outerHeight').and.returnValue(200);
this.glForm.setHeightData();
jest.spyOn($.prototype, 'data').mockImplementation(() => {});
jest.spyOn($.prototype, 'outerHeight').mockReturnValue(200);
testContext.glForm.setHeightData();
});
it('should set the height data attribute', () => {
......@@ -64,12 +69,12 @@ describe('GLForm', () => {
describe('destroyAutosize', () => {
describe('when called', () => {
beforeEach(() => {
spyOn($.prototype, 'data');
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn(window, 'outerHeight').and.returnValue(400);
spyOn(autosize, 'destroy');
jest.spyOn($.prototype, 'data').mockImplementation(() => {});
jest.spyOn($.prototype, 'outerHeight').mockReturnValue(200);
window.outerHeight = () => 400;
jest.spyOn(autosize, 'destroy').mockImplementation(() => {});
this.glForm.destroyAutosize();
testContext.glForm.destroyAutosize();
});
it('should call outerHeight', () => {
......@@ -81,7 +86,7 @@ describe('GLForm', () => {
});
it('should call autosize destroy', () => {
expect(autosize.destroy).toHaveBeenCalledWith(this.textarea);
expect(autosize.destroy).toHaveBeenCalledWith(testContext.textarea);
});
it('should set the data-height attribute', () => {
......@@ -98,11 +103,11 @@ describe('GLForm', () => {
});
it('should return undefined if the data-height equals the outerHeight', () => {
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn($.prototype, 'data').and.returnValue(200);
spyOn(autosize, 'destroy');
jest.spyOn($.prototype, 'outerHeight').mockReturnValue(200);
jest.spyOn($.prototype, 'data').mockReturnValue(200);
jest.spyOn(autosize, 'destroy').mockImplementation(() => {});
expect(this.glForm.destroyAutosize()).toBeUndefined();
expect(testContext.glForm.destroyAutosize()).toBeUndefined();
expect(autosize.destroy).not.toHaveBeenCalled();
});
});
......
......@@ -28,7 +28,7 @@ describe('Global search input dropdown', () => {
const groupName = 'Gitlab Org';
const removeBodyAttributes = function() {
const removeBodyAttributes = () => {
const $body = $('body');
$body.removeAttr('data-page');
......@@ -38,7 +38,7 @@ describe('Global search input dropdown', () => {
// Add required attributes to body before starting the test.
// section would be dashboard|group|project
const addBodyAttributes = function(section) {
const addBodyAttributes = section => {
if (section == null) {
section = 'dashboard';
}
......@@ -57,12 +57,12 @@ describe('Global search input dropdown', () => {
}
};
const disableProjectIssues = function() {
const disableProjectIssues = () => {
document.querySelector('.js-search-project-options').setAttribute('data-issues-disabled', true);
};
// Mock `gl` object in window for dashboard specific page. App code will need it.
const mockDashboardOptions = function() {
const mockDashboardOptions = () => {
window.gl || (window.gl = {});
return (window.gl.dashboardOptions = {
issuesPath: dashboardIssuesPath,
......@@ -71,7 +71,7 @@ describe('Global search input dropdown', () => {
};
// Mock `gl` object in window for project specific page. App code will need it.
const mockProjectOptions = function() {
const mockProjectOptions = () => {
window.gl || (window.gl = {});
return (window.gl.projectOptions = {
'gitlab-ce': {
......@@ -82,7 +82,7 @@ describe('Global search input dropdown', () => {
});
};
const mockGroupOptions = function() {
const mockGroupOptions = () => {
window.gl || (window.gl = {});
return (window.gl.groupOptions = {
'gitlab-org': {
......@@ -93,7 +93,7 @@ describe('Global search input dropdown', () => {
});
};
const assertLinks = function(list, issuesPath, mrsPath) {
const assertLinks = (list, issuesPath, mrsPath) => {
if (issuesPath) {
const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_username=${userName}"]`;
const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_username=${userName}"]`;
......@@ -113,7 +113,7 @@ describe('Global search input dropdown', () => {
};
preloadFixtures('static/global_search_input.html');
beforeEach(function() {
beforeEach(() => {
loadFixtures('static/global_search_input.html');
window.gon = {};
......@@ -123,13 +123,13 @@ describe('Global search input dropdown', () => {
return (widget = initGlobalSearchInput());
});
afterEach(function() {
afterEach(() => {
// Undo what we did to the shared <body>
removeBodyAttributes();
window.gon = {};
});
it('should show Dashboard specific dropdown menu', function() {
it('should show Dashboard specific dropdown menu', () => {
addBodyAttributes();
mockDashboardOptions();
widget.searchInput.triggerHandler('focus');
......@@ -137,7 +137,7 @@ describe('Global search input dropdown', () => {
return assertLinks(list, dashboardIssuesPath, dashboardMRsPath);
});
it('should show Group specific dropdown menu', function() {
it('should show Group specific dropdown menu', () => {
addBodyAttributes('group');
mockGroupOptions();
widget.searchInput.triggerHandler('focus');
......@@ -145,7 +145,7 @@ describe('Global search input dropdown', () => {
return assertLinks(list, groupIssuesPath, groupMRsPath);
});
it('should show Project specific dropdown menu', function() {
it('should show Project specific dropdown menu', () => {
addBodyAttributes('project');
mockProjectOptions();
widget.searchInput.triggerHandler('focus');
......@@ -153,7 +153,7 @@ describe('Global search input dropdown', () => {
return assertLinks(list, projectIssuesPath, projectMRsPath);
});
it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() {
it('should show only Project mergeRequest dropdown menu items when project issues are disabled', () => {
addBodyAttributes('project');
disableProjectIssues();
mockProjectOptions();
......@@ -162,7 +162,7 @@ describe('Global search input dropdown', () => {
assertLinks(list, null, projectMRsPath);
});
it('should not show category related menu if there is text in the input', function() {
it('should not show category related menu if there is text in the input', () => {
addBodyAttributes('project');
mockProjectOptions();
widget.searchInput.val('help');
......@@ -173,12 +173,12 @@ describe('Global search input dropdown', () => {
expect(list.find(link).length).toBe(0);
});
it('should not submit the search form when selecting an autocomplete row with the keyboard', function() {
it('should not submit the search form when selecting an autocomplete row with the keyboard', () => {
const ENTER = 13;
const DOWN = 40;
addBodyAttributes();
mockDashboardOptions(true);
const submitSpy = spyOnEvent('form', 'submit');
const submitSpy = jest.spyOn(document.querySelector('form'), 'submit');
widget.searchInput.triggerHandler('focus');
widget.wrap.trigger($.Event('keydown', { which: DOWN }));
const enterKeyEvent = $.Event('keydown', { which: ENTER });
......@@ -186,16 +186,16 @@ describe('Global search input dropdown', () => {
// This does not currently catch failing behavior. For security reasons,
// browsers will not trigger default behavior (form submit, in this
// example) on JavaScript-created keypresses.
expect(submitSpy).not.toHaveBeenTriggered();
expect(submitSpy).not.toHaveBeenCalled();
});
describe('disableDropdown', function() {
beforeEach(function() {
describe('disableDropdown', () => {
beforeEach(() => {
widget.enableDropdown();
});
it('should close the Dropdown', function() {
const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
it('should close the Dropdown', () => {
const toggleSpy = jest.spyOn(widget.dropdownToggle, 'dropdown');
widget.dropdown.addClass('show');
widget.disableDropdown();
......@@ -204,9 +204,9 @@ describe('Global search input dropdown', () => {
});
});
describe('enableDropdown', function() {
it('should open the Dropdown', function() {
const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
describe('enableDropdown', () => {
it('should open the Dropdown', () => {
const toggleSpy = jest.spyOn(widget.dropdownToggle, 'dropdown');
widget.enableDropdown();
expect(toggleSpy).toHaveBeenCalledWith('toggle');
......
......@@ -21,7 +21,9 @@ function testLabelClicks(labelOrder, done) {
.get(0)
.click();
setTimeout(() => {
jest.runOnlyPendingTimers();
setImmediate(() => {
const labelsInDropdown = $('.dropdown-content a');
expect(labelsInDropdown.length).toBe(10);
......@@ -38,11 +40,11 @@ function testLabelClicks(labelOrder, done) {
.get(0)
.click();
setTimeout(() => {
setImmediate(() => {
expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe(labelOrder);
done();
}, 0);
}, 0);
});
});
}
describe('Issue dropdown sidebar', () => {
......
......@@ -10,7 +10,7 @@ let $icon = null;
let $page = null;
let $labelsIcon = null;
const assertSidebarState = function(state) {
const assertSidebarState = state => {
const shouldBeExpanded = state === 'expanded';
const shouldBeCollapsed = state === 'collapsed';
expect($aside.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
......@@ -21,14 +21,13 @@ const assertSidebarState = function(state) {
expect($icon.hasClass('fa-angle-double-left')).toBe(shouldBeCollapsed);
};
describe('RightSidebar', function() {
describe('RightSidebar', () => {
describe('fixture tests', () => {
const fixtureName = 'issues/open-issue.html';
preloadFixtures(fixtureName);
loadJSONFixtures('todos/todos.json');
let mock;
beforeEach(function() {
beforeEach(() => {
loadFixtures(fixtureName);
mock = new MockAdapter(axios);
new Sidebar(); // eslint-disable-line no-new
......@@ -43,7 +42,7 @@ describe('RightSidebar', function() {
mock.restore();
});
it('should expand/collapse the sidebar when arrow is clicked', function() {
it('should expand/collapse the sidebar when arrow is clicked', () => {
assertSidebarState('expanded');
$toggle.click();
assertSidebarState('collapsed');
......@@ -51,28 +50,29 @@ describe('RightSidebar', function() {
assertSidebarState('expanded');
});
it('should float over the page and when sidebar icons clicked', function() {
it('should float over the page and when sidebar icons clicked', () => {
$labelsIcon.click();
assertSidebarState('expanded');
});
it('should collapse when the icon arrow clicked while it is floating on page', function() {
it('should collapse when the icon arrow clicked while it is floating on page', () => {
$labelsIcon.click();
assertSidebarState('expanded');
$toggle.click();
assertSidebarState('collapsed');
});
it('should broadcast todo:toggle event when add todo clicked', function(done) {
it('should broadcast todo:toggle event when add todo clicked', done => {
const todos = getJSONFixture('todos/todos.json');
mock.onPost(/(.*)\/todos$/).reply(200, todos);
const todoToggleSpy = spyOnEvent(document, 'todo:toggle');
const todoToggleSpy = jest.fn();
$(document).on('todo:toggle', todoToggleSpy);
$('.issuable-sidebar-header .js-issuable-todo').click();
setTimeout(() => {
expect(todoToggleSpy.calls.count()).toEqual(1);
setImmediate(() => {
expect(todoToggleSpy.mock.calls.length).toEqual(1);
done();
});
......
......@@ -14,8 +14,8 @@ describe('Shortcuts', () => {
beforeEach(() => {
loadFixtures(fixtureName);
spyOnEvent('.js-new-note-form .js-md-preview-button', 'focus');
spyOnEvent('.edit-note .js-md-preview-button', 'focus');
jest.spyOn(document.querySelector('.js-new-note-form .js-md-preview-button'), 'focus');
jest.spyOn(document.querySelector('.edit-note .js-md-preview-button'), 'focus');
new Shortcuts(); // eslint-disable-line no-new
});
......@@ -25,22 +25,22 @@ describe('Shortcuts', () => {
createEvent('KeyboardEvent', document.querySelector('.js-new-note-form .js-note-text')),
);
expect('focus').toHaveBeenTriggeredOn('.js-new-note-form .js-md-preview-button');
expect(
document.querySelector('.js-new-note-form .js-md-preview-button').focus,
).toHaveBeenCalled();
});
it('focues preview button inside edit comment form', done => {
it('focues preview button inside edit comment form', () => {
document.querySelector('.js-note-edit').click();
setTimeout(() => {
Shortcuts.toggleMarkdownPreview(
createEvent('KeyboardEvent', document.querySelector('.edit-note .js-note-text')),
);
expect('focus').not.toHaveBeenTriggeredOn('.js-new-note-form .js-md-preview-button');
expect('focus').toHaveBeenTriggeredOn('.edit-note .js-md-preview-button');
Shortcuts.toggleMarkdownPreview(
createEvent('KeyboardEvent', document.querySelector('.edit-note .js-note-text')),
);
done();
});
expect(
document.querySelector('.js-new-note-form .js-md-preview-button').focus,
).not.toHaveBeenCalled();
expect(document.querySelector('.edit-note .js-md-preview-button').focus).toHaveBeenCalled();
});
});
});
......@@ -26,10 +26,12 @@ describe('User Popovers', () => {
loadFixtures(fixtureTemplate);
const usersCacheSpy = () => Promise.resolve(dummyUser);
spyOn(UsersCache, 'retrieveById').and.callFake(userId => usersCacheSpy(userId));
jest.spyOn(UsersCache, 'retrieveById').mockImplementation(userId => usersCacheSpy(userId));
const userStatusCacheSpy = () => Promise.resolve(dummyUserStatus);
spyOn(UsersCache, 'retrieveStatusById').and.callFake(userId => userStatusCacheSpy(userId));
jest
.spyOn(UsersCache, 'retrieveStatusById')
.mockImplementation(userId => userStatusCacheSpy(userId));
popovers = initUserPopovers(document.querySelectorAll(selector));
});
......@@ -53,6 +55,8 @@ describe('User Popovers', () => {
let userLink;
beforeEach(() => {
UsersCache.retrieveById.mockReset();
userLink = document.querySelector(selector);
triggerEvent('mouseenter', userLink);
......@@ -68,7 +72,7 @@ describe('User Popovers', () => {
const [firstPopover] = popovers;
expect(firstPopover.$props.user).toEqual(
jasmine.objectContaining({
expect.objectContaining({
name,
userId,
username,
......
import $ from 'jquery';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Dropzone from 'dropzone';
import Mousetrap from 'mousetrap';
import ZenMode from '~/zen_mode';
import initNotes from '~/init_notes';
describe('ZenMode', () => {
let mock;
let zen;
let dropzoneForElementSpy;
const fixtureName = 'snippets/show.html';
......@@ -28,10 +31,13 @@ describe('ZenMode', () => {
}
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet().reply(200);
loadFixtures(fixtureName);
initNotes();
dropzoneForElementSpy = spyOn(Dropzone, 'forElement').and.callFake(() => ({
dropzoneForElementSpy = jest.spyOn(Dropzone, 'forElement').mockImplementation(() => ({
enable: () => true,
}));
zen = new ZenMode();
......@@ -49,20 +55,20 @@ describe('ZenMode', () => {
$('.div-dropzone').addClass('js-invalid-dropzone');
exitZen();
expect(dropzoneForElementSpy.calls.count()).toEqual(0);
expect(dropzoneForElementSpy.mock.calls.length).toEqual(0);
});
it('should call dropzone if element is dropzone valid', () => {
$('.div-dropzone').removeClass('js-invalid-dropzone');
exitZen();
expect(dropzoneForElementSpy.calls.count()).toEqual(2);
expect(dropzoneForElementSpy.mock.calls.length).toEqual(2);
});
});
describe('on enter', () => {
it('pauses Mousetrap', () => {
const mouseTrapPauseSpy = spyOn(Mousetrap, 'pause');
const mouseTrapPauseSpy = jest.spyOn(Mousetrap, 'pause');
enterZen();
expect(mouseTrapPauseSpy).toHaveBeenCalled();
......@@ -90,14 +96,14 @@ describe('ZenMode', () => {
beforeEach(enterZen);
it('unpauses Mousetrap', () => {
const mouseTrapUnpauseSpy = spyOn(Mousetrap, 'unpause');
const mouseTrapUnpauseSpy = jest.spyOn(Mousetrap, 'unpause');
exitZen();
expect(mouseTrapUnpauseSpy).toHaveBeenCalled();
});
it('restores the scroll position', () => {
spyOn(zen, 'scrollTo');
jest.spyOn(zen, 'scrollTo').mockImplementation(() => {});
exitZen();
expect(zen.scrollTo).toHaveBeenCalled();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment