summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-09-20 19:03:53 +0100
committerFilipa Lacerda <filipa@gitlab.com>2017-09-20 19:03:53 +0100
commitee3cf5d6f3d5a3631fa7e94a242f2dfe9b38a935 (patch)
tree855937f227caaac46688dca63f82a18598be778b
parent6c63520ef5735e56749c77b495f8137a20942504 (diff)
downloadgitlab-ce-ee3cf5d6f3d5a3631fa7e94a242f2dfe9b38a935.tar.gz
[ci skip] Adds tests to vuex and collapsibe component
Formats dates Fixes clipboard button Simplifies HTML
-rw-r--r--app/assets/javascripts/registry/components/app.vue4
-rw-r--r--app/assets/javascripts/registry/components/collapsible_container.vue69
-rw-r--r--app/assets/javascripts/registry/index.js3
-rw-r--r--app/assets/javascripts/registry/stores/actions.js12
-rw-r--r--app/assets/javascripts/registry/stores/getters.js2
-rw-r--r--app/assets/javascripts/registry/stores/mutation_types.js5
-rw-r--r--app/assets/javascripts/registry/stores/mutations.js23
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue15
-rw-r--r--app/assets/stylesheets/pages/container_registry.scss4
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb28
-rw-r--r--app/views/projects/registry/repositories/index.html.haml9
-rw-r--r--spec/javascripts/helpers/vuex_action_helper.js (renamed from spec/javascripts/notes/stores/helpers.js)0
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js2
-rw-r--r--spec/javascripts/registry/components/app_spec.js0
-rw-r--r--spec/javascripts/registry/components/collapsible_container_spec.js112
-rw-r--r--spec/javascripts/registry/stores/actions_spec.js85
-rw-r--r--spec/javascripts/registry/stores/getters_spec.js43
-rw-r--r--spec/javascripts/registry/stores/mock_data.js91
-rw-r--r--spec/javascripts/registry/stores/mutations_spec.js57
19 files changed, 469 insertions, 95 deletions
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue
index 17a57ae248d..c4d66382850 100644
--- a/app/assets/javascripts/registry/components/app.vue
+++ b/app/assets/javascripts/registry/components/app.vue
@@ -33,7 +33,7 @@
'fetchList',
'deleteRepo',
'deleteRegistry',
- 'toggleIsLoading',
+ 'toggleLoading',
]),
fetchRegistryList(repo) {
@@ -49,7 +49,7 @@
deleteRepository(repo) {
this.deleteRepo(repo)
- .then(() => this.fetchRepo())
+ .then(() => this.fetchRepos())
.catch(() => this.showError(errorMessagesTypes.DELETE_REPO));
},
diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue
index 6be2aa60ebd..739e48b93f2 100644
--- a/app/assets/javascripts/registry/components/collapsible_container.vue
+++ b/app/assets/javascripts/registry/components/collapsible_container.vue
@@ -2,6 +2,7 @@
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
+ import timeagoMixin from '../../vue_shared/mixins/timeago';
export default {
name: 'collapsibeContainerRegisty',
@@ -15,6 +16,9 @@
clipboardButton,
loadingIcon,
},
+ mixins: [
+ timeagoMixin,
+ ],
directives: {
tooltip,
},
@@ -28,16 +32,18 @@
const pluralize = gl.text.pluralize('layer', item.layers);
return `${item.layers} ${pluralize}`;
},
+
toggleRepo() {
if (this.isOpen === false) {
- // consider not fetching data the second time it is toggled? :fry:
this.$emit('fetchRegistryList', this.repo);
}
this.isOpen = !this.isOpen;
},
+
handleDeleteRepository() {
this.$emit('deleteRepository', this.repo)
},
+
handleDeleteRegistry(registry) {
this.$emit('deleteRegistry', this.repo, registry);
},
@@ -51,7 +57,8 @@
class="container-image-head">
<a
role="button"
- @click="toggleRepo">
+ @click="toggleRepo"
+ class="js-toggle-repo">
<i
class="fa"
:class="{
@@ -63,13 +70,17 @@
{{repo.name}}
</a>
- <clipboard-button text="foo" title="bar" />
+ <clipboard-button
+ v-if="repo.location"
+ :text="__(`docker pull ${repo.location}`)"
+ :title="repo.location"
+ />
<div class="controls hidden-xs pull-right">
<button
v-if="repo.canDelete"
type="button"
- class="btn btn-remove"
+ class="js-remove-repo btn btn-remove"
:title="__('Remove repository')"
v-tooltip
@click="handleDeleteRepository">
@@ -90,14 +101,16 @@
v-else-if="!repo.isLoading && isOpen"
class="container-image-tags">
- <table class="table tags" v-if="repo.list.length">
+ <table
+ class="table tags"
+ v-if="repo.list.length">
<thead>
<tr>
<th>{{__("Tag")}}</th>
<th>{{__("Tag ID")}}</th>
<th>{{__("Size")}}</th>
<th>{{__("Created")}}</th>
- <th v-if="true"></th>
+ <th></th>
</tr>
</thead>
<tbody>
@@ -109,16 +122,16 @@
{{item.tag}}
<clipboard-button
- :title="item.tag"
- :text="item.tag"
+ v-if="item.location"
+ :title="item.location"
+ :text="__(`docker pull ${item.location}`)"
/>
</td>
<td>
<span
v-tooltip
:title="item.revision"
- data-placement="bottom"
- >
+ data-placement="bottom">
{{item.shortRevision}}
</span>
</td>
@@ -128,34 +141,38 @@
&middot;
{{layers(item)}}
</template>
- <div v-else class="light">
+ <div
+ v-else
+ class="light">
\-
</div>
</td>
<td>
<template v-if="item.createdAt">
- format {{item.createdAt}}
+ {{timeFormated(item.createdAt)}}
</template>
- <div v-else class="light">
+ <div
+ v-else
+ class="light">
\-
</div>
</td>
<td class="content">
- <div class="controls hidden-xs pull-right">
- <button
- type="button"
- class="btn btn-remove"
- title="Remove tag"
- v-tooltip
- @click="handleDeleteRegistry(item)">
- <i
- class="fa fa-trash"
- aria-hidden="true">
- </i>
- </button>
- </div>
+ <button
+ v-if="item.canDelete"
+ type="button"
+ class="js-delete-registry btn btn-remove hidden-xs pull-right"
+ :title="__('Remove tag')"
+ data-container="body"
+ v-tooltip
+ @click="handleDeleteRegistry(item)">
+ <i
+ class="fa fa-trash"
+ aria-hidden="true">
+ </i>
+ </button>
</td>
</tr>
</tbody>
diff --git a/app/assets/javascripts/registry/index.js b/app/assets/javascripts/registry/index.js
index 4f7895897b2..ad76dfd333b 100644
--- a/app/assets/javascripts/registry/index.js
+++ b/app/assets/javascripts/registry/index.js
@@ -1,9 +1,6 @@
import Vue from 'vue';
-import Translate from '../vue_shared/translate';
import registryApp from './components/app.vue';
-// Vue.use(Translate);
-
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#js-vue-registry-images',
components: {
diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js
index 5dda16b8d9a..c86e40a1a28 100644
--- a/app/assets/javascripts/registry/stores/actions.js
+++ b/app/assets/javascripts/registry/stores/actions.js
@@ -27,16 +27,10 @@ export const fetchList = ({ commit }, list) => {
};
export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.path)
- .then(res => res.json())
- .then(() => {
- commit(types.DELETE_REPO, repo);
- });
+ .then(res => res.json());
export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.path)
- .then(res => res.json())
- .then(() => {
- commit(types.DELETE_IMAGE, image);
- });
+ .then(res => res.json());
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
-export const toggleIsLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
+export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
diff --git a/app/assets/javascripts/registry/stores/getters.js b/app/assets/javascripts/registry/stores/getters.js
index 6c6ed0cd738..588f479c492 100644
--- a/app/assets/javascripts/registry/stores/getters.js
+++ b/app/assets/javascripts/registry/stores/getters.js
@@ -1,2 +1,2 @@
export const isLoading = state => state.isLoading;
-export const repos = state => state.repos; \ No newline at end of file
+export const repos = state => state.repos;
diff --git a/app/assets/javascripts/registry/stores/mutation_types.js b/app/assets/javascripts/registry/stores/mutation_types.js
index aece401a24a..2c69bf11807 100644
--- a/app/assets/javascripts/registry/stores/mutation_types.js
+++ b/app/assets/javascripts/registry/stores/mutation_types.js
@@ -1,10 +1,7 @@
export const SET_MAIN_ENDPOINT = 'SET_MAIN_ENDPOINT';
-export const FETCH_REPOS_LIST = 'FETCH_REPOS_LIST';
-export const DELETE_REPO = 'DELETE_REPO';
+
export const SET_REPOS_LIST = 'SET_REPOS_LIST';
export const TOGGLE_MAIN_LOADING = 'TOGGLE_MAIN_LOADING';
-export const FETCH_IMAGES_LIST = 'FETCH_IMAGES_LIST';
export const SET_REGISTRY_LIST = 'SET_REGISTRY_LIST';
-export const DELETE_IMAGE = 'DELETE_IMAGE';
export const TOGGLE_REGISTRY_LIST_LOADING = 'TOGGLE_REGISTRY_LIST_LOADING';
diff --git a/app/assets/javascripts/registry/stores/mutations.js b/app/assets/javascripts/registry/stores/mutations.js
index 796548bffec..0e69d2bed1b 100644
--- a/app/assets/javascripts/registry/stores/mutations.js
+++ b/app/assets/javascripts/registry/stores/mutations.js
@@ -11,12 +11,12 @@ export default {
repos: list.map(el => ({
canDelete: !!el.destroy_path,
destroyPath: el.destroy_path,
+ id: el.id,
isLoading: false,
list: [],
location: el.location,
name: el.name,
tagsPath: el.tags_path,
- id: el.id,
})),
});
},
@@ -26,26 +26,6 @@ export default {
},
[types.SET_REGISTRY_LIST](state, repo, list) {
- // mock
- list = [
- {
- name: 'centos6',
- short_revision: '0b6091a66',
- revision: '0b6091a665af68bbbbb36a3e088ec3cd6f35389deebf6d4617042d56722d76fb',
- size: 706,
- layers: 19,
- created_at: 1505828744434,
- },
- {
- name: 'centos7',
- short_revision: 'b118ab5b0',
- revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43',
- size: 679,
- layers: 19,
- created_at: 1505828744434,
- },
- ];
-
const listToUpdate = state.repos.find(el => el.id === repo.id);
listToUpdate.list = list.map(element => ({
@@ -54,6 +34,7 @@ export default {
shortRevision: element.short_revision,
size: element.size,
layers: element.layers,
+ location: element.location,
createdAt: element.created_at,
destroyPath: element.destroy_path,
canDelete: !!element.destroy_path,
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index fbf7233b13d..3a7143c450e 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -1,5 +1,7 @@
<script>
- import Clipboard from 'vendor/clipboard';
+ /**
+ * Falls back to the code used in `copy_to_clipboard.js`
+ */
export default {
name: 'clipboardButton',
@@ -13,13 +15,6 @@
required: true,
},
},
- mounted() {
- // return new Clipboard(this.$refs.btn, {
- // text: () => {
- // return this.text;
- // },
- // });
- }
};
</script>
@@ -28,9 +23,7 @@
type="button"
class="btn btn-transparent btn-clipboard"
:data-title="title"
- :data-clipboard-text="text"
- ref="btn"
- >
+ :data-clipboard-text="text">
<i
aria-hidden="true"
class="fa fa-clipboard">
diff --git a/app/assets/stylesheets/pages/container_registry.scss b/app/assets/stylesheets/pages/container_registry.scss
index 089a693efe4..3266714396e 100644
--- a/app/assets/stylesheets/pages/container_registry.scss
+++ b/app/assets/stylesheets/pages/container_registry.scss
@@ -9,10 +9,6 @@
.container-image-head {
padding: 0 16px;
line-height: 4em;
-
- &:hover {
- text-decoration: underline;
- }
}
.table.tags {
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index 89093e4172a..952081a349f 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -10,7 +10,7 @@ module Projects
respond_to do |format|
format.html
format.json do
- # render json: @images
+ # Remove code below
render json: [
{
name: 'gitlab-org/omnibus-gitlab/foo',
@@ -41,13 +41,27 @@ module Projects
def destroy
if image.destroy
- redirect_to project_container_registry_index_path(@project),
- status: 302,
- notice: 'Image repository has been removed successfully!'
+ respond_to do |format|
+ # TODO: @Kamil, I don't think this is used ever. Should we keep it or remove it?
+ format.html do
+ redirect_to project_container_registry_index_path(@project),
+ status: 302,
+ notice: 'Image repository has been removed successfully!'
+ end
+
+ format.json { head :no_content }
+ end
else
- redirect_to project_container_registry_index_path(@project),
- status: 302,
- alert: 'Failed to remove image repository!'
+ respond_to do |format|
+ # TODO: @Kamil, I don't think this is used ever. Should we keep it or remove it?
+ format.html do
+ redirect_to project_container_registry_index_path(@project),
+ status: 302,
+ alert: 'Failed to remove image repository!'
+ end
+
+ format.json { head :no_content }
+ end
end
end
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 4a76431494c..9bf5eb03cb0 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -8,7 +8,7 @@
= _('With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images.')
%p.append-bottom-0
= succeed '.' do
- Learn more about
+ = _('Learn more about')
= link_to _('Container Registry'), help_page_path('user/project/container_registry'), target: '_blank'
.row
.col-lg-12
@@ -20,14 +20,14 @@
%p
= _('First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have')
= link_to _('2FA enabled'), help_page_path('user/profile/account/two_factor_authentication'), target: '_blank'
- you need to use a
+ = _('you need to use a')
= succeed ':' do
= link_to _('personal access token'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank'
%pre
docker login #{Gitlab.config.registry.host_port}
%br
%p
- = _("Once you log in, you&rsquo;re free to create and upload a container image using the common")
+ = _('Once you log in, you&rsquo;re free to create and upload a container image using the common')
%code
= _('build')
= _('and')
@@ -37,7 +37,6 @@
:plain
docker build -t #{escape_once(@project.container_registry_url)} .
docker push #{escape_once(@project.container_registry_url)}
-
%hr
%h5.prepend-top-default
= _('Use different image names')
@@ -48,8 +47,6 @@
#{escape_once(@project.container_registry_url)}:tag
#{escape_once(@project.container_registry_url)}/optional-image-name:tag
#{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag
-
-
.row
.col-lg-12
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json)}}
diff --git a/spec/javascripts/notes/stores/helpers.js b/spec/javascripts/helpers/vuex_action_helper.js
index 2d386fe1da5..2d386fe1da5 100644
--- a/spec/javascripts/notes/stores/helpers.js
+++ b/spec/javascripts/helpers/vuex_action_helper.js
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index 72d362acb2f..4359899299f 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -1,6 +1,6 @@
import * as actions from '~/notes/stores/actions';
-import testAction from './helpers';
+import testAction from '../../helpers/vuex_action_helper';
import { discussionMock, notesDataMock, userDataMock, issueDataMock, individualNote } from '../mock_data';
describe('Actions Notes Store', () => {
diff --git a/spec/javascripts/registry/components/app_spec.js b/spec/javascripts/registry/components/app_spec.js
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/spec/javascripts/registry/components/app_spec.js
diff --git a/spec/javascripts/registry/components/collapsible_container_spec.js b/spec/javascripts/registry/components/collapsible_container_spec.js
new file mode 100644
index 00000000000..b9372f48965
--- /dev/null
+++ b/spec/javascripts/registry/components/collapsible_container_spec.js
@@ -0,0 +1,112 @@
+import Vue from 'vue';
+import collapsibleComponent from '~/registry/components/collapsible_container.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('collapsible registry container', () => {
+ let vm;
+ let Component;
+ let mockData;
+
+ beforeEach(() => {
+ Component = Vue.extend(collapsibleComponent);
+ mockData = {
+ canDelete: true,
+ destroyPath: 'path',
+ id: '123',
+ isLoading: false,
+ list: [
+ {
+ tag: 'centos6',
+ revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43',
+ shortRevision: 'b118ab5b0',
+ size: 19,
+ layers: 10,
+ location: 'location',
+ createdAt: 1505828744434,
+ destroyPath: 'path',
+ canDelete: true,
+ },
+ ],
+ location: 'location',
+ name: 'foo',
+ tagsPath: 'path',
+ };
+ vm = mountComponent(Component, { repo: mockData });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('toggle', () => {
+ it('should be closed by default', () => {
+ expect(vm.$el.querySelector('.container-image-tags')).toBe(null);
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-right');
+ });
+
+ it('should be open when user clicks on closed repo', (done) => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.container-image-tags')).toBeDefined();
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-up');
+ done();
+ });
+ });
+
+ it('should be closed when the user clicks on an opened repo', (done) => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+
+ Vue.nextTick(() => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.container-image-tags')).toBe(null);
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-right');
+ done();
+ });
+ });
+ });
+ });
+
+ describe('delete repo', () => {
+ it('should be possible to delete a repo', () => {
+ expect(vm.$el.querySelector('.js-remove-repo')).toBeDefined();
+ });
+ });
+
+ describe('registry list', () => {
+ it('should render a table with the registry list', (done) => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+
+ Vue.nextTick(() => {
+ expect(
+ vm.$el.querySelectorAll('table tbody tr').length,
+ ).toEqual(mockData.list.length);
+ done();
+ });
+ });
+
+ it('should render registry tag', (done) => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+
+ Vue.nextTick(() => {
+ const textRendered = vm.$el.querySelector('.table tbody tr').textContent.trim().replace(/\s\s+/g, ' ');
+ expect(textRendered).toContain(mockData.list[0].tag);
+ expect(textRendered).toContain(mockData.list[0].shortRevision);
+ expect(textRendered).toContain(mockData.list[0].layers);
+ expect(textRendered).toContain(mockData.list[0].size);
+ done();
+ });
+ });
+
+ it('should be possible to delete a registry', (done) => {
+ vm.$el.querySelector('.js-toggle-repo').click();
+
+ Vue.nextTick(() => {
+ expect(
+ vm.$el.querySelector('.table tbody tr .js-delete-registry'),
+ ).toBeDefined();
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/registry/stores/actions_spec.js b/spec/javascripts/registry/stores/actions_spec.js
new file mode 100644
index 00000000000..d835ea04622
--- /dev/null
+++ b/spec/javascripts/registry/stores/actions_spec.js
@@ -0,0 +1,85 @@
+import Vue from 'vue';
+import VueResource from 'vue-resource';
+import _ from 'underscore';
+import * as actions from '~/registry/stores/actions';
+import * as types from '~/registry/stores/mutation_types';
+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;
+
+ beforeEach(() => {
+ mockedState = defaultState;
+ });
+
+ describe('server requests', () => {
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ });
+
+ describe('fetchRepos', () => {
+ beforeEach(() => {
+ interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify(reposServerResponse), {
+ status: 200,
+ }));
+ };
+
+ Vue.http.interceptors.push(interceptor);
+ });
+
+ it('should set receveived repos', (done) => {
+ testAction(actions.fetchRepos, null, mockedState, [
+ { type: types.TOGGLE_MAIN_LOADING },
+ { type: types.SET_REPOS_LIST, payload: reposServerResponse },
+ ], done);
+ });
+ });
+
+ describe('fetchList', () => {
+ beforeEach(() => {
+ interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify(registryServerResponse), {
+ status: 200,
+ }));
+ };
+
+ Vue.http.interceptors.push(interceptor);
+ });
+
+ it('should set received list', (done) => {
+ mockedState.repos = parsedReposServerResponse;
+
+ testAction(actions.fetchList, mockedState.repos[1], mockedState, [
+ { type: types.TOGGLE_REGISTRY_LIST_LOADING },
+ { type: types.SET_REGISTRY_LIST, payload: registryServerResponse },
+ ], done);
+ });
+ });
+ });
+
+ describe('setMainEndpoint', () => {
+ it('should commit set main endpoint', (done) => {
+ testAction(actions.setMainEndpoint, 'endpoint', mockedState, [
+ { type: types.SET_MAIN_ENDPOINT, payload: 'endpoint' },
+ ], done);
+ });
+ });
+
+ describe('toggleLoading', () => {
+ it('should commit toggle main loading', (done) => {
+ testAction(actions.toggleLoading, null, mockedState, [
+ { type: types.TOGGLE_MAIN_LOADING },
+ ], done);
+ });
+ });
+});
diff --git a/spec/javascripts/registry/stores/getters_spec.js b/spec/javascripts/registry/stores/getters_spec.js
new file mode 100644
index 00000000000..3d989541881
--- /dev/null
+++ b/spec/javascripts/registry/stores/getters_spec.js
@@ -0,0 +1,43 @@
+import * as getters from '~/registry/stores/getters';
+
+describe('Getters Registry Store', () => {
+ let state;
+
+ beforeEach(() => {
+ state = {
+ isLoading: false,
+ endpoint: '/root/empty-project/container_registry.json',
+ repos: [{
+ canDelete: true,
+ destroyPath: 'bar',
+ id: '134',
+ isLoading: false,
+ list: [],
+ location: 'foo',
+ name: 'gitlab-org/omnibus-gitlab/foo',
+ tagsPath: 'foo',
+ }, {
+ canDelete: true,
+ destroyPath: 'bar',
+ id: '123',
+ isLoading: false,
+ list: [],
+ location: 'foo',
+ name: 'gitlab-org/omnibus-gitlab',
+ tagsPath: 'foo',
+ }],
+ };
+ });
+
+ describe('isLoading', () => {
+ it('should return the isLoading property', () => {
+ expect(getters.isLoading(state)).toEqual(state.isLoading);
+ });
+ });
+
+ describe('repos', () => {
+ it('should return the repos', () => {
+ expect(getters.repos(state)).toEqual(state.repos);
+ });
+ });
+});
diff --git a/spec/javascripts/registry/stores/mock_data.js b/spec/javascripts/registry/stores/mock_data.js
new file mode 100644
index 00000000000..80f7c51426a
--- /dev/null
+++ b/spec/javascripts/registry/stores/mock_data.js
@@ -0,0 +1,91 @@
+export const defaultState = {
+ isLoading: false,
+ endpoint: '',
+ repos: [],
+};
+
+export const reposServerResponse = [
+ {
+ destroy_path: 'path',
+ id: '123',
+ location: 'location',
+ name: 'foo',
+ tags_path: 'tags_path',
+ },
+ {
+ destroy_path: 'path_',
+ id: '456',
+ location: 'location_',
+ name: 'bar',
+ tags_path: 'tags_path_',
+ },
+];
+
+export const registryServerResponse = [
+ {
+ name: 'centos7',
+ short_revision: 'b118ab5b0',
+ revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43',
+ size: 679,
+ layers: 19,
+ location: 'location',
+ created_at: 1505828744434,
+ destroy_path: 'path_',
+ },
+ {
+ name: 'centos6',
+ short_revision: 'b118ab5b0',
+ revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43',
+ size: 679,
+ layers: 19,
+ location: 'location',
+ created_at: 1505828744434,
+ }];
+
+export const parsedReposServerResponse = [
+ {
+ canDelete: true,
+ destroyPath: reposServerResponse[0].destroy_path,
+ id: reposServerResponse[0].id,
+ isLoading: false,
+ list: [],
+ location: reposServerResponse[0].location,
+ name: reposServerResponse[0].name,
+ tagsPath: reposServerResponse[0].tags_path,
+ },
+ {
+ canDelete: true,
+ destroyPath: reposServerResponse[1].destroy_path,
+ id: reposServerResponse[1].id,
+ isLoading: false,
+ list: [],
+ location: reposServerResponse[1].location,
+ name: reposServerResponse[1].name,
+ tagsPath: reposServerResponse[1].tags_path,
+ },
+];
+
+export const parsedRegistryServerResponse = [
+ {
+ tag: registryServerResponse[0].name,
+ revision: registryServerResponse[0].revision,
+ shortRevision: registryServerResponse[0].short_revision,
+ size: registryServerResponse[0].size,
+ layers: registryServerResponse[0].layers,
+ location: registryServerResponse[0].location,
+ createdAt: registryServerResponse[0].created_at,
+ destroyPath: registryServerResponse[0].destroy_path,
+ canDelete: true,
+ },
+ {
+ tag: registryServerResponse[1].name,
+ revision: registryServerResponse[1].revision,
+ shortRevision: registryServerResponse[1].short_revision,
+ size: registryServerResponse[1].size,
+ layers: registryServerResponse[1].layers,
+ location: registryServerResponse[1].location,
+ createdAt: registryServerResponse[1].created_at,
+ destroyPath: registryServerResponse[1].destroy_path,
+ canDelete: false,
+ },
+];
diff --git a/spec/javascripts/registry/stores/mutations_spec.js b/spec/javascripts/registry/stores/mutations_spec.js
new file mode 100644
index 00000000000..7fae19f3656
--- /dev/null
+++ b/spec/javascripts/registry/stores/mutations_spec.js
@@ -0,0 +1,57 @@
+import mutations from '~/registry/stores/mutations';
+import * as types from '~/registry/stores/mutation_types';
+import {
+ defaultState,
+ reposServerResponse,
+ registryServerResponse,
+ parsedReposServerResponse,
+ parsedRegistryServerResponse,
+} from './mock_data';
+
+describe('Mutations Registry Store', () => {
+ let mockState;
+ beforeEach(() => {
+ mockState = defaultState;
+ });
+
+ describe('SET_MAIN_ENDPOINT', () => {
+ it('should set the main endpoint', () => {
+ const expectedState = Object.assign({}, mockState, { endpoint: 'foo' });
+ mutations[types.SET_MAIN_ENDPOINT](mockState, 'foo');
+ expect(mockState).toEqual(expectedState);
+ });
+ });
+
+ describe('SET_REPOS_LIST', () => {
+ it('should set a parsed repository list', () => {
+ mutations[types.SET_REPOS_LIST](mockState, reposServerResponse);
+ expect(mockState.repos).toEqual(parsedReposServerResponse);
+ });
+ });
+
+ describe('TOGGLE_MAIN_LOADING', () => {
+ it('should set a parsed repository list', () => {
+ mutations[types.TOGGLE_MAIN_LOADING](mockState);
+ expect(mockState.isLoading).toEqual(true);
+ });
+ });
+
+ describe('SET_REGISTRY_LIST', () => {
+ it('should set a list of registries in a specific repository', () => {
+ mutations[types.SET_REPOS_LIST](mockState, reposServerResponse);
+ mutations[types.SET_REGISTRY_LIST](mockState, mockState.repos[0], registryServerResponse);
+
+ expect(mockState.repos[0].list).toEqual(parsedRegistryServerResponse);
+ });
+ });
+
+ describe('TOGGLE_REGISTRY_LIST_LOADING', () => {
+ it('should toggle isLoading property for a specific repository', () => {
+ mutations[types.SET_REPOS_LIST](mockState, reposServerResponse);
+ mutations[types.SET_REGISTRY_LIST](mockState, mockState.repos[0], registryServerResponse);
+
+ mutations[types.TOGGLE_REGISTRY_LIST_LOADING](mockState, mockState.repos[0]);
+ expect(mockState.repos[0].isLoading).toEqual(true);
+ });
+ });
+});