diff options
Diffstat (limited to 'spec/frontend/import_projects/store/actions_spec.js')
-rw-r--r-- | spec/frontend/import_projects/store/actions_spec.js | 221 |
1 files changed, 174 insertions, 47 deletions
diff --git a/spec/frontend/import_projects/store/actions_spec.js b/spec/frontend/import_projects/store/actions_spec.js index fd6fbcbfce0..45a59b3f6d6 100644 --- a/spec/frontend/import_projects/store/actions_spec.js +++ b/spec/frontend/import_projects/store/actions_spec.js @@ -1,7 +1,7 @@ import MockAdapter from 'axios-mock-adapter'; -import createFlash from '~/flash'; import testAction from 'helpers/vuex_action_helper'; import { TEST_HOST } from 'helpers/test_constants'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { @@ -12,41 +12,79 @@ import { RECEIVE_IMPORT_SUCCESS, RECEIVE_IMPORT_ERROR, RECEIVE_JOBS_SUCCESS, + REQUEST_NAMESPACES, + RECEIVE_NAMESPACES_SUCCESS, + RECEIVE_NAMESPACES_ERROR, + SET_PAGE, } from '~/import_projects/store/mutation_types'; -import { - fetchRepos, - fetchImport, - receiveJobsSuccess, - fetchJobs, - clearJobsEtagPoll, - stopJobsPolling, -} from '~/import_projects/store/actions'; +import actionsFactory from '~/import_projects/store/actions'; +import { getImportTarget } from '~/import_projects/store/getters'; import state from '~/import_projects/store/state'; +import { STATUSES } from '~/import_projects/constants'; jest.mock('~/flash'); +const MOCK_ENDPOINT = `${TEST_HOST}/endpoint.json`; +const endpoints = { + reposPath: MOCK_ENDPOINT, + importPath: MOCK_ENDPOINT, + jobsPath: MOCK_ENDPOINT, + namespacesPath: MOCK_ENDPOINT, +}; + +const { + clearJobsEtagPoll, + stopJobsPolling, + importAll, + fetchRepos, + fetchImport, + fetchJobs, + fetchNamespaces, + setPage, +} = actionsFactory({ + endpoints, +}); + describe('import_projects store actions', () => { let localState; - const repos = [{ id: 1 }, { id: 2 }]; - const importPayload = { newName: 'newName', targetNamespace: 'targetNamespace', repo: { id: 1 } }; + const importRepoId = 1; + const otherImportRepoId = 2; + const defaultTargetNamespace = 'default'; + const sanitizedName = 'sanitizedName'; + const defaultImportTarget = { newName: sanitizedName, targetNamespace: defaultTargetNamespace }; beforeEach(() => { - localState = state(); + localState = { + ...state(), + defaultTargetNamespace, + repositories: [ + { importSource: { id: importRepoId, sanitizedName }, importStatus: STATUSES.NONE }, + { + importSource: { id: otherImportRepoId, sanitizedName: 's2' }, + importStatus: STATUSES.NONE, + }, + { + importSource: { id: 3, sanitizedName: 's3', incompatible: true }, + importStatus: STATUSES.NONE, + }, + ], + }; + + localState.getImportTarget = getImportTarget(localState); }); describe('fetchRepos', () => { let mock; - const payload = { imported_projects: [{}], provider_repos: [{}], namespaces: [{}] }; + const payload = { imported_projects: [{}], provider_repos: [{}] }; beforeEach(() => { - localState.reposPath = `${TEST_HOST}/endpoint.json`; mock = new MockAdapter(axios); }); afterEach(() => mock.restore()); it('dispatches stopJobsPolling actions and commits REQUEST_REPOS, RECEIVE_REPOS_SUCCESS mutations on a successful request', () => { - mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, payload); + mock.onGet(MOCK_ENDPOINT).reply(200, payload); return testAction( fetchRepos, @@ -64,7 +102,7 @@ describe('import_projects store actions', () => { }); it('dispatches stopJobsPolling action and commits REQUEST_REPOS, RECEIVE_REPOS_ERROR mutations on an unsuccessful request', () => { - mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); + mock.onGet(MOCK_ENDPOINT).reply(500); return testAction( fetchRepos, @@ -75,18 +113,39 @@ describe('import_projects store actions', () => { ); }); - describe('when filtered', () => { - beforeEach(() => { - localState.filter = 'filter'; + describe('when pagination is enabled', () => { + it('includes page in url query params', async () => { + const { fetchRepos: fetchReposWithPagination } = actionsFactory({ + endpoints, + hasPagination: true, + }); + + let requestedUrl; + mock.onGet().reply(config => { + requestedUrl = config.url; + return [200, payload]; + }); + + await testAction( + fetchReposWithPagination, + null, + localState, + expect.any(Array), + expect.any(Array), + ); + + expect(requestedUrl).toBe(`${MOCK_ENDPOINT}?page=${localState.pageInfo.page}`); }); + }); + describe('when filtered', () => { it('fetches repos with filter applied', () => { mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(200, payload); return testAction( fetchRepos, null, - localState, + { ...localState, filter: 'filter' }, [ { type: REQUEST_REPOS }, { @@ -104,7 +163,6 @@ describe('import_projects store actions', () => { let mock; beforeEach(() => { - localState.importPath = `${TEST_HOST}/endpoint.json`; mock = new MockAdapter(axios); }); @@ -112,15 +170,17 @@ describe('import_projects store actions', () => { it('commits REQUEST_IMPORT and REQUEST_IMPORT_SUCCESS mutations on a successful request', () => { const importedProject = { name: 'imported/project' }; - const importRepoId = importPayload.repo.id; - mock.onPost(`${TEST_HOST}/endpoint.json`).reply(200, importedProject); + mock.onPost(MOCK_ENDPOINT).reply(200, importedProject); return testAction( fetchImport, - importPayload, + importRepoId, localState, [ - { type: REQUEST_IMPORT, payload: importRepoId }, + { + type: REQUEST_IMPORT, + payload: { repoId: importRepoId, importTarget: defaultImportTarget }, + }, { type: RECEIVE_IMPORT_SUCCESS, payload: { @@ -134,15 +194,18 @@ describe('import_projects store actions', () => { }); it('commits REQUEST_IMPORT and RECEIVE_IMPORT_ERROR and shows generic error message on an unsuccessful request', async () => { - mock.onPost(`${TEST_HOST}/endpoint.json`).reply(500); + mock.onPost(MOCK_ENDPOINT).reply(500); await testAction( fetchImport, - importPayload, + importRepoId, localState, [ - { type: REQUEST_IMPORT, payload: importPayload.repo.id }, - { type: RECEIVE_IMPORT_ERROR, payload: importPayload.repo.id }, + { + type: REQUEST_IMPORT, + payload: { repoId: importRepoId, importTarget: defaultImportTarget }, + }, + { type: RECEIVE_IMPORT_ERROR, payload: importRepoId }, ], [], ); @@ -152,15 +215,18 @@ describe('import_projects store actions', () => { it('commits REQUEST_IMPORT and RECEIVE_IMPORT_ERROR and shows detailed error message on an unsuccessful request with errors fields in response', async () => { const ERROR_MESSAGE = 'dummy'; - mock.onPost(`${TEST_HOST}/endpoint.json`).reply(500, { errors: ERROR_MESSAGE }); + mock.onPost(MOCK_ENDPOINT).reply(500, { errors: ERROR_MESSAGE }); await testAction( fetchImport, - importPayload, + importRepoId, localState, [ - { type: REQUEST_IMPORT, payload: importPayload.repo.id }, - { type: RECEIVE_IMPORT_ERROR, payload: importPayload.repo.id }, + { + type: REQUEST_IMPORT, + payload: { repoId: importRepoId, importTarget: defaultImportTarget }, + }, + { type: RECEIVE_IMPORT_ERROR, payload: importRepoId }, ], [], ); @@ -169,24 +235,11 @@ describe('import_projects store actions', () => { }); }); - describe('receiveJobsSuccess', () => { - it(`commits ${RECEIVE_JOBS_SUCCESS} mutation`, () => { - return testAction( - receiveJobsSuccess, - repos, - localState, - [{ type: RECEIVE_JOBS_SUCCESS, payload: repos }], - [], - ); - }); - }); - describe('fetchJobs', () => { let mock; const updatedProjects = [{ name: 'imported/project' }, { name: 'provider/repo' }]; beforeEach(() => { - localState.jobsPath = `${TEST_HOST}/endpoint.json`; mock = new MockAdapter(axios); }); @@ -198,7 +251,7 @@ describe('import_projects store actions', () => { afterEach(() => mock.restore()); it('commits RECEIVE_JOBS_SUCCESS mutation on a successful request', async () => { - mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, updatedProjects); + mock.onGet(MOCK_ENDPOINT).reply(200, updatedProjects); await testAction( fetchJobs, @@ -237,4 +290,78 @@ describe('import_projects store actions', () => { }); }); }); + + describe('fetchNamespaces', () => { + let mock; + const namespaces = [{ full_name: 'test/ns1' }, { full_name: 'test_ns2' }]; + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => mock.restore()); + + it('commits REQUEST_NAMESPACES and RECEIVE_NAMESPACES_SUCCESS on success', async () => { + mock.onGet(MOCK_ENDPOINT).reply(200, namespaces); + + await testAction( + fetchNamespaces, + null, + localState, + [ + { type: REQUEST_NAMESPACES }, + { + type: RECEIVE_NAMESPACES_SUCCESS, + payload: convertObjectPropsToCamelCase(namespaces, { deep: true }), + }, + ], + [], + ); + }); + + it('commits REQUEST_NAMESPACES and RECEIVE_NAMESPACES_ERROR and shows generic error message on an unsuccessful request', async () => { + mock.onGet(MOCK_ENDPOINT).reply(500); + + await testAction( + fetchNamespaces, + null, + localState, + [{ type: REQUEST_NAMESPACES }, { type: RECEIVE_NAMESPACES_ERROR }], + [], + ); + + expect(createFlash).toHaveBeenCalledWith('Requesting namespaces failed'); + }); + }); + + describe('importAll', () => { + it('dispatches multiple fetchImport actions', async () => { + await testAction( + importAll, + null, + localState, + [], + [ + { type: 'fetchImport', payload: importRepoId }, + { type: 'fetchImport', payload: otherImportRepoId }, + ], + ); + }); + + describe('setPage', () => { + it('dispatches fetchRepos and commits setPage when page number differs from current one', async () => { + await testAction( + setPage, + 2, + { ...localState, pageInfo: { page: 1 } }, + [{ type: SET_PAGE, payload: 2 }], + [{ type: 'fetchRepos' }], + ); + }); + + it('does not perform any action if page equals to current one', async () => { + await testAction(setPage, 2, { ...localState, pageInfo: { page: 2 } }, [], []); + }); + }); + }); }); |