diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-23 15:06:32 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-23 15:06:32 +0000 |
commit | 6f9edd1a4c4942d3d13ec54793cfae56164b1a0a (patch) | |
tree | f118f4a1dcad2db7b35ab15157e16eef56eba860 /spec/frontend/registry | |
parent | 94e614c94c0a42e261e6af88c89461d90f3330c0 (diff) | |
download | gitlab-ce-6f9edd1a4c4942d3d13ec54793cfae56164b1a0a.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/registry')
-rw-r--r-- | spec/frontend/registry/components/app_spec.js | 121 | ||||
-rw-r--r-- | spec/frontend/registry/components/collapsible_container_spec.js | 89 | ||||
-rw-r--r-- | spec/frontend/registry/components/table_registry_spec.js | 211 | ||||
-rw-r--r-- | spec/frontend/registry/mock_data.js | 134 | ||||
-rw-r--r-- | spec/frontend/registry/stores/actions_spec.js | 189 | ||||
-rw-r--r-- | spec/frontend/registry/stores/getters_spec.js (renamed from spec/frontend/registry/getters_spec.js) | 0 | ||||
-rw-r--r-- | spec/frontend/registry/stores/mutations_spec.js | 85 |
7 files changed, 829 insertions, 0 deletions
diff --git a/spec/frontend/registry/components/app_spec.js b/spec/frontend/registry/components/app_spec.js new file mode 100644 index 00000000000..190af5c11cd --- /dev/null +++ b/spec/frontend/registry/components/app_spec.js @@ -0,0 +1,121 @@ +import registry from '~/registry/components/app.vue'; +import { mount } from '@vue/test-utils'; +import { TEST_HOST } from '../../helpers/test_constants'; +import { reposServerResponse, parsedReposServerResponse } from '../mock_data'; + +describe('Registry List', () => { + let wrapper; + + const findCollapsibleContainer = w => w.findAll({ name: 'CollapsibeContainerRegisty' }); + const findNoContainerImagesText = w => w.find('.js-no-container-images-text'); + const findSpinner = w => w.find('.gl-spinner'); + const findCharacterErrorText = w => w.find('.js-character-error-text'); + + const propsData = { + endpoint: `${TEST_HOST}/foo`, + helpPagePath: 'foo', + noContainersImage: 'foo', + containersErrorImage: 'foo', + repositoryUrl: 'foo', + }; + + const setMainEndpoint = jest.fn(); + const fetchRepos = jest.fn(); + + const methods = { + setMainEndpoint, + fetchRepos, + }; + + beforeEach(() => { + wrapper = mount(registry, { + propsData, + computed: { + repos() { + return parsedReposServerResponse; + }, + }, + methods, + }); + }); + + describe('with data', () => { + it('should render a list of CollapsibeContainerRegisty', () => { + const containers = findCollapsibleContainer(wrapper); + expect(wrapper.vm.repos.length).toEqual(reposServerResponse.length); + expect(containers.length).toEqual(reposServerResponse.length); + }); + }); + + describe('without data', () => { + let localWrapper; + beforeEach(() => { + localWrapper = mount(registry, { + propsData, + computed: { + repos() { + return []; + }, + }, + methods, + }); + }); + + it('should render empty message', () => { + const noContainerImagesText = findNoContainerImagesText(localWrapper); + expect(noContainerImagesText.text()).toEqual( + 'With the Container Registry, every project can have its own space to store its Docker images. More Information', + ); + }); + }); + + describe('while loading data', () => { + let localWrapper; + + beforeEach(() => { + localWrapper = mount(registry, { + propsData, + computed: { + repos() { + return []; + }, + isLoading() { + return true; + }, + }, + methods, + }); + }); + + it('should render a loading spinner', () => { + const spinner = findSpinner(localWrapper); + expect(spinner.exists()).toBe(true); + }); + }); + + describe('invalid characters in path', () => { + let localWrapper; + + beforeEach(() => { + localWrapper = mount(registry, { + propsData: { + ...propsData, + characterError: true, + }, + computed: { + repos() { + return []; + }, + }, + methods, + }); + }); + + it('should render invalid characters error message', () => { + const characterErrorText = findCharacterErrorText(localWrapper); + expect(characterErrorText.text()).toEqual( + 'We are having trouble connecting to Docker, which could be due to an issue with your project name or path. More Information', + ); + }); + }); +}); diff --git a/spec/frontend/registry/components/collapsible_container_spec.js b/spec/frontend/registry/components/collapsible_container_spec.js new file mode 100644 index 00000000000..0fe4338f1ba --- /dev/null +++ b/spec/frontend/registry/components/collapsible_container_spec.js @@ -0,0 +1,89 @@ +import Vue from 'vue'; +import { mount } from '@vue/test-utils'; +import collapsibleComponent from '~/registry/components/collapsible_container.vue'; +import { repoPropsData } from '../mock_data'; +import createFlash from '~/flash'; + +jest.mock('~/flash.js'); + +describe('collapsible registry container', () => { + let wrapper; + + const findDeleteBtn = w => w.find('.js-remove-repo'); + const findContainerImageTags = w => w.find('.container-image-tags'); + const findToggleRepos = w => w.findAll('.js-toggle-repo'); + + beforeEach(() => { + createFlash.mockClear(); + // This is needed due to console.error called by vue to emit a warning that stop the tests + // see https://github.com/vuejs/vue-test-utils/issues/532 + Vue.config.silent = true; + wrapper = mount(collapsibleComponent, { + propsData: { + repo: repoPropsData, + }, + }); + }); + + afterEach(() => { + Vue.config.silent = false; + }); + + describe('toggle', () => { + beforeEach(() => { + const fetchList = jest.fn(); + wrapper.setMethods({ fetchList }); + }); + + const expectIsClosed = () => { + const container = findContainerImageTags(wrapper); + expect(container.exists()).toBe(false); + expect(wrapper.vm.iconName).toEqual('angle-right'); + }; + + it('should be closed by default', () => { + expectIsClosed(); + }); + it('should be open when user clicks on closed repo', () => { + const toggleRepos = findToggleRepos(wrapper); + toggleRepos.at(0).trigger('click'); + const container = findContainerImageTags(wrapper); + expect(container.exists()).toBe(true); + expect(wrapper.vm.fetchList).toHaveBeenCalled(); + }); + it('should be closed when the user clicks on an opened repo', done => { + const toggleRepos = findToggleRepos(wrapper); + toggleRepos.at(0).trigger('click'); + Vue.nextTick(() => { + toggleRepos.at(0).trigger('click'); + Vue.nextTick(() => { + expectIsClosed(); + done(); + }); + }); + }); + }); + + describe('delete repo', () => { + it('should be possible to delete a repo', () => { + const deleteBtn = findDeleteBtn(wrapper); + expect(deleteBtn.exists()).toBe(true); + }); + + it('should call deleteItem when confirming deletion', () => { + const deleteItem = jest.fn().mockResolvedValue(); + const fetchRepos = jest.fn().mockResolvedValue(); + wrapper.setMethods({ deleteItem, fetchRepos }); + wrapper.vm.handleDeleteRepository(); + expect(wrapper.vm.deleteItem).toHaveBeenCalledWith(wrapper.vm.repo); + }); + + it('should show an error when there is API error', () => { + const deleteItem = jest.fn().mockRejectedValue('error'); + wrapper.setMethods({ deleteItem }); + return wrapper.vm.handleDeleteRepository().then(() => { + expect(createFlash).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/spec/frontend/registry/components/table_registry_spec.js b/spec/frontend/registry/components/table_registry_spec.js new file mode 100644 index 00000000000..a2eee4aada7 --- /dev/null +++ b/spec/frontend/registry/components/table_registry_spec.js @@ -0,0 +1,211 @@ +import Vue from 'vue'; +import tableRegistry from '~/registry/components/table_registry.vue'; +import { mount } from '@vue/test-utils'; +import { repoPropsData } from '../mock_data'; + +const [firstImage, secondImage] = repoPropsData.list; + +describe('table registry', () => { + let wrapper; + + const findSelectAllCheckbox = w => w.find('.js-select-all-checkbox > input'); + const findSelectCheckboxes = w => w.findAll('.js-select-checkbox > input'); + const findDeleteButton = w => w.find('.js-delete-registry'); + const findDeleteButtonsRow = w => w.findAll('.js-delete-registry-row'); + const findPagination = w => w.find('.js-registry-pagination'); + const bulkDeletePath = 'path'; + + beforeEach(() => { + // This is needed due to console.error called by vue to emit a warning that stop the tests + // see https://github.com/vuejs/vue-test-utils/issues/532 + Vue.config.silent = true; + wrapper = mount(tableRegistry, { + propsData: { + repo: repoPropsData, + }, + }); + }); + + afterEach(() => { + Vue.config.silent = false; + }); + + describe('rendering', () => { + it('should render a table with the registry list', () => { + expect(wrapper.findAll('.registry-image-row').length).toEqual(repoPropsData.list.length); + }); + + it('should render registry tag', () => { + const tds = wrapper.findAll('.registry-image-row td'); + expect(tds.at(0).classes()).toContain('check'); + expect(tds.at(1).html()).toContain(repoPropsData.list[0].tag); + expect(tds.at(2).html()).toContain(repoPropsData.list[0].shortRevision); + expect(tds.at(3).html()).toContain(repoPropsData.list[0].layers); + expect(tds.at(3).html()).toContain(repoPropsData.list[0].size); + expect(tds.at(4).html()).toContain(wrapper.vm.timeFormated(repoPropsData.list[0].createdAt)); + }); + }); + + describe('multi select', () => { + it('selecting a row should enable delete button', done => { + const deleteBtn = findDeleteButton(wrapper); + const checkboxes = findSelectCheckboxes(wrapper); + + expect(deleteBtn.attributes('disabled')).toBe('disabled'); + + checkboxes.at(0).trigger('click'); + Vue.nextTick(() => { + expect(deleteBtn.attributes('disabled')).toEqual(undefined); + done(); + }); + }); + + it('selecting all checkbox should select all rows and enable delete button', done => { + const selectAll = findSelectAllCheckbox(wrapper); + const checkboxes = findSelectCheckboxes(wrapper); + selectAll.trigger('click'); + + Vue.nextTick(() => { + const checked = checkboxes.filter(w => w.element.checked); + expect(checked.length).toBe(checkboxes.length); + done(); + }); + }); + + it('deselecting select all checkbox should deselect all rows and disable delete button', done => { + const checkboxes = findSelectCheckboxes(wrapper); + const selectAll = findSelectAllCheckbox(wrapper); + selectAll.trigger('click'); + selectAll.trigger('click'); + + Vue.nextTick(() => { + const checked = checkboxes.filter(w => !w.element.checked); + expect(checked.length).toBe(checkboxes.length); + done(); + }); + }); + + it('should delete multiple items when multiple items are selected', done => { + const multiDeleteItems = jest.fn().mockResolvedValue(); + wrapper.setMethods({ multiDeleteItems }); + const selectAll = findSelectAllCheckbox(wrapper); + selectAll.trigger('click'); + + Vue.nextTick(() => { + const deleteBtn = findDeleteButton(wrapper); + expect(wrapper.vm.itemsToBeDeleted).toEqual([0, 1]); + expect(deleteBtn.attributes('disabled')).toEqual(undefined); + wrapper.vm.handleMultipleDelete(); + + Vue.nextTick(() => { + expect(wrapper.vm.itemsToBeDeleted).toEqual([]); + expect(wrapper.vm.multiDeleteItems).toHaveBeenCalledWith({ + path: bulkDeletePath, + items: [firstImage.tag, secondImage.tag], + }); + done(); + }); + }); + }); + + it('should show an error message if bulkDeletePath is not set', () => { + const showError = jest.fn(); + wrapper.setMethods({ showError }); + wrapper.setProps({ + repo: { + ...repoPropsData, + tagsPath: null, + }, + }); + wrapper.vm.handleMultipleDelete(); + expect(wrapper.vm.showError).toHaveBeenCalled(); + }); + }); + + describe('delete registry', () => { + beforeEach(() => { + wrapper.setData({ itemsToBeDeleted: [0] }); + }); + + it('should be possible to delete a registry', () => { + const deleteBtn = findDeleteButton(wrapper); + const deleteBtns = findDeleteButtonsRow(wrapper); + expect(wrapper.vm.itemsToBeDeleted).toEqual([0]); + expect(deleteBtn).toBeDefined(); + expect(deleteBtn.attributes('disable')).toBe(undefined); + expect(deleteBtns.is('button')).toBe(true); + }); + + it('should allow deletion row by row', () => { + const deleteBtns = findDeleteButtonsRow(wrapper); + const deleteSingleItem = jest.fn(); + const deleteItem = jest.fn().mockResolvedValue(); + wrapper.setMethods({ deleteSingleItem, deleteItem }); + deleteBtns.at(0).trigger('click'); + expect(wrapper.vm.deleteSingleItem).toHaveBeenCalledWith(0); + wrapper.vm.handleSingleDelete(1); + expect(wrapper.vm.deleteItem).toHaveBeenCalledWith(1); + }); + }); + + describe('pagination', () => { + let localWrapper = null; + const repo = { + repoPropsData, + pagination: { + total: 20, + perPage: 2, + nextPage: 2, + }, + }; + + beforeEach(() => { + localWrapper = mount(tableRegistry, { + propsData: { + repo, + }, + }); + }); + + it('should exist', () => { + const pagination = findPagination(localWrapper); + expect(pagination.exists()).toBe(true); + }); + it('should be visible when pagination is needed', () => { + const pagination = findPagination(localWrapper); + expect(pagination.isVisible()).toBe(true); + localWrapper.setProps({ + repo: { + pagination: { + total: 0, + perPage: 10, + }, + }, + }); + expect(localWrapper.vm.shouldRenderPagination).toBe(false); + }); + it('should have a change function that update the list when run', () => { + const fetchList = jest.fn().mockResolvedValue(); + localWrapper.setMethods({ fetchList }); + localWrapper.vm.onPageChange(1); + expect(localWrapper.vm.fetchList).toHaveBeenCalledWith({ repo, page: 1 }); + }); + }); + + describe('modal content', () => { + it('should show the singular title and image name when deleting a single image', () => { + wrapper.setData({ itemsToBeDeleted: [1] }); + wrapper.vm.setModalDescription(0); + expect(wrapper.vm.modalTitle).toBe('Remove image'); + expect(wrapper.vm.modalDescription).toContain(firstImage.tag); + }); + + it('should show the plural title and image count when deleting more than one image', () => { + wrapper.setData({ itemsToBeDeleted: [1, 2] }); + wrapper.vm.setModalDescription(); + + expect(wrapper.vm.modalTitle).toBe('Remove images'); + expect(wrapper.vm.modalDescription).toContain('<b>2</b> images'); + }); + }); +}); diff --git a/spec/frontend/registry/mock_data.js b/spec/frontend/registry/mock_data.js new file mode 100644 index 00000000000..130ab298e89 --- /dev/null +++ b/spec/frontend/registry/mock_data.js @@ -0,0 +1,134 @@ +export const defaultState = { + isLoading: false, + endpoint: '', + repos: [], +}; + +export const reposServerResponse = [ + { + destroy_path: 'path', + id: '123', + location: 'location', + path: 'foo', + tags_path: 'tags_path', + }, + { + destroy_path: 'path_', + id: '456', + location: 'location_', + path: 'bar', + tags_path: 'tags_path_', + }, +]; + +export const registryServerResponse = [ + { + name: 'centos7', + short_revision: 'b118ab5b0', + revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43', + total_size: 679, + layers: 19, + location: 'location', + created_at: 1505828744434, + destroy_path: 'path_', + }, + { + name: 'centos6', + short_revision: 'b118ab5b0', + revision: 'b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43', + total_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].path, + 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].path, + tagsPath: reposServerResponse[1].tags_path, + }, +]; + +export const parsedRegistryServerResponse = [ + { + tag: registryServerResponse[0].name, + revision: registryServerResponse[0].revision, + shortRevision: registryServerResponse[0].short_revision, + size: registryServerResponse[0].total_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].total_size, + layers: registryServerResponse[1].layers, + location: registryServerResponse[1].location, + createdAt: registryServerResponse[1].created_at, + destroyPath: registryServerResponse[1].destroy_path, + canDelete: false, + }, +]; + +export const repoPropsData = { + 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, + }, + { + tag: 'test-image', + revision: 'b969de599faea2b3d9b6605a8b0897261c571acaa36db1bdc7349b5775b4e0b4', + shortRevision: 'b969de599', + size: 19, + layers: 10, + location: 'location-2', + createdAt: 1505828744434, + destroyPath: 'path-2', + canDelete: true, + }, + ], + location: 'location', + name: 'foo', + tagsPath: 'path', + pagination: { + perPage: 5, + page: 1, + total: 13, + totalPages: 1, + nextPage: null, + previousPage: null, + }, +}; diff --git a/spec/frontend/registry/stores/actions_spec.js b/spec/frontend/registry/stores/actions_spec.js new file mode 100644 index 00000000000..bf335904d23 --- /dev/null +++ b/spec/frontend/registry/stores/actions_spec.js @@ -0,0 +1,189 @@ +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 { TEST_HOST } from '../../helpers/test_constants'; +import testAction from '../../helpers/vuex_action_helper'; +import createFlash from '~/flash'; + +import { + reposServerResponse, + registryServerResponse, + parsedReposServerResponse, +} from '../mock_data'; + +jest.mock('~/flash.js'); + +describe('Actions Registry Store', () => { + let mock; + let state; + + beforeEach(() => { + mock = new MockAdapter(axios); + state = { + endpoint: `${TEST_HOST}/endpoint.json`, + }; + }); + + afterEach(() => { + mock.restore(); + }); + + describe('fetchRepos', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, reposServerResponse, {}); + }); + + it('should set receveived repos', done => { + testAction( + actions.fetchRepos, + null, + state, + [ + { type: types.TOGGLE_MAIN_LOADING }, + { type: types.TOGGLE_MAIN_LOADING }, + { type: types.SET_REPOS_LIST, payload: reposServerResponse }, + ], + [], + done, + ); + }); + + it('should create flash on API error', done => { + testAction( + actions.fetchRepos, + null, + { + endpoint: null, + }, + [{ type: types.TOGGLE_MAIN_LOADING }, { type: types.TOGGLE_MAIN_LOADING }], + [], + () => { + expect(createFlash).toHaveBeenCalled(); + done(); + }, + ); + }); + }); + + describe('fetchList', () => { + let repo; + beforeEach(() => { + state.repos = parsedReposServerResponse; + [, repo] = state.repos; + mock.onGet(repo.tagsPath).replyOnce(200, registryServerResponse, {}); + }); + + it('should set received list', done => { + testAction( + actions.fetchList, + { repo }, + state, + [ + { type: types.TOGGLE_REGISTRY_LIST_LOADING, payload: repo }, + { type: types.TOGGLE_REGISTRY_LIST_LOADING, payload: repo }, + { + type: types.SET_REGISTRY_LIST, + payload: { + repo, + resp: registryServerResponse, + headers: expect.anything(), + }, + }, + ], + [], + done, + ); + }); + + it('should create flash on API error', done => { + const updatedRepo = { + ...repo, + tagsPath: null, + }; + testAction( + actions.fetchList, + { + repo: updatedRepo, + }, + state, + [ + { type: types.TOGGLE_REGISTRY_LIST_LOADING, payload: updatedRepo }, + { type: types.TOGGLE_REGISTRY_LIST_LOADING, payload: updatedRepo }, + ], + [], + () => { + expect(createFlash).toHaveBeenCalled(); + done(); + }, + ); + }); + }); + + describe('setMainEndpoint', () => { + it('should commit set main endpoint', done => { + testAction( + actions.setMainEndpoint, + 'endpoint', + state, + [{ type: types.SET_MAIN_ENDPOINT, payload: 'endpoint' }], + [], + done, + ); + }); + }); + + describe('toggleLoading', () => { + it('should commit toggle main loading', done => { + testAction( + actions.toggleLoading, + null, + state, + [{ type: types.TOGGLE_MAIN_LOADING }], + [], + done, + ); + }); + }); + + describe('deleteItem and multiDeleteItems', () => { + let deleted; + const destroyPath = `${TEST_HOST}/mygroup/myproject/container_registry/1.json`; + + const expectDelete = done => { + expect(mock.history.delete.length).toBe(1); + expect(deleted).toBe(true); + done(); + }; + + beforeEach(() => { + deleted = false; + mock.onDelete(destroyPath).replyOnce(() => { + deleted = true; + return [200]; + }); + }); + + it('deleteItem should perform DELETE request on destroyPath', done => { + testAction( + actions.deleteItem, + { + destroyPath, + }, + state, + ) + .then(() => { + expectDelete(done); + }) + .catch(done.fail); + }); + + it('multiDeleteItems should perform DELETE request on path', done => { + testAction(actions.multiDeleteItems, { path: destroyPath, items: [1] }, state) + .then(() => { + expectDelete(done); + }) + .catch(done.fail); + }); + }); +}); diff --git a/spec/frontend/registry/getters_spec.js b/spec/frontend/registry/stores/getters_spec.js index 839aa718997..839aa718997 100644 --- a/spec/frontend/registry/getters_spec.js +++ b/spec/frontend/registry/stores/getters_spec.js diff --git a/spec/frontend/registry/stores/mutations_spec.js b/spec/frontend/registry/stores/mutations_spec.js new file mode 100644 index 00000000000..e19fe7a27cf --- /dev/null +++ b/spec/frontend/registry/stores/mutations_spec.js @@ -0,0 +1,85 @@ +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, { + repo: mockState.repos[0], + resp: registryServerResponse, + headers: { + 'x-per-page': 2, + 'x-page': 1, + 'x-total': 10, + }, + }); + + expect(mockState.repos[0].list).toEqual(parsedRegistryServerResponse); + expect(mockState.repos[0].pagination).toEqual({ + perPage: 2, + page: 1, + total: 10, + totalPages: NaN, + nextPage: NaN, + previousPage: NaN, + }); + }); + }); + + 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, { + repo: mockState.repos[0], + resp: registryServerResponse, + headers: { + 'x-per-page': 2, + 'x-page': 1, + 'x-total': 10, + }, + }); + + mutations[types.TOGGLE_REGISTRY_LIST_LOADING](mockState, mockState.repos[0]); + + expect(mockState.repos[0].isLoading).toEqual(true); + }); + }); +}); |