summaryrefslogtreecommitdiff
path: root/spec/frontend/static_site_editor
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/static_site_editor')
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js76
-rw-r--r--spec/frontend/static_site_editor/components/publish_toolbar_spec.js17
-rw-r--r--spec/frontend/static_site_editor/components/saved_changes_message_spec.js7
-rw-r--r--spec/frontend/static_site_editor/components/static_site_editor_spec.js247
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/file_spec.js25
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js37
-rw-r--r--spec/frontend/static_site_editor/mock_data.js5
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js211
-rw-r--r--spec/frontend/static_site_editor/pages/success_spec.js78
-rw-r--r--spec/frontend/static_site_editor/services/submit_content_changes_spec.js32
-rw-r--r--spec/frontend/static_site_editor/store/actions_spec.js152
-rw-r--r--spec/frontend/static_site_editor/store/getters_spec.js19
-rw-r--r--spec/frontend/static_site_editor/store/mutations_spec.js54
13 files changed, 468 insertions, 492 deletions
diff --git a/spec/frontend/static_site_editor/components/edit_area_spec.js b/spec/frontend/static_site_editor/components/edit_area_spec.js
new file mode 100644
index 00000000000..bfe41f65d6e
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -0,0 +1,76 @@
+import { shallowMount } from '@vue/test-utils';
+
+import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
+
+import EditArea from '~/static_site_editor/components/edit_area.vue';
+import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
+import EditHeader from '~/static_site_editor/components/edit_header.vue';
+
+import { sourceContentTitle as title, sourceContent as content, returnUrl } from '../mock_data';
+
+describe('~/static_site_editor/components/edit_area.vue', () => {
+ let wrapper;
+ const savingChanges = true;
+ const newContent = `new ${content}`;
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(EditArea, {
+ propsData: {
+ title,
+ content,
+ returnUrl,
+ savingChanges,
+ ...propsData,
+ },
+ });
+ };
+
+ const findEditHeader = () => wrapper.find(EditHeader);
+ const findRichContentEditor = () => wrapper.find(RichContentEditor);
+ const findPublishToolbar = () => wrapper.find(PublishToolbar);
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders edit header', () => {
+ expect(findEditHeader().exists()).toBe(true);
+ expect(findEditHeader().props('title')).toBe(title);
+ });
+
+ it('renders rich content editor', () => {
+ expect(findRichContentEditor().exists()).toBe(true);
+ expect(findRichContentEditor().props('value')).toBe(content);
+ });
+
+ it('renders publish toolbar', () => {
+ expect(findPublishToolbar().exists()).toBe(true);
+ expect(findPublishToolbar().props('returnUrl')).toBe(returnUrl);
+ expect(findPublishToolbar().props('savingChanges')).toBe(savingChanges);
+ expect(findPublishToolbar().props('saveable')).toBe(false);
+ });
+
+ describe('when content changes', () => {
+ beforeEach(() => {
+ findRichContentEditor().vm.$emit('input', newContent);
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('sets publish toolbar as saveable when content changes', () => {
+ expect(findPublishToolbar().props('saveable')).toBe(true);
+ });
+
+ it('sets publish toolbar as not saveable when content changes are rollback', () => {
+ findRichContentEditor().vm.$emit('input', content);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findPublishToolbar().props('saveable')).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
index 82eb12d4c4d..5428ed23266 100644
--- a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
+++ b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
@@ -19,7 +19,6 @@ describe('Static Site Editor Toolbar', () => {
const findReturnUrlLink = () => wrapper.find({ ref: 'returnUrlLink' });
const findSaveChangesButton = () => wrapper.find(GlButton);
- const findLoadingIndicator = () => wrapper.find(GlLoadingIcon);
beforeEach(() => {
buildWrapper();
@@ -37,8 +36,8 @@ describe('Static Site Editor Toolbar', () => {
expect(findSaveChangesButton().attributes('disabled')).toBe('true');
});
- it('does not display saving changes indicator', () => {
- expect(findLoadingIndicator().classes()).toContain('invisible');
+ it('does not render the Submit Changes button with a loader', () => {
+ expect(findSaveChangesButton().props('loading')).toBe(false);
});
it('does not render returnUrl link', () => {
@@ -62,15 +61,11 @@ describe('Static Site Editor Toolbar', () => {
describe('when saving changes', () => {
beforeEach(() => {
- buildWrapper({ saveable: true, savingChanges: true });
+ buildWrapper({ savingChanges: true });
});
- it('disables Submit Changes button', () => {
- expect(findSaveChangesButton().attributes('disabled')).toBe('true');
- });
-
- it('displays saving changes indicator', () => {
- expect(findLoadingIndicator().classes()).not.toContain('invisible');
+ it('renders the Submit Changes button with a loading indicator', () => {
+ expect(findSaveChangesButton().props('loading')).toBe(true);
});
});
diff --git a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
index 659e9be59d2..a63c3a83395 100644
--- a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
+++ b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
@@ -46,14 +46,11 @@ describe('~/static_site_editor/components/saved_changes_message.vue', () => {
${'branch'} | ${findBranchLink} | ${props.branch}
${'commit'} | ${findCommitLink} | ${props.commit}
${'merge request'} | ${findMergeRequestLink} | ${props.mergeRequest}
- `('renders $desc link', ({ desc, findEl, prop }) => {
+ `('renders $desc link', ({ findEl, prop }) => {
const el = findEl();
expect(el.exists()).toBe(true);
expect(el.text()).toBe(prop.label);
-
- if (desc !== 'branch') {
- expect(el.attributes('href')).toBe(prop.url);
- }
+ expect(el.attributes('href')).toBe(prop.url);
});
});
diff --git a/spec/frontend/static_site_editor/components/static_site_editor_spec.js b/spec/frontend/static_site_editor/components/static_site_editor_spec.js
deleted file mode 100644
index 5d4e3758557..00000000000
--- a/spec/frontend/static_site_editor/components/static_site_editor_spec.js
+++ /dev/null
@@ -1,247 +0,0 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlSkeletonLoader } from '@gitlab/ui';
-
-import createState from '~/static_site_editor/store/state';
-
-import StaticSiteEditor from '~/static_site_editor/components/static_site_editor.vue';
-import EditArea from '~/static_site_editor/components/edit_area.vue';
-import EditHeader from '~/static_site_editor/components/edit_header.vue';
-import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue';
-import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
-import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
-import SavedChangesMessage from '~/static_site_editor/components/saved_changes_message.vue';
-
-import {
- returnUrl,
- sourceContent,
- sourceContentTitle,
- savedContentMeta,
- submitChangesError,
-} from '../mock_data';
-
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
-
-describe('StaticSiteEditor', () => {
- let wrapper;
- let store;
- let loadContentActionMock;
- let setContentActionMock;
- let submitChangesActionMock;
- let dismissSubmitChangesErrorActionMock;
-
- const buildStore = ({ initialState, getters } = {}) => {
- loadContentActionMock = jest.fn();
- setContentActionMock = jest.fn();
- submitChangesActionMock = jest.fn();
- dismissSubmitChangesErrorActionMock = jest.fn();
-
- store = new Vuex.Store({
- state: createState({
- isSupportedContent: true,
- ...initialState,
- }),
- getters: {
- contentChanged: () => false,
- ...getters,
- },
- actions: {
- loadContent: loadContentActionMock,
- setContent: setContentActionMock,
- submitChanges: submitChangesActionMock,
- dismissSubmitChangesError: dismissSubmitChangesErrorActionMock,
- },
- });
- };
- const buildContentLoadedStore = ({ initialState, getters } = {}) => {
- buildStore({
- initialState: {
- isContentLoaded: true,
- ...initialState,
- },
- getters: {
- ...getters,
- },
- });
- };
-
- const buildWrapper = () => {
- wrapper = shallowMount(StaticSiteEditor, {
- localVue,
- store,
- });
- };
-
- const findEditArea = () => wrapper.find(EditArea);
- const findEditHeader = () => wrapper.find(EditHeader);
- const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage);
- const findPublishToolbar = () => wrapper.find(PublishToolbar);
- const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
- const findSubmitChangesError = () => wrapper.find(SubmitChangesError);
- const findSavedChangesMessage = () => wrapper.find(SavedChangesMessage);
-
- beforeEach(() => {
- buildStore();
- buildWrapper();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders the saved changes message when changes are submitted successfully', () => {
- buildStore({ initialState: { returnUrl, savedContentMeta } });
- buildWrapper();
-
- expect(findSavedChangesMessage().exists()).toBe(true);
- expect(findSavedChangesMessage().props()).toEqual({
- returnUrl,
- ...savedContentMeta,
- });
- });
-
- describe('when content is not loaded', () => {
- it('does not render edit area', () => {
- expect(findEditArea().exists()).toBe(false);
- });
-
- it('does not render edit header', () => {
- expect(findEditHeader().exists()).toBe(false);
- });
-
- it('does not render toolbar', () => {
- expect(findPublishToolbar().exists()).toBe(false);
- });
-
- it('does not render saved changes message', () => {
- expect(findSavedChangesMessage().exists()).toBe(false);
- });
- });
-
- describe('when content is loaded', () => {
- const content = sourceContent;
- const title = sourceContentTitle;
-
- beforeEach(() => {
- buildContentLoadedStore({ initialState: { content, title } });
- buildWrapper();
- });
-
- it('renders the edit area', () => {
- expect(findEditArea().exists()).toBe(true);
- });
-
- it('renders the edit header', () => {
- expect(findEditHeader().exists()).toBe(true);
- });
-
- it('does not render skeleton loader', () => {
- expect(findSkeletonLoader().exists()).toBe(false);
- });
-
- it('passes page content to edit area', () => {
- expect(findEditArea().props('value')).toBe(content);
- });
-
- it('passes page title to edit header', () => {
- expect(findEditHeader().props('title')).toBe(title);
- });
-
- it('renders toolbar', () => {
- expect(findPublishToolbar().exists()).toBe(true);
- });
- });
-
- it('sets toolbar as saveable when content changes', () => {
- buildContentLoadedStore({
- getters: {
- contentChanged: () => true,
- },
- });
- buildWrapper();
-
- expect(findPublishToolbar().props('saveable')).toBe(true);
- });
-
- it('displays skeleton loader when loading content', () => {
- buildStore({ initialState: { isLoadingContent: true } });
- buildWrapper();
-
- expect(findSkeletonLoader().exists()).toBe(true);
- });
-
- it('does not display submit changes error when an error does not exist', () => {
- buildContentLoadedStore();
- buildWrapper();
-
- expect(findSubmitChangesError().exists()).toBe(false);
- });
-
- it('sets toolbar as saving when saving changes', () => {
- buildContentLoadedStore({
- initialState: {
- isSavingChanges: true,
- },
- });
- buildWrapper();
-
- expect(findPublishToolbar().props('savingChanges')).toBe(true);
- });
-
- it('displays invalid content message when content is not supported', () => {
- buildStore({ initialState: { isSupportedContent: false } });
- buildWrapper();
-
- expect(findInvalidContentMessage().exists()).toBe(true);
- });
-
- describe('when submitting changes fail', () => {
- beforeEach(() => {
- buildContentLoadedStore({
- initialState: {
- submitChangesError,
- },
- });
- buildWrapper();
- });
-
- it('displays submit changes error message', () => {
- expect(findSubmitChangesError().exists()).toBe(true);
- });
-
- it('dispatches submitChanges action when error message emits retry event', () => {
- findSubmitChangesError().vm.$emit('retry');
-
- expect(submitChangesActionMock).toHaveBeenCalled();
- });
-
- it('dispatches dismissSubmitChangesError action when error message emits dismiss event', () => {
- findSubmitChangesError().vm.$emit('dismiss');
-
- expect(dismissSubmitChangesErrorActionMock).toHaveBeenCalled();
- });
- });
-
- it('dispatches load content action', () => {
- expect(loadContentActionMock).toHaveBeenCalled();
- });
-
- it('dispatches setContent action when edit area emits input event', () => {
- buildContentLoadedStore();
- buildWrapper();
-
- findEditArea().vm.$emit('input', sourceContent);
-
- expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), sourceContent, undefined);
- });
-
- it('dispatches submitChanges action when toolbar emits submit event', () => {
- buildContentLoadedStore();
- buildWrapper();
- findPublishToolbar().vm.$emit('submit');
-
- expect(submitChangesActionMock).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
new file mode 100644
index 00000000000..8504d09e0f1
--- /dev/null
+++ b/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
@@ -0,0 +1,25 @@
+import fileResolver from '~/static_site_editor/graphql/resolvers/file';
+import loadSourceContent from '~/static_site_editor/services/load_source_content';
+
+import {
+ projectId,
+ sourcePath,
+ sourceContentTitle as title,
+ sourceContent as content,
+} from '../../mock_data';
+
+jest.mock('~/static_site_editor/services/load_source_content', () => jest.fn());
+
+describe('static_site_editor/graphql/resolvers/file', () => {
+ it('returns file content and title when fetching file successfully', () => {
+ loadSourceContent.mockResolvedValueOnce({ title, content });
+
+ return fileResolver({ fullPath: projectId }, { path: sourcePath }).then(file => {
+ expect(file).toEqual({
+ __typename: 'File',
+ title,
+ content,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
new file mode 100644
index 00000000000..515b5394594
--- /dev/null
+++ b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
@@ -0,0 +1,37 @@
+import savedContentMetaQuery from '~/static_site_editor/graphql/queries/saved_content_meta.query.graphql';
+import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
+import submitContentChangesResolver from '~/static_site_editor/graphql/resolvers/submit_content_changes';
+
+import {
+ projectId as project,
+ sourcePath,
+ username,
+ sourceContent as content,
+ savedContentMeta,
+} from '../../mock_data';
+
+jest.mock('~/static_site_editor/services/submit_content_changes', () => jest.fn());
+
+describe('static_site_editor/graphql/resolvers/submit_content_changes', () => {
+ it('writes savedContentMeta query with the data returned by the submitContentChanges service', () => {
+ const cache = { writeQuery: jest.fn() };
+
+ submitContentChanges.mockResolvedValueOnce(savedContentMeta);
+
+ return submitContentChangesResolver(
+ {},
+ { input: { path: sourcePath, project, sourcePath, content, username } },
+ { cache },
+ ).then(() => {
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: savedContentMetaQuery,
+ data: {
+ savedContentMeta: {
+ __typename: 'SavedContentMeta',
+ ...savedContentMeta,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js
index 962047e6dd2..371695e913e 100644
--- a/spec/frontend/static_site_editor/mock_data.js
+++ b/spec/frontend/static_site_editor/mock_data.js
@@ -34,6 +34,9 @@ export const savedContentMeta = {
};
export const submitChangesError = 'Could not save changes';
+export const commitBranchResponse = {
+ web_url: '/tree/root-master-patch-88195',
+};
export const commitMultipleResponse = {
short_id: 'ed899a2f4b5',
web_url: '/commit/ed899a2f4b5',
@@ -42,3 +45,5 @@ export const createMergeRequestResponse = {
iid: '123',
web_url: '/merge_requests/123',
};
+
+export const trackingCategory = 'projects:static_site_editor:show';
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
new file mode 100644
index 00000000000..8c9c54f593e
--- /dev/null
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -0,0 +1,211 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Home from '~/static_site_editor/pages/home.vue';
+import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue';
+import EditArea from '~/static_site_editor/components/edit_area.vue';
+import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue';
+import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
+import submitContentChangesMutation from '~/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql';
+import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants';
+
+import {
+ projectId as project,
+ returnUrl,
+ sourceContent as content,
+ sourceContentTitle as title,
+ sourcePath,
+ username,
+ savedContentMeta,
+ submitChangesError,
+} from '../mock_data';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('static_site_editor/pages/home', () => {
+ let wrapper;
+ let store;
+ let $apollo;
+ let $router;
+ let mutateMock;
+
+ 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: { isSupportedContent: true, returnUrl, project, username, sourcePath },
+ sourceContent: { title, content },
+ ...data,
+ };
+ },
+ });
+ };
+
+ const findEditArea = () => wrapper.find(EditArea);
+ const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage);
+ const findSkeletonLoader = () => wrapper.find(SkeletonLoader);
+ const findSubmitChangesError = () => wrapper.find(SubmitChangesError);
+
+ beforeEach(() => {
+ buildApollo();
+ buildRouter();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ 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,
+ 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: { isSupportedContent: false } });
+
+ expect(findInvalidContentMessage().exists()).toBe(true);
+ });
+
+ it('does not display invalid content message when content is supported', () => {
+ buildWrapper({ appData: { isSupportedContent: true } });
+
+ expect(findInvalidContentMessage().exists()).toBe(false);
+ });
+
+ describe('when submitting changes fails', () => {
+ beforeEach(() => {
+ mutateMock.mockRejectedValue(new Error(submitChangesError));
+
+ buildWrapper();
+ findEditArea().vm.$emit('submit', { content });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays submit changes error message', () => {
+ expect(findSubmitChangesError().exists()).toBe(true);
+ });
+
+ it('retries submitting changes when retry button is clicked', () => {
+ 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);
+ });
+ });
+ });
+
+ it('does not display submit changes error when an error does not exist', () => {
+ buildWrapper();
+
+ expect(findSubmitChangesError().exists()).toBe(false);
+ });
+
+ describe('when submitting changes succeeds', () => {
+ const newContent = `new ${content}`;
+
+ beforeEach(() => {
+ mutateMock.mockResolvedValueOnce({ data: { submitContentChanges: savedContentMeta } });
+
+ buildWrapper();
+ findEditArea().vm.$emit('submit', { content: newContent });
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('dispatches submitContentChanges mutation', () => {
+ expect(mutateMock).toHaveBeenCalledWith({
+ mutation: submitContentChangesMutation,
+ variables: {
+ input: {
+ content: newContent,
+ project,
+ sourcePath,
+ username,
+ },
+ },
+ });
+ });
+
+ it('transitions to the SUCCESS route', () => {
+ expect($router.push).toHaveBeenCalledWith(SUCCESS_ROUTE);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/pages/success_spec.js b/spec/frontend/static_site_editor/pages/success_spec.js
new file mode 100644
index 00000000000..d62b67bfa83
--- /dev/null
+++ b/spec/frontend/static_site_editor/pages/success_spec.js
@@ -0,0 +1,78 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Success from '~/static_site_editor/pages/success.vue';
+import SavedChangesMessage from '~/static_site_editor/components/saved_changes_message.vue';
+import { savedContentMeta, returnUrl } from '../mock_data';
+import { HOME_ROUTE } from '~/static_site_editor/router/constants';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('static_site_editor/pages/success', () => {
+ let wrapper;
+ let store;
+ let router;
+
+ const buildRouter = () => {
+ router = {
+ push: jest.fn(),
+ };
+ };
+
+ const buildWrapper = (data = {}) => {
+ wrapper = shallowMount(Success, {
+ localVue,
+ store,
+ mocks: {
+ $router: router,
+ },
+ data() {
+ return {
+ savedContentMeta,
+ appData: {
+ returnUrl,
+ },
+ ...data,
+ };
+ },
+ });
+ };
+
+ const findSavedChangesMessage = () => wrapper.find(SavedChangesMessage);
+
+ beforeEach(() => {
+ buildRouter();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders saved changes message', () => {
+ buildWrapper();
+
+ expect(findSavedChangesMessage().exists()).toBe(true);
+ });
+
+ it('passes returnUrl to the saved changes message', () => {
+ buildWrapper();
+
+ expect(findSavedChangesMessage().props('returnUrl')).toBe(returnUrl);
+ });
+
+ it('passes saved content metadata to the saved changes message', () => {
+ buildWrapper();
+
+ expect(findSavedChangesMessage().props('branch')).toBe(savedContentMeta.branch);
+ expect(findSavedChangesMessage().props('commit')).toBe(savedContentMeta.commit);
+ expect(findSavedChangesMessage().props('mergeRequest')).toBe(savedContentMeta.mergeRequest);
+ });
+
+ it('redirects to the HOME route when content has not been submitted', () => {
+ buildWrapper({ savedContentMeta: null });
+
+ expect(router.push).toHaveBeenCalledWith(HOME_ROUTE);
+ });
+});
diff --git a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
index 9a0bd88b57d..a1e9ff4ec4c 100644
--- a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
+++ b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
@@ -1,11 +1,13 @@
import Api from '~/api';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import {
DEFAULT_TARGET_BRANCH,
SUBMIT_CHANGES_BRANCH_ERROR,
SUBMIT_CHANGES_COMMIT_ERROR,
SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
+ TRACKING_ACTION_CREATE_COMMIT,
} from '~/static_site_editor/constants';
import generateBranchName from '~/static_site_editor/services/generate_branch_name';
import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
@@ -13,10 +15,12 @@ import submitContentChanges from '~/static_site_editor/services/submit_content_c
import {
username,
projectId,
+ commitBranchResponse,
commitMultipleResponse,
createMergeRequestResponse,
sourcePath,
sourceContent as content,
+ trackingCategory,
} from '../mock_data';
jest.mock('~/static_site_editor/services/generate_branch_name');
@@ -24,15 +28,26 @@ jest.mock('~/static_site_editor/services/generate_branch_name');
describe('submitContentChanges', () => {
const mergeRequestTitle = `Update ${sourcePath} file`;
const branch = 'branch-name';
+ let trackingSpy;
+ let origPage;
beforeEach(() => {
- jest.spyOn(Api, 'createBranch').mockResolvedValue();
+ jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse });
jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse });
jest
.spyOn(Api, 'createProjectMergeRequest')
.mockResolvedValue({ data: createMergeRequestResponse });
generateBranchName.mockReturnValue(branch);
+
+ origPage = document.body.dataset.page;
+ document.body.dataset.page = trackingCategory;
+ trackingSpy = mockTracking(document.body.dataset.page, undefined, jest.spyOn);
+ });
+
+ afterEach(() => {
+ document.body.dataset.page = origPage;
+ unmockTracking();
});
it('creates a branch named after the username and target branch', () => {
@@ -47,7 +62,7 @@ describe('submitContentChanges', () => {
it('notifies error when branch could not be created', () => {
Api.createBranch.mockRejectedValueOnce();
- expect(submitContentChanges({ username, projectId })).rejects.toThrow(
+ return expect(submitContentChanges({ username, projectId })).rejects.toThrow(
SUBMIT_CHANGES_BRANCH_ERROR,
);
});
@@ -68,10 +83,19 @@ describe('submitContentChanges', () => {
});
});
+ it('sends the correct tracking event when committing content changes', () => {
+ return submitContentChanges({ username, projectId, sourcePath, content }).then(() => {
+ expect(trackingSpy).toHaveBeenCalledWith(
+ document.body.dataset.page,
+ TRACKING_ACTION_CREATE_COMMIT,
+ );
+ });
+ });
+
it('notifies error when content could not be committed', () => {
Api.commitMultiple.mockRejectedValueOnce();
- expect(submitContentChanges({ username, projectId })).rejects.toThrow(
+ return expect(submitContentChanges({ username, projectId })).rejects.toThrow(
SUBMIT_CHANGES_COMMIT_ERROR,
);
});
@@ -92,7 +116,7 @@ describe('submitContentChanges', () => {
it('notifies error when merge request could not be created', () => {
Api.createProjectMergeRequest.mockRejectedValueOnce();
- expect(submitContentChanges({ username, projectId })).rejects.toThrow(
+ return expect(submitContentChanges({ username, projectId })).rejects.toThrow(
SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
);
});
diff --git a/spec/frontend/static_site_editor/store/actions_spec.js b/spec/frontend/static_site_editor/store/actions_spec.js
deleted file mode 100644
index 6b0b77f59b7..00000000000
--- a/spec/frontend/static_site_editor/store/actions_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import testAction from 'helpers/vuex_action_helper';
-import createState from '~/static_site_editor/store/state';
-import * as actions from '~/static_site_editor/store/actions';
-import * as mutationTypes from '~/static_site_editor/store/mutation_types';
-import loadSourceContent from '~/static_site_editor/services/load_source_content';
-import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
-
-import createFlash from '~/flash';
-
-import {
- username,
- projectId,
- sourcePath,
- sourceContentTitle as title,
- sourceContent as content,
- savedContentMeta,
- submitChangesError,
-} from '../mock_data';
-
-jest.mock('~/flash');
-jest.mock('~/static_site_editor/services/load_source_content', () => jest.fn());
-jest.mock('~/static_site_editor/services/submit_content_changes', () => jest.fn());
-
-describe('Static Site Editor Store actions', () => {
- let state;
-
- beforeEach(() => {
- state = createState({
- projectId,
- sourcePath,
- });
- });
-
- describe('loadContent', () => {
- describe('on success', () => {
- const payload = { title, content };
-
- beforeEach(() => {
- loadSourceContent.mockResolvedValueOnce(payload);
- });
-
- it('commits receiveContentSuccess', () => {
- testAction(
- actions.loadContent,
- null,
- state,
- [
- { type: mutationTypes.LOAD_CONTENT },
- { type: mutationTypes.RECEIVE_CONTENT_SUCCESS, payload },
- ],
- [],
- );
-
- expect(loadSourceContent).toHaveBeenCalledWith({ projectId, sourcePath });
- });
- });
-
- describe('on error', () => {
- const expectedMutations = [
- { type: mutationTypes.LOAD_CONTENT },
- { type: mutationTypes.RECEIVE_CONTENT_ERROR },
- ];
-
- beforeEach(() => {
- loadSourceContent.mockRejectedValueOnce();
- });
-
- it('commits receiveContentError', () => {
- testAction(actions.loadContent, null, state, expectedMutations);
- });
-
- it('displays flash communicating error', () => {
- return testAction(actions.loadContent, null, state, expectedMutations).then(() => {
- expect(createFlash).toHaveBeenCalledWith(
- 'An error ocurred while loading your content. Please try again.',
- );
- });
- });
- });
- });
-
- describe('setContent', () => {
- it('commits setContent mutation', () => {
- testAction(actions.setContent, content, state, [
- {
- type: mutationTypes.SET_CONTENT,
- payload: content,
- },
- ]);
- });
- });
-
- describe('submitChanges', () => {
- describe('on success', () => {
- beforeEach(() => {
- state = createState({
- projectId,
- content,
- username,
- sourcePath,
- });
- submitContentChanges.mockResolvedValueOnce(savedContentMeta);
- });
-
- it('commits submitChangesSuccess mutation', () => {
- testAction(
- actions.submitChanges,
- null,
- state,
- [
- { type: mutationTypes.SUBMIT_CHANGES },
- { type: mutationTypes.SUBMIT_CHANGES_SUCCESS, payload: savedContentMeta },
- ],
- [],
- );
-
- expect(submitContentChanges).toHaveBeenCalledWith({
- username,
- projectId,
- content,
- sourcePath,
- });
- });
- });
-
- describe('on error', () => {
- const error = new Error(submitChangesError);
- const expectedMutations = [
- { type: mutationTypes.SUBMIT_CHANGES },
- { type: mutationTypes.SUBMIT_CHANGES_ERROR, payload: error.message },
- ];
-
- beforeEach(() => {
- submitContentChanges.mockRejectedValueOnce(error);
- });
-
- it('dispatches receiveContentError', () => {
- testAction(actions.submitChanges, null, state, expectedMutations);
- });
- });
- });
-
- describe('dismissSubmitChangesError', () => {
- it('commits dismissSubmitChangesError', () => {
- testAction(actions.dismissSubmitChangesError, null, state, [
- {
- type: mutationTypes.DISMISS_SUBMIT_CHANGES_ERROR,
- },
- ]);
- });
- });
-});
diff --git a/spec/frontend/static_site_editor/store/getters_spec.js b/spec/frontend/static_site_editor/store/getters_spec.js
deleted file mode 100644
index 5793e344784..00000000000
--- a/spec/frontend/static_site_editor/store/getters_spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import createState from '~/static_site_editor/store/state';
-import { contentChanged } from '~/static_site_editor/store/getters';
-import { sourceContent as content } from '../mock_data';
-
-describe('Static Site Editor Store getters', () => {
- describe('contentChanged', () => {
- it('returns true when content and originalContent are different', () => {
- const state = createState({ content, originalContent: 'something else' });
-
- expect(contentChanged(state)).toBe(true);
- });
-
- it('returns false when content and originalContent are the same', () => {
- const state = createState({ content, originalContent: content });
-
- expect(contentChanged(state)).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/static_site_editor/store/mutations_spec.js b/spec/frontend/static_site_editor/store/mutations_spec.js
deleted file mode 100644
index 2441f317d90..00000000000
--- a/spec/frontend/static_site_editor/store/mutations_spec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import createState from '~/static_site_editor/store/state';
-import mutations from '~/static_site_editor/store/mutations';
-import * as types from '~/static_site_editor/store/mutation_types';
-import {
- sourceContentTitle as title,
- sourceContent as content,
- savedContentMeta,
- submitChangesError,
-} from '../mock_data';
-
-describe('Static Site Editor Store mutations', () => {
- let state;
- const contentLoadedPayload = { title, content };
-
- beforeEach(() => {
- state = createState();
- });
-
- it.each`
- mutation | stateProperty | payload | expectedValue
- ${types.LOAD_CONTENT} | ${'isLoadingContent'} | ${undefined} | ${true}
- ${types.RECEIVE_CONTENT_SUCCESS} | ${'isLoadingContent'} | ${contentLoadedPayload} | ${false}
- ${types.RECEIVE_CONTENT_SUCCESS} | ${'isContentLoaded'} | ${contentLoadedPayload} | ${true}
- ${types.RECEIVE_CONTENT_SUCCESS} | ${'title'} | ${contentLoadedPayload} | ${title}
- ${types.RECEIVE_CONTENT_SUCCESS} | ${'content'} | ${contentLoadedPayload} | ${content}
- ${types.RECEIVE_CONTENT_SUCCESS} | ${'originalContent'} | ${contentLoadedPayload} | ${content}
- ${types.RECEIVE_CONTENT_ERROR} | ${'isLoadingContent'} | ${undefined} | ${false}
- ${types.SET_CONTENT} | ${'content'} | ${content} | ${content}
- ${types.SUBMIT_CHANGES} | ${'isSavingChanges'} | ${undefined} | ${true}
- ${types.SUBMIT_CHANGES_SUCCESS} | ${'savedContentMeta'} | ${savedContentMeta} | ${savedContentMeta}
- ${types.SUBMIT_CHANGES_SUCCESS} | ${'isSavingChanges'} | ${savedContentMeta} | ${false}
- ${types.SUBMIT_CHANGES_ERROR} | ${'isSavingChanges'} | ${undefined} | ${false}
- ${types.SUBMIT_CHANGES_ERROR} | ${'submitChangesError'} | ${submitChangesError} | ${submitChangesError}
- ${types.DISMISS_SUBMIT_CHANGES_ERROR} | ${'submitChangesError'} | ${undefined} | ${''}
- `(
- '$mutation sets $stateProperty to $expectedValue',
- ({ mutation, stateProperty, payload, expectedValue }) => {
- mutations[mutation](state, payload);
- expect(state[stateProperty]).toBe(expectedValue);
- },
- );
-
- it(`${types.SUBMIT_CHANGES_SUCCESS} sets originalContent to content current value`, () => {
- const editedContent = `${content} plus something else`;
-
- state = createState({
- originalContent: content,
- content: editedContent,
- });
- mutations[types.SUBMIT_CHANGES_SUCCESS](state);
-
- expect(state.originalContent).toBe(state.content);
- });
-});