diff options
8 files changed, 103 insertions, 134 deletions
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue index 6233fb169e9..ab568da1fcb 100644 --- a/app/assets/javascripts/registry/components/app.vue +++ b/app/assets/javascripts/registry/components/app.vue @@ -1,7 +1,7 @@ <script> import { mapGetters, mapActions } from 'vuex'; import { GlLoadingIcon } from '@gitlab/ui'; -import Flash from '../../flash'; +import createFlash from '../../flash'; import store from '../stores'; import collapsibleContainer from './collapsible_container.vue'; import { errorMessages, errorMessagesTypes } from '../constants'; @@ -26,7 +26,7 @@ export default { this.setMainEndpoint(this.endpoint); }, mounted() { - this.fetchRepos().catch(() => Flash(errorMessages[errorMessagesTypes.FETCH_REPOS])); + this.fetchRepos().catch(() => createFlash(errorMessages[errorMessagesTypes.FETCH_REPOS])); }, methods: { ...mapActions(['setMainEndpoint', 'fetchRepos']), diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue index 6514c05a9c7..72f0aceb534 100644 --- a/app/assets/javascripts/registry/components/collapsible_container.vue +++ b/app/assets/javascripts/registry/components/collapsible_container.vue @@ -1,18 +1,18 @@ <script> import { mapActions } from 'vuex'; import { GlLoadingIcon } from '@gitlab/ui'; -import Flash from '../../flash'; -import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; +import createFlash from '../../flash'; +import ClipboardButton from '../../vue_shared/components/clipboard_button.vue'; import tooltip from '../../vue_shared/directives/tooltip'; -import tableRegistry from './table_registry.vue'; +import TableRegistry from './table_registry.vue'; import { errorMessages, errorMessagesTypes } from '../constants'; import { __ } from '../../locale'; export default { name: 'CollapsibeContainerRegisty', components: { - clipboardButton, - tableRegistry, + ClipboardButton, + TableRegistry, GlLoadingIcon, }, directives: { @@ -31,7 +31,6 @@ export default { }, methods: { ...mapActions(['fetchRepos', 'fetchList', 'deleteRepo']), - toggleRepo() { this.isOpen = !this.isOpen; @@ -41,18 +40,16 @@ export default { ); } }, - handleDeleteRepository() { this.deleteRepo(this.repo) .then(() => { - Flash(__('This container registry has been scheduled for deletion.'), 'notice'); + createFlash(__('This container registry has been scheduled for deletion.'), 'notice'); this.fetchRepos(); }) .catch(() => this.showError(errorMessagesTypes.DELETE_REPO)); }, - showError(message) { - Flash(errorMessages[message]); + createFlash(errorMessages[message]); }, }, }; diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js index a78aa90b7b5..6d025aecaec 100644 --- a/app/assets/javascripts/registry/stores/actions.js +++ b/app/assets/javascripts/registry/stores/actions.js @@ -1,39 +1,34 @@ -import Vue from 'vue'; -import VueResource from 'vue-resource'; +import axios from '~/lib/utils/axios_utils'; import * as types from './mutation_types'; -Vue.use(VueResource); export const fetchRepos = ({ commit, state }) => { commit(types.TOGGLE_MAIN_LOADING); - return Vue.http + return axios .get(state.endpoint) - .then(res => res.json()) - .then(response => { + .then(({ data }) => { commit(types.TOGGLE_MAIN_LOADING); - commit(types.SET_REPOS_LIST, response); + commit(types.SET_REPOS_LIST, data); }); }; export const fetchList = ({ commit }, { repo, page }) => { commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); - return Vue.http.get(repo.tagsPath, { params: { page } }).then(response => { - const { headers } = response; + return axios.get(repo.tagsPath, { params: { page } }).then(response => { + const { headers, data } = response; - return response.json().then(resp => { - commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); - commit(types.SET_REGISTRY_LIST, { repo, resp, headers }); - }); + commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); + commit(types.SET_REGISTRY_LIST, { repo, resp: data, headers }); }); }; // eslint-disable-next-line no-unused-vars -export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath); +export const deleteRepo = ({ commit }, repo) => axios.delete(repo.destroyPath); // eslint-disable-next-line no-unused-vars -export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath); +export const deleteRegistry = ({ commit }, image) => axios.delete(image.destroyPath); export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data); export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING); diff --git a/app/assets/javascripts/registry/stores/index.js b/app/assets/javascripts/registry/stores/index.js index 78b67881210..1bb06bd6e81 100644 --- a/app/assets/javascripts/registry/stores/index.js +++ b/app/assets/javascripts/registry/stores/index.js @@ -3,36 +3,12 @@ import Vuex from 'vuex'; import * as actions from './actions'; import * as getters from './getters'; import mutations from './mutations'; +import createState from './state'; Vue.use(Vuex); export default new Vuex.Store({ - state: { - isLoading: false, - endpoint: '', // initial endpoint to fetch the repos list - /** - * Each object in `repos` has the following strucure: - * { - * name: String, - * isLoading: Boolean, - * tagsPath: String // endpoint to request the list - * destroyPath: String // endpoit to delete the repo - * list: Array // List of the registry images - * } - * - * Each registry image inside `list` has the following structure: - * { - * tag: String, - * revision: String - * shortRevision: String - * size: Number - * layers: Number - * createdAt: String - * destroyPath: String // endpoit to delete each image - * } - */ - repos: [], - }, + state: createState(), actions, getters, mutations, diff --git a/app/assets/javascripts/registry/stores/state.js b/app/assets/javascripts/registry/stores/state.js new file mode 100644 index 00000000000..feeac10cbe1 --- /dev/null +++ b/app/assets/javascripts/registry/stores/state.js @@ -0,0 +1,26 @@ +export default () => ({ + isLoading: false, + endpoint: '', // initial endpoint to fetch the repos list + /** + * Each object in `repos` has the following strucure: + * { + * name: String, + * isLoading: Boolean, + * tagsPath: String // endpoint to request the list + * destroyPath: String // endpoit to delete the repo + * list: Array // List of the registry images + * } + * + * Each registry image inside `list` has the following structure: + * { + * tag: String, + * revision: String + * shortRevision: String + * size: Number + * layers: Number + * createdAt: String + * destroyPath: String // endpoit to delete each image + * } + */ + repos: [], +}); diff --git a/spec/javascripts/registry/components/app_spec.js b/spec/javascripts/registry/components/app_spec.js index 92ff960277a..103a59e7094 100644 --- a/spec/javascripts/registry/components/app_spec.js +++ b/spec/javascripts/registry/components/app_spec.js @@ -1,37 +1,30 @@ -import _ from 'underscore'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import Vue from 'vue'; import registry from '~/registry/components/app.vue'; import mountComponent from 'spec/helpers/vue_mount_component_helper'; +import { TEST_HOST } from 'spec/test_constants'; import { reposServerResponse } from '../mock_data'; describe('Registry List', () => { + const Component = Vue.extend(registry); let vm; - let Component; + let mock; beforeEach(() => { - Component = Vue.extend(registry); + mock = new MockAdapter(axios); }); afterEach(() => { + mock.restore(); vm.$destroy(); }); describe('with data', () => { - const interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify(reposServerResponse), { - status: 200, - }), - ); - }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - vm = mountComponent(Component, { endpoint: 'foo' }); - }); + mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, reposServerResponse); - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` }); }); it('should render a list of repos', done => { @@ -76,21 +69,10 @@ describe('Registry List', () => { }); describe('without data', () => { - const interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify([]), { - status: 200, - }), - ); - }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - vm = mountComponent(Component, { endpoint: 'foo' }); - }); + mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, []); - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` }); }); it('should render empty message', done => { @@ -109,21 +91,10 @@ describe('Registry List', () => { }); describe('while loading data', () => { - const interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify(reposServerResponse), { - status: 200, - }), - ); - }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - vm = mountComponent(Component, { endpoint: 'foo' }); - }); + mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, []); - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` }); }); it('should render a loading spinner', done => { diff --git a/spec/javascripts/registry/components/collapsible_container_spec.js b/spec/javascripts/registry/components/collapsible_container_spec.js index 256a242f784..069139bc564 100644 --- a/spec/javascripts/registry/components/collapsible_container_spec.js +++ b/spec/javascripts/registry/components/collapsible_container_spec.js @@ -1,14 +1,22 @@ +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import Vue from 'vue'; import collapsibleComponent from '~/registry/components/collapsible_container.vue'; import store from '~/registry/stores'; -import { repoPropsData } from '../mock_data'; +import { repoPropsData, registryServerResponse } from '../mock_data'; describe('collapsible registry container', () => { let vm; - let Component; + let mock; + const Component = Vue.extend(collapsibleComponent); beforeEach(() => { - Component = Vue.extend(collapsibleComponent); + mock = new MockAdapter(axios); + + mock + .onGet(repoPropsData.tagsPath) + .replyOnce(200, registryServerResponse, {}); + vm = new Component({ store, propsData: { @@ -18,6 +26,7 @@ describe('collapsible registry container', () => { }); afterEach(() => { + mock.restore(); vm.$destroy(); }); @@ -29,10 +38,17 @@ describe('collapsible registry container', () => { ); }); - it('should be open when user clicks on closed repo', done => { + fit('should be open when user clicks on closed repo', done => { + + console.log(vm.repo, vm.$el) + vm.$el.querySelector('.js-toggle-repo').click(); + Vue.nextTick(() => { - expect(vm.$el.querySelector('.container-image-tags')).toBeDefined(); + + console.log('nextTick', vm.repo, vm.$el) + + expect(vm.$el.querySelector('.container-image-tags')).not.toBeNull(); expect(vm.$el.querySelector('.container-image-head i').className).toEqual( 'fa fa-chevron-up', ); @@ -58,7 +74,7 @@ describe('collapsible registry container', () => { describe('delete repo', () => { it('should be possible to delete a repo', () => { - expect(vm.$el.querySelector('.js-remove-repo')).toBeDefined(); + expect(vm.$el.querySelector('.js-remove-repo')).not.toBeNull(); }); }); }); diff --git a/spec/javascripts/registry/stores/actions_spec.js b/spec/javascripts/registry/stores/actions_spec.js index bc4c444655a..30114f5dca5 100644 --- a/spec/javascripts/registry/stores/actions_spec.js +++ b/spec/javascripts/registry/stores/actions_spec.js @@ -1,42 +1,36 @@ -import Vue from 'vue'; -import VueResource from 'vue-resource'; -import _ from 'underscore'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import * as actions from '~/registry/stores/actions'; import * as types from '~/registry/stores/mutation_types'; +import state from '~/registry/stores/state'; +import { TEST_HOST } from 'spec/test_constants'; import testAction from '../../helpers/vuex_action_helper'; import { - defaultState, reposServerResponse, registryServerResponse, parsedReposServerResponse, } from '../mock_data'; -Vue.use(VueResource); - describe('Actions Registry Store', () => { - let interceptor; let mockedState; + let mock; beforeEach(() => { - mockedState = defaultState; + mockedState = state(); + mockedState.endpoint = `${TEST_HOST}/endpoint.json`; + mock = new MockAdapter(axios); }); - describe('server requests', () => { - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); - }); + afterEach(() => { + mock.restore(); + }); + describe('server requests', () => { describe('fetchRepos', () => { beforeEach(() => { - interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify(reposServerResponse), { - status: 200, - }), - ); - }; - - Vue.http.interceptors.push(interceptor); + mock + .onGet(`${TEST_HOST}/endpoint.json`) + .replyOnce(200, reposServerResponse, {}) }); it('should set receveived repos', done => { @@ -56,23 +50,17 @@ describe('Actions Registry Store', () => { }); describe('fetchList', () => { + let repo; beforeEach(() => { - interceptor = (request, next) => { - next( - request.respondWith(JSON.stringify(registryServerResponse), { - status: 200, - }), - ); - }; + mockedState.repos = parsedReposServerResponse; + [, repo ] = mockedState.repos; - Vue.http.interceptors.push(interceptor); + mock + .onGet(repo.tagsPath) + .replyOnce(200, registryServerResponse, {}) }); it('should set received list', done => { - mockedState.repos = parsedReposServerResponse; - - const repo = mockedState.repos[1]; - testAction( actions.fetchList, { repo }, |