Commit 69ec8c2f authored by Enrique Alcantara's avatar Enrique Alcantara

Replace Vuex with VueApollo for submitting changes

Use VueApollo instead of Vuex when submitting
changes in the Static Site Editor
parent 69bdc477
<script>
import { mapState, mapActions } from 'vuex';
import SkeletonLoader from '../components/skeleton_loader.vue';
import EditArea from '../components/edit_area.vue';
import InvalidContentMessage from '../components/invalid_content_message.vue';
import SubmitChangesError from '../components/submit_changes_error.vue';
import { SUCCESS_ROUTE } from '../router/constants';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
import submitContentChangesMutation from '../graphql/mutations/submit_content_changes.mutation.graphql';
import createFlash from '~/flash';
import { LOAD_CONTENT_ERROR } from '../constants';
import { SUCCESS_ROUTE } from '../router/constants';
export default {
components: {
......@@ -44,8 +44,14 @@ export default {
},
},
},
data() {
return {
content: null,
submitChangesError: null,
isSavingChanges: false,
};
},
computed: {
...mapState(['isSavingChanges', 'submitChangesError']),
isLoadingContent() {
return this.$apollo.queries.sourceContent.loading;
},
......@@ -54,11 +60,35 @@ export default {
},
},
methods: {
...mapActions(['setContent', 'submitChanges', 'dismissSubmitChangesError']),
onDismissError() {
this.submitChangesError = null;
},
onSubmit({ content }) {
this.setContent(content);
this.content = content;
this.submitChanges();
},
submitChanges() {
this.isSavingChanges = true;
return this.submitChanges().then(() => this.$router.push(SUCCESS_ROUTE));
this.$apollo
.mutate({
mutation: submitContentChangesMutation,
variables: {
project: this.appData.project,
username: this.appData.username,
sourcePath: this.appData.sourcePath,
content: this.content,
},
})
.then(() => {
this.$router.push(SUCCESS_ROUTE);
})
.catch(e => {
this.submitChangesError = e.message;
})
.finally(() => {
this.isSavingChanges = false;
});
},
},
};
......@@ -71,7 +101,7 @@ export default {
v-if="submitChangesError"
:error="submitChangesError"
@retry="submitChanges"
@dismiss="dismissSubmitChangesError"
@dismiss="onDismissError"
/>
<edit-area
v-if="isContentLoaded"
......
<script>
import { mapState } from 'vuex';
import savedContentMetaQuery from '../graphql/queries/saved_content_meta.query.graphql';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
import SavedChangesMessage from '../components/saved_changes_message.vue';
import { HOME_ROUTE } from '../router/constants';
......@@ -7,8 +8,13 @@ export default {
components: {
SavedChangesMessage,
},
computed: {
...mapState(['savedContentMeta', 'returnUrl']),
apollo: {
savedContentMeta: {
query: savedContentMetaQuery,
},
appData: {
query: appDataQuery,
},
},
created() {
if (!this.savedContentMeta) {
......@@ -23,7 +29,7 @@ export default {
:branch="savedContentMeta.branch"
:commit="savedContentMeta.commit"
:merge-request="savedContentMeta.mergeRequest"
:return-url="returnUrl"
:return-url="appData.returnUrl"
/>
</div>
</template>
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import createState from '~/static_site_editor/store/state';
import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants';
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';
......@@ -24,32 +28,11 @@ describe('static_site_editor/pages/home', () => {
let store;
let $apollo;
let $router;
let setContentActionMock;
let submitChangesActionMock;
let dismissSubmitChangesErrorActionMock;
const buildStore = ({ initialState, getters } = {}) => {
setContentActionMock = jest.fn();
submitChangesActionMock = jest.fn();
dismissSubmitChangesErrorActionMock = jest.fn();
store = new Vuex.Store({
state: createState({
...initialState,
}),
getters: {
contentChanged: () => false,
...getters,
},
actions: {
setContent: setContentActionMock,
submitChanges: submitChangesActionMock,
dismissSubmitChangesError: dismissSubmitChangesErrorActionMock,
},
});
};
let mutateMock;
const buildApollo = (queries = {}) => {
mutateMock = jest.fn();
$apollo = {
queries: {
sourceContent: {
......@@ -57,6 +40,7 @@ describe('static_site_editor/pages/home', () => {
},
...queries,
},
mutate: mutateMock,
};
};
......@@ -76,7 +60,8 @@ describe('static_site_editor/pages/home', () => {
},
data() {
return {
appData: { isSupportedContent: true, returnUrl },
appData: { isSupportedContent: true, returnUrl, project, username, sourcePath },
sourceContent: { title, content },
...data,
};
},
......@@ -91,7 +76,6 @@ describe('static_site_editor/pages/home', () => {
beforeEach(() => {
buildApollo();
buildRouter();
buildStore();
});
afterEach(() => {
......@@ -102,8 +86,7 @@ describe('static_site_editor/pages/home', () => {
describe('when content is loaded', () => {
beforeEach(() => {
buildStore({ initialState: { isSavingChanges: true } });
buildWrapper({ sourceContent: { title, content } });
buildWrapper();
});
it('renders edit area', () => {
......@@ -115,7 +98,7 @@ describe('static_site_editor/pages/home', () => {
title,
content,
returnUrl,
savingChanges: true,
savingChanges: false,
});
});
});
......@@ -148,30 +131,44 @@ describe('static_site_editor/pages/home', () => {
expect(findSkeletonLoader().exists()).toBe(false);
});
describe('when submitting changes fail', () => {
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 not supported', () => {
buildWrapper({ appData: { isSupportedContent: true } });
expect(findInvalidContentMessage().exists()).toBe(false);
});
describe('when submitting changes fails', () => {
beforeEach(() => {
buildStore({
initialState: {
submitChangesError,
},
});
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('dispatches submitChanges action when error message emits retry event', () => {
it('retries submitting changes when retry button is clicked', () => {
findSubmitChangesError().vm.$emit('retry');
expect(submitChangesActionMock).toHaveBeenCalled();
expect(mutateMock).toHaveBeenCalled();
});
it('dispatches dismissSubmitChangesError action when error message emits dismiss event', () => {
it('hides submit changes error message when dismiss button is clicked', () => {
findSubmitChangesError().vm.$emit('dismiss');
expect(dismissSubmitChangesErrorActionMock).toHaveBeenCalled();
return wrapper.vm.$nextTick().then(() => {
expect(findSubmitChangesError().exists()).toBe(false);
});
});
});
......@@ -181,34 +178,32 @@ describe('static_site_editor/pages/home', () => {
expect(findSubmitChangesError().exists()).toBe(false);
});
it('displays invalid content message when content is not supported', () => {
buildWrapper({ appData: { isSupportedContent: false } });
expect(findInvalidContentMessage().exists()).toBe(true);
});
describe('when edit area emits submit event', () => {
describe('when submitting changes succeeds', () => {
const newContent = `new ${content}`;
beforeEach(() => {
submitChangesActionMock.mockResolvedValueOnce();
mutateMock.mockResolvedValueOnce({ data: { submitContentChanges: savedContentMeta } });
buildWrapper({ sourceContent: { title, content } });
buildWrapper();
findEditArea().vm.$emit('submit', { content: newContent });
});
it('dispatches setContent property', () => {
expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), newContent, undefined);
return wrapper.vm.$nextTick();
});
it('dispatches submitChanges action', () => {
expect(submitChangesActionMock).toHaveBeenCalled();
it('dispatches submitContentChanges mutation', () => {
expect(mutateMock).toHaveBeenCalledWith({
mutation: submitContentChangesMutation,
variables: {
content: newContent,
project,
sourcePath,
username,
},
});
});
it('pushes success route when submitting changes succeeds', () => {
return wrapper.vm.$nextTick().then(() => {
expect($router.push).toHaveBeenCalledWith(SUCCESS_ROUTE);
});
it('transitions to the SUCCESS route', () => {
expect($router.push).toHaveBeenCalledWith(SUCCESS_ROUTE);
});
});
});
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import createState from '~/static_site_editor/store/state';
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';
......@@ -21,23 +20,22 @@ describe('static_site_editor/pages/success', () => {
};
};
const buildStore = (initialState = {}) => {
store = new Vuex.Store({
state: createState({
savedContentMeta,
returnUrl,
...initialState,
}),
});
};
const buildWrapper = () => {
const buildWrapper = (data = {}) => {
wrapper = shallowMount(Success, {
localVue,
store,
mocks: {
$router: router,
},
data() {
return {
savedContentMeta,
appData: {
returnUrl,
},
...data,
};
},
});
};
......@@ -45,7 +43,6 @@ describe('static_site_editor/pages/success', () => {
beforeEach(() => {
buildRouter();
buildStore();
});
afterEach(() => {
......@@ -74,8 +71,7 @@ describe('static_site_editor/pages/success', () => {
});
it('redirects to the HOME route when content has not been submitted', () => {
buildStore({ savedContentMeta: null });
buildWrapper();
buildWrapper({ savedContentMeta: null });
expect(router.push).toHaveBeenCalledWith(HOME_ROUTE);
});
......
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