Commit 3611c87f authored by Enrique Alcantara's avatar Enrique Alcantara

Remove Vuex from Static Site Editor

After adopting VueApollo, we can remove
Vuex code from the Static Site Editor
parent e6442cb3
import Vue from 'vue'; import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import App from './components/app.vue'; import App from './components/app.vue';
import createStore from './store';
import createRouter from './router'; import createRouter from './router';
import createApolloProvider from './graphql'; import createApolloProvider from './graphql';
const initStaticSiteEditor = el => { const initStaticSiteEditor = el => {
const { const { isSupportedContent, path: sourcePath, baseUrl, namespace, project } = el.dataset;
isSupportedContent,
projectId,
path: sourcePath,
baseUrl,
namespace,
project,
} = el.dataset;
const { current_username: username } = window.gon; const { current_username: username } = window.gon;
const returnUrl = el.dataset.returnUrl || null; const returnUrl = el.dataset.returnUrl || null;
const store = createStore({
initialState: {
isSupportedContent: parseBoolean(isSupportedContent),
projectId,
returnUrl,
sourcePath,
username,
},
});
const router = createRouter(baseUrl); const router = createRouter(baseUrl);
const apolloProvider = createApolloProvider({ const apolloProvider = createApolloProvider({
isSupportedContent: parseBoolean(isSupportedContent), isSupportedContent: parseBoolean(isSupportedContent),
...@@ -37,7 +20,6 @@ const initStaticSiteEditor = el => { ...@@ -37,7 +20,6 @@ const initStaticSiteEditor = el => {
return new Vue({ return new Vue({
el, el,
store,
router, router,
apolloProvider, apolloProvider,
components: { components: {
......
import createFlash from '~/flash';
import * as mutationTypes from './mutation_types';
import loadSourceContent from '~/static_site_editor/services/load_source_content';
import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
import { LOAD_CONTENT_ERROR } from '../constants';
export const loadContent = ({ commit, state: { sourcePath, projectId } }) => {
commit(mutationTypes.LOAD_CONTENT);
return loadSourceContent({ sourcePath, projectId })
.then(data => commit(mutationTypes.RECEIVE_CONTENT_SUCCESS, data))
.catch(() => {
commit(mutationTypes.RECEIVE_CONTENT_ERROR);
createFlash(LOAD_CONTENT_ERROR);
});
};
export const setContent = ({ commit }, content) => {
commit(mutationTypes.SET_CONTENT, content);
};
export const submitChanges = ({ state: { projectId, content, sourcePath, username }, commit }) => {
commit(mutationTypes.SUBMIT_CHANGES);
return submitContentChanges({ content, projectId, sourcePath, username })
.then(data => commit(mutationTypes.SUBMIT_CHANGES_SUCCESS, data))
.catch(error => {
commit(mutationTypes.SUBMIT_CHANGES_ERROR, error.message);
});
};
export const dismissSubmitChangesError = ({ commit }) => {
commit(mutationTypes.DISMISS_SUBMIT_CHANGES_ERROR);
};
export default () => {};
// eslint-disable-next-line import/prefer-default-export
export const contentChanged = ({ originalContent, content }) => originalContent !== content;
import Vuex from 'vuex';
import Vue from 'vue';
import createState from './state';
import * as getters from './getters';
import * as actions from './actions';
import mutations from './mutations';
Vue.use(Vuex);
const createStore = ({ initialState } = {}) => {
return new Vuex.Store({
state: createState(initialState),
getters,
actions,
mutations,
});
};
export default createStore;
export const LOAD_CONTENT = 'loadContent';
export const RECEIVE_CONTENT_SUCCESS = 'receiveContentSuccess';
export const RECEIVE_CONTENT_ERROR = 'receiveContentError';
export const SET_CONTENT = 'setContent';
export const SUBMIT_CHANGES = 'submitChanges';
export const SUBMIT_CHANGES_SUCCESS = 'submitChangesSuccess';
export const SUBMIT_CHANGES_ERROR = 'submitChangesError';
export const DISMISS_SUBMIT_CHANGES_ERROR = 'dismissSubmitChangesError';
import * as types from './mutation_types';
export default {
[types.LOAD_CONTENT](state) {
state.isLoadingContent = true;
},
[types.RECEIVE_CONTENT_SUCCESS](state, { title, content }) {
state.isLoadingContent = false;
state.isContentLoaded = true;
state.title = title;
state.content = content;
state.originalContent = content;
},
[types.RECEIVE_CONTENT_ERROR](state) {
state.isLoadingContent = false;
},
[types.SET_CONTENT](state, content) {
state.content = content;
},
[types.SUBMIT_CHANGES](state) {
state.isSavingChanges = true;
state.submitChangesError = '';
},
[types.SUBMIT_CHANGES_SUCCESS](state, meta) {
state.savedContentMeta = meta;
state.isSavingChanges = false;
state.originalContent = state.content;
},
[types.SUBMIT_CHANGES_ERROR](state, error) {
state.submitChangesError = error;
state.isSavingChanges = false;
},
[types.DISMISS_SUBMIT_CHANGES_ERROR](state) {
state.submitChangesError = '';
},
};
const createState = (initialState = {}) => ({
username: null,
projectId: null,
returnUrl: null,
sourcePath: null,
isLoadingContent: false,
isSavingChanges: false,
isContentLoaded: false,
originalContent: '',
content: '',
title: '',
submitChangesError: '',
savedContentMeta: null,
...initialState,
});
export default createState;
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,
},
]);
});
});
});
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);
});
});
});
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);
});
});
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