Commit 9c00dafb authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera Committed by Martin Wortschack

Move store call to in-component router guards

- move to components
- remove store singleton usage
parent 52952037
...@@ -19,7 +19,7 @@ export default () => { ...@@ -19,7 +19,7 @@ export default () => {
const { endpoint } = el.dataset; const { endpoint } = el.dataset;
const store = createStore(); const store = createStore();
const router = createRouter(endpoint, store); const router = createRouter(endpoint);
store.dispatch('setInitialState', el.dataset); store.dispatch('setInitialState', el.dataset);
const attachMainComponent = () => const attachMainComponent = () =>
......
...@@ -157,6 +157,9 @@ export default { ...@@ -157,6 +157,9 @@ export default {
return config; return config;
}, },
}, },
mounted() {
this.requestTagsList({ params: this.$route.params.id });
},
methods: { methods: {
...mapActions(['requestTagsList', 'requestDeleteTag', 'requestDeleteTags']), ...mapActions(['requestTagsList', 'requestDeleteTag', 'requestDeleteTags']),
setModalDescription(itemIndex = -1) { setModalDescription(itemIndex = -1) {
......
...@@ -103,8 +103,16 @@ export default { ...@@ -103,8 +103,16 @@ export default {
: DELETE_IMAGE_ERROR_MESSAGE; : DELETE_IMAGE_ERROR_MESSAGE;
}, },
}, },
mounted() {
this.loadImageList(this.$route.name);
},
methods: { methods: {
...mapActions(['requestImagesList', 'requestDeleteImage']), ...mapActions(['requestImagesList', 'requestDeleteImage']),
loadImageList(fromName) {
if (!fromName || !this.images?.length) {
this.requestImagesList();
}
},
deleteImage(item) { deleteImage(item) {
this.track('click_button'); this.track('click_button');
this.itemToDelete = item; this.itemToDelete = item;
......
...@@ -7,7 +7,7 @@ import { decodeAndParse } from './utils'; ...@@ -7,7 +7,7 @@ import { decodeAndParse } from './utils';
Vue.use(VueRouter); Vue.use(VueRouter);
export default function createRouter(base, store) { export default function createRouter(base) {
const router = new VueRouter({ const router = new VueRouter({
base, base,
mode: 'history', mode: 'history',
...@@ -20,12 +20,6 @@ export default function createRouter(base, store) { ...@@ -20,12 +20,6 @@ export default function createRouter(base, store) {
nameGenerator: () => s__('ContainerRegistry|Container Registry'), nameGenerator: () => s__('ContainerRegistry|Container Registry'),
root: true, root: true,
}, },
beforeEnter: (to, from, next) => {
if (!from.name || !store.state.images?.length) {
store.dispatch('requestImagesList');
}
next();
},
}, },
{ {
name: 'details', name: 'details',
...@@ -34,10 +28,6 @@ export default function createRouter(base, store) { ...@@ -34,10 +28,6 @@ export default function createRouter(base, store) {
meta: { meta: {
nameGenerator: route => decodeAndParse(route.params.id).name, nameGenerator: route => decodeAndParse(route.params.id).name,
}, },
beforeEnter: (to, from, next) => {
store.dispatch('requestTagsList', { params: to.params.id });
next();
},
}, },
], ],
}); });
......
...@@ -15,4 +15,5 @@ export const createStore = () => ...@@ -15,4 +15,5 @@ export const createStore = () =>
mutations, mutations,
}); });
// Deprecated and to be removed
export default createStore(); export default createStore();
...@@ -4,7 +4,12 @@ import Tracking from '~/tracking'; ...@@ -4,7 +4,12 @@ import Tracking from '~/tracking';
import stubChildren from 'helpers/stub_children'; import stubChildren from 'helpers/stub_children';
import component from '~/registry/explorer/pages/details.vue'; import component from '~/registry/explorer/pages/details.vue';
import { createStore } from '~/registry/explorer/stores/'; import { createStore } from '~/registry/explorer/stores/';
import { SET_MAIN_LOADING, SET_INITIAL_STATE } from '~/registry/explorer/stores/mutation_types/'; import {
SET_MAIN_LOADING,
SET_INITIAL_STATE,
SET_TAGS_LIST_SUCCESS,
SET_TAGS_PAGINATION,
} from '~/registry/explorer/stores/mutation_types/';
import { import {
DELETE_TAG_SUCCESS_MESSAGE, DELETE_TAG_SUCCESS_MESSAGE,
DELETE_TAG_ERROR_MESSAGE, DELETE_TAG_ERROR_MESSAGE,
...@@ -60,7 +65,9 @@ describe('Details Page', () => { ...@@ -60,7 +65,9 @@ describe('Details Page', () => {
beforeEach(() => { beforeEach(() => {
store = createStore(); store = createStore();
dispatchSpy = jest.spyOn(store, 'dispatch'); dispatchSpy = jest.spyOn(store, 'dispatch');
store.dispatch('receiveTagsListSuccess', tagsListResponse); dispatchSpy.mockResolvedValue();
store.commit(SET_TAGS_LIST_SUCCESS, tagsListResponse.data);
store.commit(SET_TAGS_PAGINATION, tagsListResponse.headers);
jest.spyOn(Tracking, 'event'); jest.spyOn(Tracking, 'event');
}); });
......
import VueRouter from 'vue-router'; import { shallowMount } from '@vue/test-utils';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlPagination, GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui'; import { GlPagination, GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import component from '~/registry/explorer/pages/list.vue'; import component from '~/registry/explorer/pages/list.vue';
...@@ -7,22 +6,25 @@ import QuickstartDropdown from '~/registry/explorer/components/quickstart_dropdo ...@@ -7,22 +6,25 @@ import QuickstartDropdown from '~/registry/explorer/components/quickstart_dropdo
import GroupEmptyState from '~/registry/explorer/components/group_empty_state.vue'; import GroupEmptyState from '~/registry/explorer/components/group_empty_state.vue';
import ProjectEmptyState from '~/registry/explorer/components/project_empty_state.vue'; import ProjectEmptyState from '~/registry/explorer/components/project_empty_state.vue';
import ProjectPolicyAlert from '~/registry/explorer/components/project_policy_alert.vue'; import ProjectPolicyAlert from '~/registry/explorer/components/project_policy_alert.vue';
import store from '~/registry/explorer/stores/'; import { createStore } from '~/registry/explorer/stores/';
import { SET_MAIN_LOADING } from '~/registry/explorer/stores/mutation_types/'; import {
SET_MAIN_LOADING,
SET_IMAGES_LIST_SUCCESS,
SET_PAGINATION,
SET_INITIAL_STATE,
} from '~/registry/explorer/stores/mutation_types/';
import { import {
DELETE_IMAGE_SUCCESS_MESSAGE, DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE, DELETE_IMAGE_ERROR_MESSAGE,
} from '~/registry/explorer/constants'; } from '~/registry/explorer/constants';
import { imagesListResponse } from '../mock_data'; import { imagesListResponse } from '../mock_data';
import { GlModal, GlEmptyState } from '../stubs'; import { GlModal, GlEmptyState, RouterLink } from '../stubs';
import { $toast } from '../../shared/mocks'; import { $toast } from '../../shared/mocks';
const localVue = createLocalVue();
localVue.use(VueRouter);
describe('List Page', () => { describe('List Page', () => {
let wrapper; let wrapper;
let dispatchSpy; let dispatchSpy;
let store;
const findDeleteBtn = () => wrapper.find({ ref: 'deleteImageButton' }); const findDeleteBtn = () => wrapper.find({ ref: 'deleteImageButton' });
const findDeleteModal = () => wrapper.find(GlModal); const findDeleteModal = () => wrapper.find(GlModal);
...@@ -39,21 +41,31 @@ describe('List Page', () => { ...@@ -39,21 +41,31 @@ describe('List Page', () => {
const findProjectPolicyAlert = () => wrapper.find(ProjectPolicyAlert); const findProjectPolicyAlert = () => wrapper.find(ProjectPolicyAlert);
const findDeleteAlert = () => wrapper.find(GlAlert); const findDeleteAlert = () => wrapper.find(GlAlert);
beforeEach(() => { const mountComponent = ({ mocks } = {}) => {
wrapper = shallowMount(component, { wrapper = shallowMount(component, {
localVue,
store, store,
stubs: { stubs: {
GlModal, GlModal,
GlEmptyState, GlEmptyState,
GlSprintf, GlSprintf,
RouterLink,
}, },
mocks: { mocks: {
$toast, $toast,
$route: {
name: 'foo',
},
...mocks,
}, },
}); });
};
beforeEach(() => {
store = createStore();
dispatchSpy = jest.spyOn(store, 'dispatch'); dispatchSpy = jest.spyOn(store, 'dispatch');
store.dispatch('receiveImagesListSuccess', imagesListResponse); dispatchSpy.mockResolvedValue();
store.commit(SET_IMAGES_LIST_SUCCESS, imagesListResponse.data);
store.commit(SET_PAGINATION, imagesListResponse.headers);
}); });
afterEach(() => { afterEach(() => {
...@@ -61,17 +73,38 @@ describe('List Page', () => { ...@@ -61,17 +73,38 @@ describe('List Page', () => {
}); });
describe('Expiration policy notification', () => { describe('Expiration policy notification', () => {
beforeEach(() => {
mountComponent();
});
it('shows up on project page', () => { it('shows up on project page', () => {
expect(findProjectPolicyAlert().exists()).toBe(true); expect(findProjectPolicyAlert().exists()).toBe(true);
}); });
it('does show up on group page', () => { it('does show up on group page', () => {
store.dispatch('setInitialState', { isGroupPage: true }); store.commit(SET_INITIAL_STATE, { isGroupPage: true });
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(findProjectPolicyAlert().exists()).toBe(false); expect(findProjectPolicyAlert().exists()).toBe(false);
}); });
}); });
}); });
describe('API calls', () => {
it.each`
imageList | name | called
${[]} | ${'foo'} | ${['requestImagesList']}
${imagesListResponse.data} | ${undefined} | ${['requestImagesList']}
${imagesListResponse.data} | ${'foo'} | ${undefined}
`(
'with images equal $imageList and name $name dispatch calls $called',
({ imageList, name, called }) => {
store.commit(SET_IMAGES_LIST_SUCCESS, imageList);
dispatchSpy.mockClear();
mountComponent({ mocks: { $route: { name } } });
expect(dispatchSpy.mock.calls[0]).toEqual(called);
},
);
});
describe('connection error', () => { describe('connection error', () => {
const config = { const config = {
characterError: true, characterError: true,
...@@ -79,12 +112,13 @@ describe('List Page', () => { ...@@ -79,12 +112,13 @@ describe('List Page', () => {
helpPagePath: 'bar', helpPagePath: 'bar',
}; };
beforeAll(() => { beforeEach(() => {
store.dispatch('setInitialState', config); store.commit(SET_INITIAL_STATE, config);
mountComponent();
}); });
afterAll(() => { afterEach(() => {
store.dispatch('setInitialState', {}); store.commit(SET_INITIAL_STATE, {});
}); });
it('should show an empty state', () => { it('should show an empty state', () => {
...@@ -106,9 +140,12 @@ describe('List Page', () => { ...@@ -106,9 +140,12 @@ describe('List Page', () => {
}); });
describe('isLoading is true', () => { describe('isLoading is true', () => {
beforeAll(() => store.commit(SET_MAIN_LOADING, true)); beforeEach(() => {
store.commit(SET_MAIN_LOADING, true);
mountComponent();
});
afterAll(() => store.commit(SET_MAIN_LOADING, false)); afterEach(() => store.commit(SET_MAIN_LOADING, false));
it('shows the skeleton loader', () => { it('shows the skeleton loader', () => {
expect(findSkeletonLoader().exists()).toBe(true); expect(findSkeletonLoader().exists()).toBe(true);
...@@ -125,7 +162,8 @@ describe('List Page', () => { ...@@ -125,7 +162,8 @@ describe('List Page', () => {
describe('list is empty', () => { describe('list is empty', () => {
beforeEach(() => { beforeEach(() => {
store.dispatch('receiveImagesListSuccess', { data: [] }); store.commit(SET_IMAGES_LIST_SUCCESS, []);
mountComponent();
}); });
it('quick start is not visible', () => { it('quick start is not visible', () => {
...@@ -137,12 +175,13 @@ describe('List Page', () => { ...@@ -137,12 +175,13 @@ describe('List Page', () => {
}); });
describe('is group page is true', () => { describe('is group page is true', () => {
beforeAll(() => { beforeEach(() => {
store.dispatch('setInitialState', { isGroupPage: true }); store.commit(SET_INITIAL_STATE, { isGroupPage: true });
mountComponent();
}); });
afterAll(() => { afterEach(() => {
store.dispatch('setInitialState', { isGroupPage: undefined }); store.commit(SET_INITIAL_STATE, { isGroupPage: undefined });
}); });
it('group empty state is visible', () => { it('group empty state is visible', () => {
...@@ -156,6 +195,10 @@ describe('List Page', () => { ...@@ -156,6 +195,10 @@ describe('List Page', () => {
}); });
describe('list is not empty', () => { describe('list is not empty', () => {
beforeEach(() => {
mountComponent();
});
it('quick start is visible', () => { it('quick start is visible', () => {
expect(findQuickStartDropdown().exists()).toBe(true); expect(findQuickStartDropdown().exists()).toBe(true);
}); });
......
...@@ -9,3 +9,8 @@ export const GlEmptyState = { ...@@ -9,3 +9,8 @@ export const GlEmptyState = {
template: '<div><slot name="description"></slot></div>', template: '<div><slot name="description"></slot></div>',
name: 'GlEmptyStateSTub', name: 'GlEmptyStateSTub',
}; };
export const RouterLink = {
template: `<div><slot></slot></div>`,
props: ['to'],
};
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