Commit e00f7f1c authored by Illya Klymov's avatar Illya Klymov

Remove deprecated `setMethods` calls

`@vue/test-utils` 1.x deprecate `setMethods`
parent 42e1a2aa
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import DesignPresentation from '~/design_management/components/design_presentation.vue';
import DesignOverlay from '~/design_management/components/design_overlay.vue';
......@@ -100,12 +101,12 @@ describe('Design management design presentation component', () => {
clientY: endCoords.clientY,
});
return wrapper.vm.$nextTick();
return nextTick();
})
.then(() => {
if (mouseup) {
addCommentOverlay.trigger(event.mouseup);
return wrapper.vm.$nextTick();
return nextTick();
}
return undefined;
......@@ -125,7 +126,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.element).toMatchSnapshot();
});
});
......@@ -133,7 +134,7 @@ describe('Design management design presentation component', () => {
it('renders empty state when no image provided', () => {
createComponent();
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.element).toMatchSnapshot();
});
});
......@@ -149,7 +150,7 @@ describe('Design management design presentation component', () => {
wrapper.vm.openCommentForm({ x: 1, y: 1 });
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toEqual([
[{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
]);
......@@ -166,7 +167,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
......@@ -182,7 +183,7 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
......@@ -206,7 +207,7 @@ describe('Design management design presentation component', () => {
},
);
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.vm.currentCommentForm).toEqual({
x: 1,
y: 1,
......@@ -379,7 +380,7 @@ describe('Design management design presentation component', () => {
});
describe('onImageResize', () => {
it('sets zoom focal point on initial load', () => {
beforeEach(() => {
createComponent(
{
image: 'test.jpg',
......@@ -388,22 +389,21 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
wrapper.setMethods({
shiftZoomFocalPoint: jest.fn(),
scaleZoomFocalPoint: jest.fn(),
scrollToFocalPoint: jest.fn(),
jest.spyOn(wrapper.vm, 'shiftZoomFocalPoint');
jest.spyOn(wrapper.vm, 'scaleZoomFocalPoint');
jest.spyOn(wrapper.vm, 'scrollToFocalPoint');
wrapper.vm.onImageResize({ width: 10, height: 10 });
return nextTick();
});
wrapper.vm.onImageResize({ width: 10, height: 10 });
return wrapper.vm.$nextTick().then(() => {
it('sets zoom focal point on initial load', () => {
expect(wrapper.vm.shiftZoomFocalPoint).toHaveBeenCalled();
expect(wrapper.vm.initialLoad).toBe(false);
});
});
it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', () => {
wrapper.vm.onImageResize({ width: 10, height: 10 });
return wrapper.vm.$nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
});
......@@ -506,7 +506,7 @@ describe('Design management design presentation component', () => {
.$nextTick()
.then(() => {
addCommentOverlay.trigger('mouseup');
return wrapper.vm.$nextTick();
return nextTick();
})
.then(() => {
expect(wrapper.emitted('openCommentForm')).toBeDefined();
......
import { nextTick } from 'vue';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo, { ApolloMutation } from 'vue-apollo';
import VueDraggable from 'vuedraggable';
......@@ -8,7 +9,7 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import Index from '~/design_management/pages/index.vue';
import uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
import uploadDesignMutation from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
import DesignDestroyer from '~/design_management/components/design_destroyer.vue';
import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import DeleteButton from '~/design_management/components/delete_button.vue';
......@@ -113,7 +114,7 @@ describe('Design management index page', () => {
async function moveDesigns(localWrapper) {
await jest.runOnlyPendingTimers();
await localWrapper.vm.$nextTick();
await nextTick();
localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
localWrapper.find(VueDraggable).vm.$emit('change', {
......@@ -200,15 +201,14 @@ describe('Design management index page', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('renders error', () => {
it('renders error', async () => {
createComponent();
wrapper.setData({ error: true });
return wrapper.vm.$nextTick().then(() => {
await nextTick();
expect(wrapper.element).toMatchSnapshot();
});
});
it('renders a toolbar with buttons when there are designs', () => {
createComponent({ allVersions: [mockVersion] });
......@@ -254,10 +254,10 @@ describe('Design management index page', () => {
createComponent({ designCollection: { designs: [], copyState: 'READY' } });
});
it('renders design dropzone', () =>
wrapper.vm.$nextTick().then(() => {
it('renders design dropzone', async () => {
await nextTick();
expect(findDropzone().exists()).toBe(true);
}));
});
it('has correct classes applied to design dropzone', () => {
expect(dropzoneClasses()).not.toContain('design-list-item');
......@@ -268,10 +268,10 @@ describe('Design management index page', () => {
expect(findDropzoneWrapper().classes()).toEqual(['col-12']);
});
it('does not render a toolbar with buttons', () =>
wrapper.vm.$nextTick().then(() => {
it('does not render a toolbar with buttons', async () => {
await nextTick();
expect(findToolbar().exists()).toBe(false);
}));
});
});
describe('handling design collection copy state', () => {
......@@ -290,7 +290,7 @@ describe('Design management index page', () => {
});
describe('uploading designs', () => {
it('calls mutation on upload', () => {
it('calls mutation on upload', async () => {
createComponent({ stubs: { GlEmptyState } });
const mutationVariables = {
......@@ -298,7 +298,7 @@ describe('Design management index page', () => {
context: {
hasUpload: true,
},
mutation: uploadDesignQuery,
mutation: uploadDesignMutation,
variables: {
files: [{ name: 'test' }],
projectPath: 'project-path',
......@@ -348,21 +348,16 @@ describe('Design management index page', () => {
},
};
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
findDropzone().vm.$emit('change', [{ name: 'test' }]);
expect(mutate).toHaveBeenCalledWith(mutationVariables);
expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]);
expect(wrapper.vm.isSaving).toBeTruthy();
})
.then(() => {
expect(dropzoneClasses()).toContain('design-list-item');
expect(dropzoneClasses()).toContain('design-list-item-new');
});
});
it('sets isSaving', () => {
it('sets isSaving', async () => {
createComponent();
const uploadDesign = wrapper.vm.onUploadDesign([
......@@ -373,35 +368,31 @@ describe('Design management index page', () => {
expect(wrapper.vm.isSaving).toBe(true);
return uploadDesign.then(() => {
await uploadDesign;
expect(wrapper.vm.isSaving).toBe(false);
});
});
it('updates state appropriately after upload complete', () => {
it('updates state appropriately after upload complete', async () => {
createComponent({ stubs: { GlEmptyState } });
wrapper.setData({ filesToBeSaved: [{ name: 'test' }] });
wrapper.vm.onUploadDesignDone(designUploadMutationCreatedResponse);
return wrapper.vm.$nextTick().then(() => {
await nextTick();
expect(wrapper.vm.filesToBeSaved).toEqual([]);
expect(wrapper.vm.isSaving).toBeFalsy();
expect(wrapper.vm.isLatestVersion).toBe(true);
});
});
it('updates state appropriately after upload error', () => {
it('updates state appropriately after upload error', async () => {
createComponent({ stubs: { GlEmptyState } });
wrapper.setData({ filesToBeSaved: [{ name: 'test' }] });
wrapper.vm.onUploadDesignError();
return wrapper.vm.$nextTick().then(() => {
await nextTick();
expect(wrapper.vm.filesToBeSaved).toEqual([]);
expect(wrapper.vm.isSaving).toBeFalsy();
expect(createFlash).toHaveBeenCalled();
createFlash.mockReset();
});
});
it('does not call mutation if createDesign is false', () => {
......@@ -415,10 +406,6 @@ describe('Design management index page', () => {
describe('upload count limit', () => {
const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
afterEach(() => {
createFlash.mockReset();
});
it('does not warn when the max files are uploaded', () => {
createComponent();
......@@ -436,7 +423,7 @@ describe('Design management index page', () => {
});
});
it('flashes warning if designs are skipped', () => {
it('flashes warning if designs are skipped', async () => {
createComponent({
mockMutate: () =>
Promise.resolve({
......@@ -450,25 +437,22 @@ describe('Design management index page', () => {
},
]);
return uploadDesign.then(() => {
await uploadDesign;
expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith({
message: 'Upload skipped. test.jpg did not change.',
types: 'warning',
});
});
});
describe('dragging onto an existing design', () => {
let mockMutate;
beforeEach(() => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
});
it('calls onUploadDesign with valid upload', () => {
wrapper.setMethods({
onUploadDesign: jest.fn(),
mockMutate = jest.fn().mockResolvedValue();
createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate });
});
it('uploads designs with valid upload', () => {
const mockUploadPayload = [
{
name: mockDesigns[0].filename,
......@@ -478,8 +462,13 @@ describe('Design management index page', () => {
const designDropzone = findFirstDropzoneWithDesign();
designDropzone.vm.$emit('change', mockUploadPayload);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith(mockUploadPayload);
const [{ mutation, variables }] = mockMutate.mock.calls[0];
expect(mutation).toBe(uploadDesignMutation);
expect(variables).toStrictEqual({
files: mockUploadPayload,
iid: '1',
projectPath: 'project-path',
});
});
it.each`
......@@ -544,53 +533,41 @@ describe('Design management index page', () => {
expect(findToolbar().isVisible()).toBe(true);
});
it('adds two designs to selected designs when their checkboxes are checked', () => {
it('adds two designs to selected designs when their checkboxes are checked', async () => {
findDesignCheckboxes().at(0).trigger('click');
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
findDesignCheckboxes().at(1).trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
await nextTick();
expect(findDeleteButton().exists()).toBe(true);
expect(findSelectAllButton().text()).toBe('Deselect all');
findDeleteButton().vm.$emit('deleteSelectedDesigns');
const [{ variables }] = mutate.mock.calls[0];
expect(variables.filenames).toStrictEqual([
mockDesigns[0].filename,
mockDesigns[1].filename,
]);
});
expect(variables.filenames).toStrictEqual([mockDesigns[0].filename, mockDesigns[1].filename]);
});
it('adds all designs to selected designs when Select All button is clicked', () => {
it('adds all designs to selected designs when Select All button is clicked', async () => {
findSelectAllButton().vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
await nextTick();
expect(findDeleteButton().props().hasSelectedDesigns).toBe(true);
expect(findSelectAllButton().text()).toBe('Deselect all');
expect(wrapper.vm.selectedDesigns).toEqual(mockDesigns.map((design) => design.filename));
});
});
it('removes all designs from selected designs when at least one design was selected', () => {
it('removes all designs from selected designs when at least one design was selected', async () => {
findDesignCheckboxes().at(0).trigger('click');
await nextTick();
return wrapper.vm
.$nextTick()
.then(() => {
findSelectAllButton().vm.$emit('click');
})
.then(() => {
await nextTick();
expect(findDeleteButton().props().hasSelectedDesigns).toBe(false);
expect(findSelectAllButton().text()).toBe('Select all');
expect(wrapper.vm.selectedDesigns).toEqual([]);
});
});
});
it('on latest version when has no designs toolbar buttons are invisible', () => {
createComponent({
......@@ -626,12 +603,10 @@ describe('Design management index page', () => {
describe('pasting a design', () => {
let event;
let mockMutate;
beforeEach(() => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
wrapper.setMethods({
onUploadDesign: jest.fn(),
});
mockMutate = jest.fn().mockResolvedValue({});
createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate });
event = new Event('paste');
event.clipboardData = {
......@@ -640,36 +615,56 @@ describe('Design management index page', () => {
};
});
it('does not call paste event if designs wrapper is not hovered', () => {
it('does not upload designs if designs wrapper is not hovered', () => {
document.dispatchEvent(event);
expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
expect(mockMutate).not.toHaveBeenCalled();
});
describe('when designs wrapper is hovered', () => {
let realDateNow;
const today = () => new Date('2020-12-25');
beforeAll(() => {
realDateNow = Date.now;
global.Date.now = today;
});
afterAll(() => {
global.Date.now = realDateNow;
});
beforeEach(() => {
findDesignsWrapper().trigger('mouseenter');
});
it('calls onUploadDesign with valid paste', () => {
it('uploads design with valid paste', () => {
document.dispatchEvent(event);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([
new File([{ name: 'image.png' }], 'test.png'),
]);
const [{ mutation, variables }] = mockMutate.mock.calls[0];
expect(mutation).toBe(uploadDesignMutation);
expect(variables).toStrictEqual({
files: expect.any(Array),
iid: '1',
projectPath: 'project-path',
});
expect(variables.files).toEqual(event.clipboardData.files.map((f) => new File([f], '')));
});
it('renames a design if it has an image.png filename', () => {
event.clipboardData.getData = () => 'image.png';
document.dispatchEvent(event);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([
new File([{ name: 'image.png' }], `design_${Date.now()}.png`),
]);
const [{ mutation, variables }] = mockMutate.mock.calls[0];
expect(mutation).toBe(uploadDesignMutation);
expect(variables).toStrictEqual({
files: expect.any(Array),
iid: '1',
projectPath: 'project-path',
});
expect(variables.files[0].name).toEqual(`design_${Date.now()}.png`);
});
it('does not call onUploadDesign with invalid paste', () => {
it('does not call upload with invalid paste', () => {
event.clipboardData = {
items: [{ type: 'text/plain' }, { type: 'text' }],
files: [],
......@@ -677,37 +672,36 @@ describe('Design management index page', () => {
document.dispatchEvent(event);
expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
expect(mockMutate).not.toHaveBeenCalled();
});
it('removes onPaste listener after mouseleave event', async () => {
findDesignsWrapper().trigger('mouseleave');
document.dispatchEvent(event);
expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
expect(mockMutate).not.toHaveBeenCalled();
});
});
});
describe('when navigating', () => {
it('should trigger a scrollIntoView method if designs route is detected', () => {
it('should trigger a scrollIntoView method if designs route is detected', async () => {
router.replace({
path: '/designs',
});
createComponent({ loading: true });
return wrapper.vm.$nextTick().then(() => {
await nextTick();
expect(scrollIntoViewMock).toHaveBeenCalled();
});
});
});
describe('with mocked Apollo client', () => {
it('has a design with id 1 as a first one', async () => {
createComponentWithApollo({});
await jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
await nextTick();
expect(findDesigns()).toHaveLength(3);
expect(findDesigns().at(0).props('id')).toBe('1');
......@@ -720,7 +714,7 @@ describe('Design management index page', () => {
expect(moveDesignHandler).toHaveBeenCalled();
await wrapper.vm.$nextTick();
await nextTick();
expect(findDesigns().at(0).props('id')).toBe('2');
});
......@@ -733,8 +727,8 @@ describe('Design management index page', () => {
expect(draggableAttributes().disabled).toBe(true);
await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
await wrapper.vm.$nextTick(); // kick off the DOM update
await wrapper.vm.$nextTick(); // kick off the DOM update for finally block
await nextTick(); // kick off the DOM update
await nextTick(); // kick off the DOM update for finally block
expect(draggableAttributes().disabled).toBe(false);
});
......@@ -746,7 +740,7 @@ describe('Design management index page', () => {
await moveDesigns(wrapper);
await wrapper.vm.$nextTick();
await nextTick();
expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
});
......@@ -758,9 +752,9 @@ describe('Design management index page', () => {
await moveDesigns(wrapper);
await wrapper.vm.$nextTick(); // kick off the DOM update
await nextTick(); // kick off the DOM update
await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
await wrapper.vm.$nextTick(); // kick off the DOM update for flash
await nextTick(); // kick off the DOM update for flash
expect(createFlash).toHaveBeenCalledWith({
message: 'Something went wrong when reordering designs. Please try again',
......
import { nextTick } from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
......@@ -27,6 +27,8 @@ const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
const COMMIT_URL = `${TEST_HOST}/COMMIT/OLD`;
const UPDATED_COMMIT_URL = `${TEST_HOST}/COMMIT/NEW`;
Vue.use(Vuex);
function getCollapsedFilesWarning(wrapper) {
return wrapper.find(CollapsedFilesWarning);
}
......@@ -38,7 +40,6 @@ describe('diffs/components/app', () => {
let mock;
function createComponent(props = {}, extendStore = () => {}, provisions = {}) {
const localVue = createLocalVue();
const provide = {
...provisions,
glFeatures: {
......@@ -46,8 +47,6 @@ describe('diffs/components/app', () => {
},
};
localVue.use(Vuex);
store = createDiffsStore();
store.state.diffs.isLoading = false;
store.state.diffs.isTreeLoaded = true;
......@@ -55,7 +54,6 @@ describe('diffs/components/app', () => {
extendStore(store);
wrapper = shallowMount(App, {
localVue,
propsData: {
endpoint: TEST_ENDPOINT,
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
......@@ -262,7 +260,7 @@ describe('diffs/components/app', () => {
shouldShow: true,
});
// Component uses $nextTick so we wait until that has finished
// Component uses nextTick so we wait until that has finished
await nextTick();
expect(store.state.diffs.currentDiffFileId).toBe('ABC');
......@@ -298,8 +296,8 @@ describe('diffs/components/app', () => {
describe('keyboard shortcut navigation', () => {
let spies = [];
let jumpSpy;
let moveSpy;
let jumpSpy;
function setup(componentProps, featureFlags) {
createComponent(
......@@ -311,11 +309,8 @@ describe('diffs/components/app', () => {
);
moveSpy = jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
jumpSpy = jest.fn();
jumpSpy = jest.spyOn(wrapper.vm, 'jumpToFile').mockImplementation(() => {});
spies = [jumpSpy, moveSpy];
wrapper.setMethods({
jumpToFile: jumpSpy,
});
}
describe('visible app', () => {
......@@ -404,8 +399,6 @@ describe('diffs/components/app', () => {
let spy;
beforeEach(() => {
spy = jest.fn();
createComponent({}, () => {
store.state.diffs.diffFiles = [
{ file_hash: '111', file_path: '111.js' },
......@@ -413,10 +406,7 @@ describe('diffs/components/app', () => {
{ file_hash: '333', file_path: '333.js' },
];
});
wrapper.setMethods({
scrollToFile: spy,
});
spy = jest.spyOn(store, 'dispatch');
});
afterEach(() => {
......@@ -428,15 +418,15 @@ describe('diffs/components/app', () => {
wrapper.vm.jumpToFile(+1);
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '222.js']);
store.state.diffs.currentDiffFileId = '222';
wrapper.vm.jumpToFile(+1);
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['333.js']);
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '333.js']);
store.state.diffs.currentDiffFileId = '333';
wrapper.vm.jumpToFile(-1);
expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
// expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
});
it('does not jump to previous file from the first one', async () => {
......@@ -611,12 +601,6 @@ describe('diffs/components/app', () => {
});
describe('setTreeDisplay', () => {
let setShowTreeList;
beforeEach(() => {
setShowTreeList = jest.fn();
});
afterEach(() => {
localStorage.removeItem('mr_tree_show');
});
......@@ -625,14 +609,13 @@ describe('diffs/components/app', () => {
createComponent({}, ({ state }) => {
state.diffs.diffFiles.push({ sha: '123' });
});
wrapper.setMethods({
setShowTreeList,
});
jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList: false, saving: false });
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
showTreeList: false,
saving: false,
});
});
it('calls setShowTreeList with true when more than 1 file is in diffs array', () => {
......@@ -640,14 +623,14 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ sha: '123' });
state.diffs.diffFiles.push({ sha: '124' });
});
wrapper.setMethods({
setShowTreeList,
});
jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList: true, saving: false });
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
showTreeList: true,
saving: false,
});
});
it.each`
......@@ -660,14 +643,14 @@ describe('diffs/components/app', () => {
createComponent({}, ({ state }) => {
state.diffs.diffFiles.push({ sha: '123' });
});
wrapper.setMethods({
setShowTreeList,
});
jest.spyOn(store, 'dispatch');
wrapper.vm.setTreeDisplay();
expect(setShowTreeList).toHaveBeenCalledWith({ showTreeList, saving: false });
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowTreeList', {
showTreeList,
saving: false,
});
});
});
......
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import Terminal from '~/ide/components/terminal/terminal.vue';
......@@ -14,17 +15,18 @@ import GLTerminal from '~/terminal/terminal';
const TEST_TERMINAL_PATH = 'terminal/path';
const localVue = createLocalVue();
localVue.use(Vuex);
Vue.use(Vuex);
jest.mock('~/terminal/terminal', () =>
jest.fn().mockImplementation(() => ({
jest.fn().mockImplementation(function FakeTerminal() {
Object.assign(this, {
dispose: jest.fn(),
disable: jest.fn(),
addScrollListener: jest.fn(),
scrollToTop: jest.fn(),
scrollToBottom: jest.fn(),
})),
});
}),
);
describe('IDE Terminal', () => {
......@@ -41,13 +43,12 @@ describe('IDE Terminal', () => {
},
});
wrapper = shallowMount(localVue.extend(Terminal), {
wrapper = shallowMount(Terminal, {
propsData: {
status: RUNNING,
terminalPath: TEST_TERMINAL_PATH,
...propsData,
},
localVue,
store,
});
};
......@@ -102,7 +103,7 @@ describe('IDE Terminal', () => {
factory();
wrapper.vm.createTerminal();
return localVue.nextTick();
return nextTick();
});
it('is visible if terminal is created', () => {
......@@ -129,7 +130,7 @@ describe('IDE Terminal', () => {
wrapper.setData({ canScrollUp: true, canScrollDown: true });
return localVue.nextTick().then(() => {
return nextTick().then(() => {
expect(wrapper.find(TerminalControls).props()).toEqual({
canScrollUp: true,
canScrollDown: true,
......@@ -139,30 +140,24 @@ describe('IDE Terminal', () => {
});
describe('refresh', () => {
let createTerminal;
let stopTerminal;
beforeEach(() => {
createTerminal = jest.fn().mockName('createTerminal');
stopTerminal = jest.fn().mockName('stopTerminal');
});
it('creates the terminal if running', () => {
factory({ status: RUNNING, terminalPath: TEST_TERMINAL_PATH });
wrapper.setMethods({ createTerminal });
wrapper.vm.refresh();
expect(createTerminal).toHaveBeenCalled();
expect(GLTerminal.mock.instances).toHaveLength(1);
});
it('stops the terminal if stopping', () => {
factory({ status: STOPPING });
it('stops the terminal if stopping', async () => {
factory({ status: RUNNING, terminalPath: TEST_TERMINAL_PATH });
wrapper.setMethods({ stopTerminal });
wrapper.vm.refresh();
expect(stopTerminal).toHaveBeenCalled();
const terminal = GLTerminal.mock.instances[0];
wrapper.setProps({ status: STOPPING });
await nextTick();
expect(terminal.disable).toHaveBeenCalled();
});
});
......
......@@ -13,7 +13,8 @@ describe('JumpToNextDiscussionButton', () => {
wrapper = shallowMount(JumpToNextDiscussionButton, {
propsData: { fromDiscussionId },
});
wrapper.setMethods({ jumpToNextRelativeDiscussion: jumpFn });
jest.spyOn(wrapper.vm, 'jumpToNextRelativeDiscussion').mockImplementation(jumpFn);
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
});
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import createStore from '~/notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
......@@ -18,12 +19,9 @@ describe('issue_note_form component', () => {
let props;
const createComponentWrapper = () => {
const localVue = createLocalVue();
return shallowMount(localVue.extend(NoteForm), {
return shallowMount(NoteForm, {
store,
propsData: props,
// see https://gitlab.com/gitlab-org/gitlab-foss/issues/56317 for the following
localVue,
});
};
......@@ -60,24 +58,23 @@ describe('issue_note_form component', () => {
expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
});
it('return note hash as `#` when `noteId` is empty', () => {
it('return note hash as `#` when `noteId` is empty', async () => {
wrapper.setProps({
...props,
noteId: '',
});
await nextTick();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.noteHash).toBe('#');
});
});
});
describe('conflicts editing', () => {
beforeEach(() => {
wrapper = createComponentWrapper();
});
it('should show conflict message if note changes outside the component', () => {
it('should show conflict message if note changes outside the component', async () => {
wrapper.setProps({
...props,
isEditing: true,
......@@ -87,14 +84,14 @@ describe('issue_note_form component', () => {
const message =
'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.';
return wrapper.vm.$nextTick().then(() => {
await nextTick();
const conflictWarning = wrapper.find('.js-conflict-edit-warning');
expect(conflictWarning.exists()).toBe(true);
expect(conflictWarning.text().replace(/\s+/g, ' ').trim()).toBe(message);
});
});
});
describe('form', () => {
beforeEach(() => {
......@@ -156,29 +153,27 @@ describe('issue_note_form component', () => {
});
describe('actions', () => {
it('should be possible to cancel', () => {
const cancelHandler = jest.fn();
it('should be possible to cancel', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
wrapper.setMethods({ cancelHandler });
await nextTick();
return wrapper.vm.$nextTick().then(() => {
const cancelButton = wrapper.find('[data-testid="cancel"]');
cancelButton.trigger('click');
await nextTick();
expect(cancelHandler).toHaveBeenCalledWith(true);
});
expect(wrapper.emitted().cancelForm).toHaveLength(1);
});
it('should be possible to update the note', () => {
it('should be possible to update the note', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
await nextTick();
return wrapper.vm.$nextTick().then(() => {
const textarea = wrapper.find('textarea');
textarea.setValue('Foo');
const saveButton = wrapper.find('.js-vue-issue-save');
......@@ -188,7 +183,6 @@ describe('issue_note_form component', () => {
});
});
});
});
describe('with autosaveKey', () => {
describe('with draft', () => {
......@@ -199,7 +193,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
return wrapper.vm.$nextTick();
return nextTick();
});
it('displays the draft in textarea', () => {
......@@ -217,7 +211,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
return wrapper.vm.$nextTick();
return nextTick();
});
it('leaves the textarea empty', () => {
......@@ -273,16 +267,15 @@ describe('issue_note_form component', () => {
});
});
it('should be possible to cancel', () => {
it('should be possible to cancel', async () => {
jest.spyOn(wrapper.vm, 'cancelHandler');
return wrapper.vm.$nextTick().then(() => {
await nextTick();
const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
cancelButton.trigger('click');
expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
});
});
it('shows resolve checkbox', () => {
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(true);
......@@ -304,7 +297,7 @@ describe('issue_note_form component', () => {
},
});
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
});
......@@ -312,7 +305,7 @@ describe('issue_note_form component', () => {
it('hides actions for commits', () => {
wrapper.setProps({ discussion: { for_commit: true } });
return wrapper.vm.$nextTick(() => {
return nextTick(() => {
expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
});
});
......@@ -326,7 +319,7 @@ describe('issue_note_form component', () => {
textarea.setValue('Foo');
textarea.trigger('keydown.enter', { metaKey: true });
return wrapper.vm.$nextTick(() => {
return nextTick(() => {
expect(wrapper.vm.handleAddToReview).toHaveBeenCalled();
});
});
......
import { mount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { trimText } from 'helpers/text_helper';
import createStore from '~/notes/stores';
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import NoteForm from '~/notes/components/note_form.vue';
......@@ -17,8 +19,6 @@ import {
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
const localVue = createLocalVue();
describe('noteable_discussion component', () => {
let store;
let wrapper;
......@@ -32,10 +32,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
wrapper = mount(localVue.extend(noteableDiscussion), {
wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
localVue,
});
});
......@@ -47,32 +46,28 @@ describe('noteable_discussion component', () => {
expect(wrapper.find('.discussion-header').exists()).toBe(false);
});
it('should render thread header', () => {
it('should render thread header', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
discussion.expanded = false;
wrapper.setProps({ discussion });
await nextTick();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('.discussion-header').exists()).toBe(true);
});
});
describe('actions', () => {
it('should toggle reply form', () => {
const replyPlaceholder = wrapper.find(ReplyPlaceholder);
it('should toggle reply form', async () => {
await nextTick();
return wrapper.vm
.$nextTick()
.then(() => {
expect(wrapper.vm.isReplying).toEqual(false);
const replyPlaceholder = wrapper.find(ReplyPlaceholder);
replyPlaceholder.vm.$emit('onClick');
})
.then(() => wrapper.vm.$nextTick())
.then(() => {
await nextTick();
expect(wrapper.vm.isReplying).toEqual(true);
const noteForm = wrapper.find(NoteForm);
......@@ -87,23 +82,22 @@ describe('noteable_discussion component', () => {
expect(noteFormProps.saveButtonTitle).toBe('Comment');
expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
});
});
it('should expand discussion', async () => {
const expandDiscussion = jest.fn();
const discussion = { ...discussionMock };
discussion.expanded = false;
const discussion = { ...discussionMock, expanded: false };
wrapper.setProps({ discussion });
wrapper.setMethods({ expandDiscussion });
store.dispatch = jest.fn();
await wrapper.vm.$nextTick();
await nextTick();
wrapper.vm.showReplyForm();
wrapper.find(DiscussionNotes).vm.$emit('startReplying');
await wrapper.vm.$nextTick();
await nextTick();
expect(expandDiscussion).toHaveBeenCalledWith({ discussionId: discussion.id });
expect(store.dispatch).toHaveBeenCalledWith('expandDiscussion', {
discussionId: discussion.id,
});
});
it('does not render jump to thread button', () => {
......@@ -143,7 +137,7 @@ describe('noteable_discussion component', () => {
wrapper.setProps({ discussion });
return wrapper.vm.$nextTick();
return nextTick();
});
it('displays a button to resolve with issue', () => {
......@@ -169,10 +163,9 @@ describe('noteable_discussion component', () => {
window.gon.current_user_id = userDataMock.id;
store.dispatch('setUserData', userDataMock);
wrapper = mount(localVue.extend(noteableDiscussion), {
wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
localVue,
});
});
......@@ -188,10 +181,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', loggedOutnoteableData);
store.dispatch('setNotesData', notesDataMock);
wrapper = mount(localVue.extend(noteableDiscussion), {
wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
localVue,
});
});
......
import Vue from 'vue';
import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import { setHTMLFixture } from 'helpers/fixtures';
......@@ -153,21 +153,20 @@ describe('graph component', () => {
describe('triggered by', () => {
describe('on click', () => {
it('should emit `onClickUpstreamPipeline` when triggered by linked pipeline is clicked', () => {
it('should emit `onClickUpstreamPipeline` when triggered by linked pipeline is clicked', async () => {
const btnWrapper = findExpandPipelineBtn();
btnWrapper.trigger('click');
btnWrapper.vm.$nextTick(() => {
await nextTick();
expect(wrapper.emitted().onClickUpstreamPipeline).toEqual([
store.state.pipeline.triggered_by,
]);
});
});
});
describe('with expanded pipeline', () => {
it('should render expanded pipeline', (done) => {
it('should render expanded pipeline', async () => {
// expand the pipeline
store.state.pipeline.triggered_by[0].isExpanded = true;
......@@ -179,40 +178,46 @@ describe('graph component', () => {
},
});
Vue.nextTick()
.then(() => {
await nextTick();
expect(wrapper.find('.js-upstream-pipeline-12').exists()).toBe(true);
})
.then(done)
.catch(done.fail);
});
});
});
describe('triggered', () => {
describe('on click', () => {
it('should emit `onClickTriggered`', () => {
// We have to mock this method since we do both style change and
// emit and event, not mocking returns an error.
wrapper.setMethods({
handleClickedDownstream: jest.fn(() =>
wrapper.vm.$emit('onClickTriggered', ...store.state.pipeline.triggered),
),
// We have to mock this property of HTMLElement since component relies on it
let offsetParentDescriptor;
beforeAll(() => {
offsetParentDescriptor = Object.getOwnPropertyDescriptor(
HTMLElement.prototype,
'offsetParent',
);
Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
get() {
return this.parentNode;
},
});
});
afterAll(() => {
Object.defineProperty(HTMLElement.prototype, offsetParentDescriptor);
});
it('should emit `onClickDownstreamPipeline`', async () => {
const btnWrappers = findAllExpandPipelineBtns();
const downstreamBtnWrapper = btnWrappers.at(btnWrappers.length - 1);
downstreamBtnWrapper.trigger('click');
downstreamBtnWrapper.vm.$nextTick(() => {
expect(wrapper.emitted().onClickTriggered).toEqual([store.state.pipeline.triggered]);
});
await nextTick();
expect(wrapper.emitted().onClickDownstreamPipeline).toEqual([
[store.state.pipeline.triggered[1]],
]);
});
});
describe('with expanded pipeline', () => {
it('should render expanded pipeline', (done) => {
it('should render expanded pipeline', async () => {
// expand the pipeline
store.state.pipeline.triggered[0].isExpanded = true;
......@@ -224,12 +229,8 @@ describe('graph component', () => {
},
});
Vue.nextTick()
.then(() => {
await nextTick();
expect(wrapper.find('.js-downstream-pipeline-34993051')).not.toBeNull();
})
.then(done)
.catch(done.fail);
});
});
......
import 'bootstrap/js/dist/dropdown';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import StageComponent from '~/pipelines/components/pipelines_list/stage.vue';
import eventHub from '~/pipelines/event_hub';
......@@ -22,8 +22,11 @@ describe('Pipelines stage component', () => {
updateDropdown: false,
};
const isDropdownOpen = () => wrapper.classes('show');
const createComponent = (props = {}) => {
wrapper = mount(StageComponent, {
attachToDocument: true,
propsData: {
...defaultProps,
...props,
......@@ -60,11 +63,11 @@ describe('Pipelines stage component', () => {
createComponent();
});
it('should render the received data and emit `clickedDropdown` event', () => {
it('should render the received data and emit `clickedDropdown` event', async () => {
jest.spyOn(eventHub, '$emit');
wrapper.find('button').trigger('click');
return waitForPromises().then(() => {
await axios.waitForAll();
expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
stageReply.latest_statuses[0].name,
);
......@@ -72,26 +75,17 @@ describe('Pipelines stage component', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
});
});
});
describe('when request fails', () => {
beforeEach(() => {
it('when request fails should close the dropdown', async () => {
mock.onGet('path.json').reply(500);
createComponent();
});
it('should close the dropdown', () => {
wrapper.setMethods({
closeDropdown: jest.fn(),
isDropdownOpen: jest.fn().mockReturnValue(false),
});
wrapper.find({ ref: 'dropdown' }).trigger('click');
expect(isDropdownOpen()).toBe(true);
wrapper.find('button').trigger('click');
await axios.waitForAll();
return waitForPromises().then(() => {
expect(wrapper.vm.closeDropdown).toHaveBeenCalled();
});
});
expect(isDropdownOpen()).toBe(false);
});
describe('update endpoint correctly', () => {
......@@ -109,48 +103,39 @@ describe('Pipelines stage component', () => {
dropdown_path: 'bar.json',
},
});
return axios.waitForAll();
});
it('should update the stage to request the new endpoint provided', () => {
return wrapper.vm
.$nextTick()
.then(() => {
it('should update the stage to request the new endpoint provided', async () => {
wrapper.find('button').trigger('click');
return waitForPromises();
})
.then(() => {
await axios.waitForAll();
expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
'this is the updated content',
);
});
});
});
describe('pipelineActionRequestComplete', () => {
beforeEach(() => {
mock.onGet('path.json').reply(200, stageReply);
mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
createComponent({ type: 'PIPELINES_TABLE' });
});
describe('within pipeline table', () => {
it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', () => {
it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
jest.spyOn(eventHub, '$emit');
wrapper.find('button').trigger('click');
await axios.waitForAll();
return waitForPromises()
.then(() => {
wrapper.find('.js-ci-action').trigger('click');
await axios.waitForAll();
return waitForPromises();
})
.then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
});
});
});
});
});
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