diff options
Diffstat (limited to 'spec/frontend/releases/stores/modules/list/actions_spec.js')
-rw-r--r-- | spec/frontend/releases/stores/modules/list/actions_spec.js | 336 |
1 files changed, 215 insertions, 121 deletions
diff --git a/spec/frontend/releases/stores/modules/list/actions_spec.js b/spec/frontend/releases/stores/modules/list/actions_spec.js index 95e30659d6c..4e235e1d00f 100644 --- a/spec/frontend/releases/stores/modules/list/actions_spec.js +++ b/spec/frontend/releases/stores/modules/list/actions_spec.js @@ -1,31 +1,42 @@ import { cloneDeep } from 'lodash'; import testAction from 'helpers/vuex_action_helper'; +import { getJSONFixture } from 'helpers/fixtures'; import { - requestReleases, fetchReleases, - receiveReleasesSuccess, + fetchReleasesGraphQl, + fetchReleasesRest, receiveReleasesError, } from '~/releases/stores/modules/list/actions'; import createState from '~/releases/stores/modules/list/state'; import * as types from '~/releases/stores/modules/list/mutation_types'; import api from '~/api'; -import { gqClient, convertGraphQLResponse } from '~/releases/util'; -import { parseIntPagination, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import { gqClient, convertAllReleasesGraphQLResponse } from '~/releases/util'; import { - pageInfoHeadersWithoutPagination, - releases as originalReleases, - graphqlReleasesResponse as originalGraphqlReleasesResponse, -} from '../../../mock_data'; + normalizeHeaders, + parseIntPagination, + convertObjectPropsToCamelCase, +} from '~/lib/utils/common_utils'; +import { pageInfoHeadersWithoutPagination } from '../../../mock_data'; import allReleasesQuery from '~/releases/queries/all_releases.query.graphql'; +import { PAGE_SIZE } from '~/releases/constants'; + +const originalRelease = getJSONFixture('api/releases/release.json'); +const originalReleases = [originalRelease]; + +const originalGraphqlReleasesResponse = getJSONFixture( + 'graphql/releases/queries/all_releases.query.graphql.json', +); describe('Releases State actions', () => { let mockedState; - let pageInfo; let releases; let graphqlReleasesResponse; const projectPath = 'root/test-project'; const projectId = 19; + const before = 'testBeforeCursor'; + const after = 'testAfterCursor'; + const page = 2; beforeEach(() => { mockedState = { @@ -33,178 +44,261 @@ describe('Releases State actions', () => { projectId, projectPath, }), - featureFlags: { - graphqlReleaseData: true, - graphqlReleasesPage: true, - graphqlMilestoneStats: true, - }, }; - pageInfo = parseIntPagination(pageInfoHeadersWithoutPagination); releases = convertObjectPropsToCamelCase(originalReleases, { deep: true }); graphqlReleasesResponse = cloneDeep(originalGraphqlReleasesResponse); }); - describe('requestReleases', () => { - it('should commit REQUEST_RELEASES mutation', done => { - testAction(requestReleases, null, mockedState, [{ type: types.REQUEST_RELEASES }], [], done); + describe('when all the necessary GraphQL feature flags are enabled', () => { + beforeEach(() => { + mockedState.useGraphQLEndpoint = true; + }); + + describe('fetchReleases', () => { + it('dispatches fetchReleasesGraphQl with before and after parameters', () => { + return testAction( + fetchReleases, + { before, after, page }, + mockedState, + [], + [ + { + type: 'fetchReleasesGraphQl', + payload: { before, after }, + }, + ], + ); + }); }); }); - describe('fetchReleases', () => { - describe('success', () => { - it('dispatches requestReleases and receiveReleasesSuccess', done => { - jest.spyOn(gqClient, 'query').mockImplementation(({ query, variables }) => { - expect(query).toBe(allReleasesQuery); - expect(variables).toEqual({ - fullPath: projectPath, + describe('when at least one of the GraphQL feature flags is disabled', () => { + beforeEach(() => { + mockedState.useGraphQLEndpoint = false; + }); + + describe('fetchReleases', () => { + it('dispatches fetchReleasesRest with a page parameter', () => { + return testAction( + fetchReleases, + { before, after, page }, + mockedState, + [], + [ + { + type: 'fetchReleasesRest', + payload: { page }, + }, + ], + ); + }); + }); + }); + + describe('fetchReleasesGraphQl', () => { + describe('GraphQL query variables', () => { + let vuexParams; + + beforeEach(() => { + jest.spyOn(gqClient, 'query'); + + vuexParams = { dispatch: jest.fn(), commit: jest.fn(), state: mockedState }; + }); + + describe('when neither a before nor an after parameter is provided', () => { + beforeEach(() => { + fetchReleasesGraphQl(vuexParams, { before: undefined, after: undefined }); + }); + + it('makes a GraphQl query with a first variable', () => { + expect(gqClient.query).toHaveBeenCalledWith({ + query: allReleasesQuery, + variables: { fullPath: projectPath, first: PAGE_SIZE }, }); - return Promise.resolve(graphqlReleasesResponse); }); + }); - testAction( - fetchReleases, + describe('when only a before parameter is provided', () => { + beforeEach(() => { + fetchReleasesGraphQl(vuexParams, { before, after: undefined }); + }); + + it('makes a GraphQl query with last and before variables', () => { + expect(gqClient.query).toHaveBeenCalledWith({ + query: allReleasesQuery, + variables: { fullPath: projectPath, last: PAGE_SIZE, before }, + }); + }); + }); + + describe('when only an after parameter is provided', () => { + beforeEach(() => { + fetchReleasesGraphQl(vuexParams, { before: undefined, after }); + }); + + it('makes a GraphQl query with first and after variables', () => { + expect(gqClient.query).toHaveBeenCalledWith({ + query: allReleasesQuery, + variables: { fullPath: projectPath, first: PAGE_SIZE, after }, + }); + }); + }); + + describe('when both before and after parameters are provided', () => { + it('throws an error', () => { + const callFetchReleasesGraphQl = () => { + fetchReleasesGraphQl(vuexParams, { before, after }); + }; + + expect(callFetchReleasesGraphQl).toThrowError( + 'Both a `before` and an `after` parameter were provided to fetchReleasesGraphQl. These parameters cannot be used together.', + ); + }); + }); + }); + + describe('when the request is successful', () => { + beforeEach(() => { + jest.spyOn(gqClient, 'query').mockResolvedValue(graphqlReleasesResponse); + }); + + it(`commits ${types.REQUEST_RELEASES} and ${types.RECEIVE_RELEASES_SUCCESS}`, () => { + const convertedResponse = convertAllReleasesGraphQLResponse(graphqlReleasesResponse); + + return testAction( + fetchReleasesGraphQl, {}, mockedState, - [], [ { - type: 'requestReleases', + type: types.REQUEST_RELEASES, }, { - payload: convertGraphQLResponse(graphqlReleasesResponse), - type: 'receiveReleasesSuccess', + type: types.RECEIVE_RELEASES_SUCCESS, + payload: { + data: convertedResponse.data, + graphQlPageInfo: convertedResponse.paginationInfo, + }, }, ], - done, + [], ); }); }); - describe('error', () => { - it('dispatches requestReleases and receiveReleasesError', done => { - jest.spyOn(gqClient, 'query').mockRejectedValue(); + describe('when the request fails', () => { + beforeEach(() => { + jest.spyOn(gqClient, 'query').mockRejectedValue(new Error('Something went wrong!')); + }); - testAction( - fetchReleases, + it(`commits ${types.REQUEST_RELEASES} and dispatch receiveReleasesError`, () => { + return testAction( + fetchReleasesGraphQl, {}, mockedState, - [], [ { - type: 'requestReleases', + type: types.REQUEST_RELEASES, }, + ], + [ { type: 'receiveReleasesError', }, ], - done, ); }); }); + }); + + describe('fetchReleasesRest', () => { + describe('REST query parameters', () => { + let vuexParams; - describe('when the graphqlReleaseData feature flag is disabled', () => { beforeEach(() => { - mockedState.featureFlags.graphqlReleasesPage = false; - }); + jest + .spyOn(api, 'releases') + .mockResolvedValue({ data: releases, headers: pageInfoHeadersWithoutPagination }); - describe('success', () => { - it('dispatches requestReleases and receiveReleasesSuccess', done => { - jest.spyOn(api, 'releases').mockImplementation((id, options) => { - expect(id).toBe(projectId); - expect(options.page).toBe('1'); - return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination }); - }); + vuexParams = { dispatch: jest.fn(), commit: jest.fn(), state: mockedState }; + }); - testAction( - fetchReleases, - {}, - mockedState, - [], - [ - { - type: 'requestReleases', - }, - { - payload: { data: releases, headers: pageInfoHeadersWithoutPagination }, - type: 'receiveReleasesSuccess', - }, - ], - done, - ); + describe('when a page parameter is provided', () => { + beforeEach(() => { + fetchReleasesRest(vuexParams, { page: 2 }); }); - it('dispatches requestReleases and receiveReleasesSuccess on page two', done => { - jest.spyOn(api, 'releases').mockImplementation((_, options) => { - expect(options.page).toBe('2'); - return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination }); - }); - - testAction( - fetchReleases, - { page: '2' }, - mockedState, - [], - [ - { - type: 'requestReleases', - }, - { - payload: { data: releases, headers: pageInfoHeadersWithoutPagination }, - type: 'receiveReleasesSuccess', - }, - ], - done, - ); + it('makes a REST query with a page query parameter', () => { + expect(api.releases).toHaveBeenCalledWith(projectId, { page }); }); }); + }); - describe('error', () => { - it('dispatches requestReleases and receiveReleasesError', done => { - jest.spyOn(api, 'releases').mockReturnValue(Promise.reject()); + describe('when the request is successful', () => { + beforeEach(() => { + jest + .spyOn(api, 'releases') + .mockResolvedValue({ data: releases, headers: pageInfoHeadersWithoutPagination }); + }); - testAction( - fetchReleases, - {}, - mockedState, - [], - [ - { - type: 'requestReleases', - }, - { - type: 'receiveReleasesError', + it(`commits ${types.REQUEST_RELEASES} and ${types.RECEIVE_RELEASES_SUCCESS}`, () => { + return testAction( + fetchReleasesRest, + {}, + mockedState, + [ + { + type: types.REQUEST_RELEASES, + }, + { + type: types.RECEIVE_RELEASES_SUCCESS, + payload: { + data: convertObjectPropsToCamelCase(releases, { deep: true }), + restPageInfo: parseIntPagination( + normalizeHeaders(pageInfoHeadersWithoutPagination), + ), }, - ], - done, - ); - }); + }, + ], + [], + ); }); }); - }); - describe('receiveReleasesSuccess', () => { - it('should commit RECEIVE_RELEASES_SUCCESS mutation', done => { - testAction( - receiveReleasesSuccess, - { data: releases, headers: pageInfoHeadersWithoutPagination }, - mockedState, - [{ type: types.RECEIVE_RELEASES_SUCCESS, payload: { pageInfo, data: releases } }], - [], - done, - ); + describe('when the request fails', () => { + beforeEach(() => { + jest.spyOn(api, 'releases').mockRejectedValue(new Error('Something went wrong!')); + }); + + it(`commits ${types.REQUEST_RELEASES} and dispatch receiveReleasesError`, () => { + return testAction( + fetchReleasesRest, + {}, + mockedState, + [ + { + type: types.REQUEST_RELEASES, + }, + ], + [ + { + type: 'receiveReleasesError', + }, + ], + ); + }); }); }); describe('receiveReleasesError', () => { - it('should commit RECEIVE_RELEASES_ERROR mutation', done => { - testAction( + it('should commit RECEIVE_RELEASES_ERROR mutation', () => { + return testAction( receiveReleasesError, null, mockedState, [{ type: types.RECEIVE_RELEASES_ERROR }], [], - done, ); }); }); |