Commit c6d9e943 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'xanf-v1-set-methods-rip' into 'master'

Upgrading VTU to v1: Remove deprecated `setMethods` calls

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