Commit 3f98bc16 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'vs-migrate-sidebar-to-jest' into 'master'

Migrate ee/spec/javascripts/sidebar/ to Jest

Closes #194307

See merge request gitlab-org/gitlab!26959
parents ee1d9370 3a2cfa31
...@@ -6,7 +6,7 @@ import { ...@@ -6,7 +6,7 @@ import {
mockSidebarStore, mockSidebarStore,
mockEpic1, mockEpic1,
mockIssue, mockIssue,
} from '../../vue_shared/components/sidebar/mock_data'; } from 'ee_jest/vue_shared/components/sidebar/mock_data';
describe('SidebarItemEpicsSelect', () => { describe('SidebarItemEpicsSelect', () => {
let wrapper; let wrapper;
...@@ -32,50 +32,46 @@ describe('SidebarItemEpicsSelect', () => { ...@@ -32,50 +32,46 @@ describe('SidebarItemEpicsSelect', () => {
describe('methods', () => { describe('methods', () => {
describe('getInitialEpicLoading', () => { describe('getInitialEpicLoading', () => {
it('should return `false` when `initialEpic` prop is provided', done => { it('should return `false` when `initialEpic` prop is provided', () => {
wrapper.setProps({ wrapper.setProps({
initialEpic: mockEpic1, initialEpic: mockEpic1,
}); });
wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getInitialEpicLoading()).toBe(false); expect(wrapper.vm.getInitialEpicLoading()).toBe(false);
done();
}); });
}); });
it('should return value of `sidebarStore.isFetching.epic` when `initialEpic` prop is null and `isFetching` is available', done => { it('should return value of `sidebarStore.isFetching.epic` when `initialEpic` prop is null and `isFetching` is available', () => {
wrapper.setProps({ wrapper.setProps({
sidebarStore: { isFetching: { epic: true } }, sidebarStore: { isFetching: { epic: true } },
}); });
wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getInitialEpicLoading()).toBe(true); expect(wrapper.vm.getInitialEpicLoading()).toBe(true);
done();
}); });
}); });
it('should return `false` when both `initialEpic` and `sidebarStore.isFetching` are unavailable', done => { it('should return `false` when both `initialEpic` and `sidebarStore.isFetching` are unavailable', () => {
wrapper.setProps({ wrapper.setProps({
initialEpic: null, initialEpic: null,
sidebarStore: { isFetching: null }, sidebarStore: { isFetching: null },
}); });
wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getInitialEpicLoading()).toBe(false); expect(wrapper.vm.getInitialEpicLoading()).toBe(false);
done();
}); });
}); });
}); });
describe('getEpic', () => { describe('getEpic', () => {
it('should return value of `initialEpic` as it is when it is available', done => { it('should return value of `initialEpic` as it is when it is available', () => {
wrapper.setProps({ wrapper.setProps({
initialEpic: mockEpic1, initialEpic: mockEpic1,
}); });
wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getEpic()).toBe(mockEpic1); expect(wrapper.vm.getEpic()).toBe(mockEpic1);
done();
}); });
}); });
...@@ -83,21 +79,19 @@ describe('SidebarItemEpicsSelect', () => { ...@@ -83,21 +79,19 @@ describe('SidebarItemEpicsSelect', () => {
expect(wrapper.vm.getEpic()).toBe(mockEpic1); expect(wrapper.vm.getEpic()).toBe(mockEpic1);
}); });
it('should return No Epic object as it is when both `initialEpic` & `sidebarStore.epic` are unavailable', done => { it('should return No Epic object as it is when both `initialEpic` & `sidebarStore.epic` are unavailable', () => {
wrapper.setProps({ wrapper.setProps({
initialEpic: null, initialEpic: null,
sidebarStore: { epic: null }, sidebarStore: { epic: null },
}); });
wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getEpic()).toEqual( expect(wrapper.vm.getEpic()).toEqual(
expect.objectContaining({ expect.objectContaining({
id: 0, id: 0,
title: 'none', title: 'none',
}), }),
); );
done();
}); });
}); });
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import { escape } from 'underscore'; import { escape } from 'underscore';
import ancestorsTree from 'ee/sidebar/components/ancestors_tree/ancestors_tree.vue'; import ancestorsTree from 'ee/sidebar/components/ancestors_tree/ancestors_tree.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
describe('AncestorsTreeContainer', () => { describe('AncestorsTreeContainer', () => {
let vm; let vm;
...@@ -29,50 +29,42 @@ describe('AncestorsTreeContainer', () => { ...@@ -29,50 +29,42 @@ describe('AncestorsTreeContainer', () => {
); );
}); });
it('does not render timeline when fetching', done => { it('does not render timeline when fetching', () => {
vm.$props.isFetching = true; vm.$props.isFetching = true;
vm.$nextTick()
.then(() => { return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('.vertical-timeline')).toBeNull(); expect(vm.$el.querySelector('.vertical-timeline')).toBeNull();
expect(vm.$el.querySelector('.value')).toBeNull(); expect(vm.$el.querySelector('.value')).toBeNull();
}) });
.then(done)
.catch(done.fail);
}); });
it('render `None` when ancestors is an empty array', done => { it('render `None` when ancestors is an empty array', () => {
vm.$props.ancestors = []; vm.$props.ancestors = [];
vm.$nextTick()
.then(() => { return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('.vertical-timeline')).toBeNull(); expect(vm.$el.querySelector('.vertical-timeline')).toBeNull();
expect(vm.$el.querySelector('.value')).not.toBeNull(); expect(vm.$el.querySelector('.value')).not.toBeNull();
}) });
.then(done)
.catch(done.fail);
}); });
it('render loading icon when isFetching is true', done => { it('render loading icon when isFetching is true', () => {
vm.$props.isFetching = true; vm.$props.isFetching = true;
vm.$nextTick()
.then(() => { return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('.fa-spinner')).toBeDefined(); expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
}) });
.then(done)
.catch(done.fail);
}); });
it('escapes html in the tooltip', done => { it('escapes html in the tooltip', () => {
const title = '<script>alert(1);</script>'; const title = '<script>alert(1);</script>';
const escapedTitle = escape(title); const escapedTitle = escape(title);
vm.$props.ancestors = [{ id: 1, url: '', title, state: 'open' }]; vm.$props.ancestors = [{ id: 1, url: '', title, state: 'open' }];
vm.$nextTick()
.then(() => {
const tooltip = vm.$el.querySelector('.collapse-truncated-title');
expect(tooltip.innerText).toBe(escapedTitle); return vm.$nextTick().then(() => {
}) const tooltip = vm.$el.querySelector('.collapse-truncated-title');
.then(done)
.catch(done.fail); expect(tooltip.innerText).toBe(escapedTitle);
});
}); });
}); });
import CEMockData from 'spec/sidebar/mock_data'; import CEMockData from 'jest/sidebar/mock_data';
const RESPONSE_MAP = { ...CEMockData.responseMap }; const RESPONSE_MAP = { ...CEMockData.responseMap };
......
...@@ -3,7 +3,7 @@ import CESidebarMediator from '~/sidebar/sidebar_mediator'; ...@@ -3,7 +3,7 @@ import CESidebarMediator from '~/sidebar/sidebar_mediator';
import CESidebarStore from '~/sidebar/stores/sidebar_store'; import CESidebarStore from '~/sidebar/stores/sidebar_store';
import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarService from '~/sidebar/services/sidebar_service';
import Mock from './ee_mock_data'; import Mock from './ee_mock_data';
import waitForPromises from 'spec/helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
describe('EE Sidebar mediator', () => { describe('EE Sidebar mediator', () => {
let mediator; let mediator;
...@@ -31,7 +31,7 @@ describe('EE Sidebar mediator', () => { ...@@ -31,7 +31,7 @@ describe('EE Sidebar mediator', () => {
it('updates status when updateStatus is called', () => { it('updates status when updateStatus is called', () => {
const healthStatus = 'onTrack'; const healthStatus = 'onTrack';
spyOn(mediator.service, 'updateWithGraphQl').and.returnValue( jest.spyOn(mediator.service, 'updateWithGraphQl').mockReturnValue(
Promise.resolve({ Promise.resolve({
data: { data: {
updateIssue: { updateIssue: {
......
...@@ -37,11 +37,11 @@ describe('EE Sidebar store', () => { ...@@ -37,11 +37,11 @@ describe('EE Sidebar store', () => {
describe('setStatus', () => { describe('setStatus', () => {
it('sets status', () => { it('sets status', () => {
expect(store.status).toEqual(''); expect(store.status).toBe('');
const status = 'onTrack'; const status = 'onTrack';
store.setStatus(status); store.setStatus(status);
expect(store.status).toEqual(status); expect(store.status).toBe(status);
}); });
}); });
......
...@@ -2,12 +2,12 @@ import Vue from 'vue'; ...@@ -2,12 +2,12 @@ import Vue from 'vue';
import sidebarWeight from 'ee/sidebar/components/weight/sidebar_weight.vue'; import sidebarWeight from 'ee/sidebar/components/weight/sidebar_weight.vue';
import SidebarMediator from 'ee/sidebar/sidebar_mediator'; import SidebarMediator from 'ee/sidebar/sidebar_mediator';
import SidebarStore from 'ee/sidebar/stores/sidebar_store'; import SidebarStore from 'ee/sidebar/stores/sidebar_store';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarService from '~/sidebar/services/sidebar_service';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
import Mock from './ee_mock_data'; import Mock from './ee_mock_data';
describe('Sidebar Weight', function() { describe('Sidebar Weight', () => {
let vm; let vm;
let sidebarMediator; let sidebarMediator;
let SidebarWeight; let SidebarWeight;
...@@ -26,7 +26,7 @@ describe('Sidebar Weight', function() { ...@@ -26,7 +26,7 @@ describe('Sidebar Weight', function() {
}); });
it('calls the mediator updateWeight on event', () => { it('calls the mediator updateWeight on event', () => {
spyOn(SidebarMediator.prototype, 'updateWeight').and.returnValue(Promise.resolve()); jest.spyOn(SidebarMediator.prototype, 'updateWeight').mockReturnValue(Promise.resolve());
vm = mountComponent(SidebarWeight, { vm = mountComponent(SidebarWeight, {
mediator: sidebarMediator, mediator: sidebarMediator,
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import weight from 'ee/sidebar/components/weight/weight.vue'; import weight from 'ee/sidebar/components/weight/weight.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper'; import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
import { ENTER_KEY_CODE } from '~/lib/utils/keycodes'; import { ENTER_KEY_CODE } from '~/lib/utils/keycodes';
...@@ -9,14 +9,12 @@ const DEFAULT_PROPS = { ...@@ -9,14 +9,12 @@ const DEFAULT_PROPS = {
weightNoneValue: 'None', weightNoneValue: 'None',
}; };
describe('Weight', function() { describe('Weight', () => {
let vm; let vm;
let Weight; let Weight;
let trackingSpy;
beforeEach(() => { beforeEach(() => {
Weight = Vue.extend(weight); Weight = Vue.extend(weight);
trackingSpy = mockTracking('_category_', null, spyOn);
}); });
afterEach(() => { afterEach(() => {
...@@ -53,11 +51,11 @@ describe('Weight', function() { ...@@ -53,11 +51,11 @@ describe('Weight', function() {
weight: WEIGHT, weight: WEIGHT,
}); });
expect(vm.$el.querySelector('.js-weight-collapsed-weight-label').textContent.trim()).toEqual( expect(vm.$el.querySelector('.js-weight-collapsed-weight-label').textContent.trim()).toBe(
`${WEIGHT}`, `${WEIGHT}`,
); );
expect(vm.$el.querySelector('.js-weight-weight-label-value').textContent.trim()).toEqual( expect(vm.$el.querySelector('.js-weight-weight-label-value').textContent.trim()).toBe(
`${WEIGHT}`, `${WEIGHT}`,
); );
}); });
...@@ -70,68 +68,46 @@ describe('Weight', function() { ...@@ -70,68 +68,46 @@ describe('Weight', function() {
weight: WEIGHT, weight: WEIGHT,
}); });
expect(vm.$el.querySelector('.js-weight-collapsed-weight-label').textContent.trim()).toEqual( expect(vm.$el.querySelector('.js-weight-collapsed-weight-label').textContent.trim()).toBe(
'None', 'None',
); );
expect(vm.$el.querySelector('.js-weight-weight-label .no-value').textContent.trim()).toEqual( expect(vm.$el.querySelector('.js-weight-weight-label .no-value').textContent.trim()).toBe(
'None', 'None',
); );
}); });
it('adds `collapse-after-update` class when clicking the collapsed block', done => { it('adds `collapse-after-update` class when clicking the collapsed block', () => {
vm = mountComponent(Weight, { vm = mountComponent(Weight, {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
}); });
vm.$el.querySelector('.js-weight-collapsed-block').click(); vm.$el.querySelector('.js-weight-collapsed-block').click();
vm.$nextTick() return vm.$nextTick().then(() => {
.then(() => { expect(vm.$el.classList.contains('collapse-after-update')).toBe(true);
expect(vm.$el.classList.contains('collapse-after-update')).toEqual(true); });
})
.then(done)
.catch(done.fail);
}); });
it('shows dropdown on "Edit" link click', done => { it('shows dropdown on "Edit" link click', () => {
vm = mountComponent(Weight, { vm = mountComponent(Weight, {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
editable: true, editable: true,
}); });
expect(vm.shouldShowEditField).toEqual(false); expect(vm.shouldShowEditField).toBe(false);
vm.$el.querySelector('.js-weight-edit-link').click(); vm.$el.querySelector('.js-weight-edit-link').click();
vm.$nextTick() return vm.$nextTick().then(() => {
.then(() => { expect(vm.shouldShowEditField).toBe(true);
expect(vm.shouldShowEditField).toEqual(true);
})
.then(done)
.catch(done.fail);
});
it('calls trackEvent when "Edit" is clicked', done => {
vm = mountComponent(Weight, {
...DEFAULT_PROPS,
editable: true,
}); });
triggerEvent(vm.$el.querySelector('.js-weight-edit-link'));
vm.$nextTick()
.then(() => {
expect(trackingSpy).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
}); });
it('emits event on input submission', done => { it('emits event on input submission', () => {
const ID = 123; const ID = 123;
const expectedWeightValue = '3'; const expectedWeightValue = '3';
spyOn(eventHub, '$emit'); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm = mountComponent(Weight, { vm = mountComponent(Weight, {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
editable: true, editable: true,
...@@ -140,7 +116,7 @@ describe('Weight', function() { ...@@ -140,7 +116,7 @@ describe('Weight', function() {
vm.$el.querySelector('.js-weight-edit-link').click(); vm.$el.querySelector('.js-weight-edit-link').click();
vm.$nextTick(() => { return vm.$nextTick(() => {
const event = new CustomEvent('keydown'); const event = new CustomEvent('keydown');
event.keyCode = ENTER_KEY_CODE; event.keyCode = ENTER_KEY_CODE;
...@@ -150,13 +126,12 @@ describe('Weight', function() { ...@@ -150,13 +126,12 @@ describe('Weight', function() {
expect(vm.hasValidInput).toBe(true); expect(vm.hasValidInput).toBe(true);
expect(eventHub.$emit).toHaveBeenCalledWith('updateWeight', expectedWeightValue, ID); expect(eventHub.$emit).toHaveBeenCalledWith('updateWeight', expectedWeightValue, ID);
done();
}); });
}); });
it('emits event on remove weight link click', done => { it('emits event on remove weight link click', () => {
const ID = 123; const ID = 123;
spyOn(eventHub, '$emit'); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm = mountComponent(Weight, { vm = mountComponent(Weight, {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
editable: true, editable: true,
...@@ -166,14 +141,13 @@ describe('Weight', function() { ...@@ -166,14 +141,13 @@ describe('Weight', function() {
vm.$el.querySelector('.js-weight-remove-link').click(); vm.$el.querySelector('.js-weight-remove-link').click();
vm.$nextTick(() => { return vm.$nextTick(() => {
expect(vm.hasValidInput).toBe(true); expect(vm.hasValidInput).toBe(true);
expect(eventHub.$emit).toHaveBeenCalledWith('updateWeight', '', ID); expect(eventHub.$emit).toHaveBeenCalledWith('updateWeight', '', ID);
done();
}); });
}); });
it('triggers error on invalid negative integer value', done => { it('triggers error on invalid negative integer value', () => {
vm = mountComponent(Weight, { vm = mountComponent(Weight, {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
editable: true, editable: true,
...@@ -181,7 +155,7 @@ describe('Weight', function() { ...@@ -181,7 +155,7 @@ describe('Weight', function() {
vm.$el.querySelector('.js-weight-edit-link').click(); vm.$el.querySelector('.js-weight-edit-link').click();
vm.$nextTick(() => { return vm.$nextTick(() => {
const event = new CustomEvent('keydown'); const event = new CustomEvent('keydown');
event.keyCode = ENTER_KEY_CODE; event.keyCode = ENTER_KEY_CODE;
...@@ -190,7 +164,32 @@ describe('Weight', function() { ...@@ -190,7 +164,32 @@ describe('Weight', function() {
vm.$refs.editableField.dispatchEvent(event); vm.$refs.editableField.dispatchEvent(event);
expect(vm.hasValidInput).toBe(false); expect(vm.hasValidInput).toBe(false);
done(); });
});
describe('tracking', () => {
let trackingSpy;
beforeEach(() => {
vm = mountComponent(Weight, {
...DEFAULT_PROPS,
editable: true,
});
trackingSpy = mockTracking('_category_', vm.$el, (obj, what) =>
jest.spyOn(obj, what).mockImplementation(() => {}),
);
});
afterEach(() => {
unmockTracking();
});
it('calls trackEvent when "Edit" is clicked', () => {
triggerEvent(vm.$el.querySelector('.js-weight-edit-link'));
return vm.$nextTick().then(() => {
expect(trackingSpy).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