gitlab-org--gitlab-foss/spec/frontend/static_site_editor/pages/home_spec.js

306 lines
8.0 KiB
JavaScript

import { shallowMount, createLocalVue } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import EditArea from '~/static_site_editor/components/edit_area.vue';
import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue';
import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue';
import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constants';
import hasSubmittedChangesMutation from '~/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql';
import submitContentChangesMutation from '~/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql';
import Home from '~/static_site_editor/pages/home.vue';
import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants';
import {
project,
returnUrl,
sourceContentYAML as content,
sourceContentTitle as title,
sourcePath,
username,
mergeRequestMeta,
savedContentMeta,
submitChangesError,
trackingCategory,
images,
mounts,
branch,
baseUrl,
imageRoot,
} from '../mock_data';
const localVue = createLocalVue();
describe('static_site_editor/pages/home', () => {
let wrapper;
let store;
let $apollo;
let $router;
let mutateMock;
let trackingSpy;
const defaultAppData = {
isSupportedContent: true,
hasSubmittedChanges: false,
returnUrl,
project,
username,
sourcePath,
mounts,
branch,
baseUrl,
imageUploadPath: imageRoot,
};
const hasSubmittedChangesMutationPayload = {
data: {
appData: { ...defaultAppData, hasSubmittedChanges: true },
},
};
const buildApollo = (queries = {}) => {
mutateMock = jest.fn();
$apollo = {
queries: {
sourceContent: {
loading: false,
},
...queries,
},
mutate: mutateMock,
};
};
const buildRouter = () => {
$router = {
push: jest.fn(),
};
};
const buildWrapper = (data = {}) => {
wrapper = shallowMount(Home, {
localVue,
store,
mocks: {
$apollo,
$router,
},
data() {
return {
appData: { ...defaultAppData },
sourceContent: { title, content },
...data,
};
},
});
};
const findEditArea = () => wrapper.find(EditArea);
const findEditMetaModal = () => wrapper.find(EditMetaModal);
const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage);
const findSkeletonLoader = () => wrapper.find(SkeletonLoader);
const findSubmitChangesError = () => wrapper.find(SubmitChangesError);
beforeEach(() => {
buildApollo();
buildRouter();
document.body.dataset.page = trackingCategory;
trackingSpy = mockTracking(document.body.dataset.page, undefined, jest.spyOn);
});
afterEach(() => {
wrapper.destroy();
unmockTracking();
wrapper = null;
$apollo = null;
});
describe('when content is loaded', () => {
beforeEach(() => {
buildWrapper();
});
it('renders edit area', () => {
expect(findEditArea().exists()).toBe(true);
});
it('provides source content, returnUrl, and isSavingChanges to the edit area', () => {
expect(findEditArea().props()).toMatchObject({
title,
mounts,
content,
returnUrl,
savingChanges: false,
});
});
});
it('does not render edit area when content is not loaded', () => {
buildWrapper({ sourceContent: null });
expect(findEditArea().exists()).toBe(false);
});
it('renders skeleton loader when content is not loading', () => {
buildApollo({
sourceContent: {
loading: true,
},
});
buildWrapper();
expect(findSkeletonLoader().exists()).toBe(true);
});
it('does not render skeleton loader when content is not loading', () => {
buildApollo({
sourceContent: {
loading: false,
},
});
buildWrapper();
expect(findSkeletonLoader().exists()).toBe(false);
});
it('displays invalid content message when content is not supported', () => {
buildWrapper({ appData: { ...defaultAppData, isSupportedContent: false } });
expect(findInvalidContentMessage().exists()).toBe(true);
});
it('does not display invalid content message when content is supported', () => {
buildWrapper();
expect(findInvalidContentMessage().exists()).toBe(false);
});
it('renders an EditMetaModal component', () => {
buildWrapper();
expect(findEditMetaModal().exists()).toBe(true);
});
describe('when preparing submission', () => {
it('calls the show method when the edit-area submit event is emitted', () => {
buildWrapper();
const mockInstance = { show: jest.fn() };
wrapper.vm.$refs.editMetaModal = mockInstance;
findEditArea().vm.$emit('submit', { content });
return wrapper.vm.$nextTick().then(() => {
expect(mockInstance.show).toHaveBeenCalled();
});
});
});
describe('when submitting changes fails', () => {
const setupMutateMock = () => {
mutateMock
.mockResolvedValueOnce(hasSubmittedChangesMutationPayload)
.mockRejectedValueOnce(new Error(submitChangesError));
};
beforeEach(() => {
setupMutateMock();
buildWrapper({ content });
findEditMetaModal().vm.$emit('primary', mergeRequestMeta);
return wrapper.vm.$nextTick();
});
it('displays submit changes error message', () => {
expect(findSubmitChangesError().exists()).toBe(true);
});
it('retries submitting changes when retry button is clicked', () => {
setupMutateMock();
findSubmitChangesError().vm.$emit('retry');
expect(mutateMock).toHaveBeenCalled();
});
it('hides submit changes error message when dismiss button is clicked', () => {
findSubmitChangesError().vm.$emit('dismiss');
return wrapper.vm.$nextTick().then(() => {
expect(findSubmitChangesError().exists()).toBe(false);
});
});
});
describe('when submitting changes succeeds', () => {
const newContent = `new ${content}`;
const formattedMarkdown = `formatted ${content}`;
beforeEach(() => {
mutateMock.mockResolvedValueOnce(hasSubmittedChangesMutationPayload).mockResolvedValueOnce({
data: {
submitContentChanges: savedContentMeta,
},
});
buildWrapper();
findEditMetaModal().vm.show = jest.fn();
findEditArea().vm.$emit('submit', { content: newContent, images, formattedMarkdown });
findEditMetaModal().vm.$emit('primary', mergeRequestMeta);
return wrapper.vm.$nextTick();
});
it('dispatches hasSubmittedChanges mutation', () => {
expect(mutateMock).toHaveBeenNthCalledWith(1, {
mutation: hasSubmittedChangesMutation,
variables: {
input: {
hasSubmittedChanges: true,
},
},
});
});
it('dispatches submitContentChanges mutation', () => {
expect(mutateMock).toHaveBeenNthCalledWith(2, {
mutation: submitContentChangesMutation,
variables: {
input: {
content: newContent,
formattedMarkdown,
project,
sourcePath,
targetBranch: branch,
username,
images,
mergeRequestMeta,
},
},
});
});
it('transitions to the SUCCESS route', () => {
expect($router.push).toHaveBeenCalledWith(SUCCESS_ROUTE);
});
});
it('does not display submit changes error when an error does not exist', () => {
buildWrapper();
expect(findSubmitChangesError().exists()).toBe(false);
});
it('tracks when editor is initialized on the mounted lifecycle hook', () => {
buildWrapper();
expect(trackingSpy).toHaveBeenCalledWith(
document.body.dataset.page,
TRACKING_ACTION_INITIALIZE_EDITOR,
);
});
});