diff options
Diffstat (limited to 'spec/frontend/ref')
-rw-r--r-- | spec/frontend/ref/components/ref_selector_spec.js | 532 | ||||
-rw-r--r-- | spec/frontend/ref/stores/actions_spec.js | 180 | ||||
-rw-r--r-- | spec/frontend/ref/stores/getters_spec.js | 36 | ||||
-rw-r--r-- | spec/frontend/ref/stores/mutations_spec.js | 274 |
4 files changed, 1022 insertions, 0 deletions
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js new file mode 100644 index 00000000000..2688e4b3428 --- /dev/null +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -0,0 +1,532 @@ +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import { GlLoadingIcon, GlSearchBoxByType, GlNewDropdownItem, GlIcon } from '@gitlab/ui'; +import { trimText } from 'helpers/text_helper'; +import { sprintf } from '~/locale'; +import RefSelector from '~/ref/components/ref_selector.vue'; +import { X_TOTAL_HEADER, DEFAULT_I18N } from '~/ref/constants'; +import createStore from '~/ref/stores/'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('Ref selector component', () => { + const fixtures = { + branches: getJSONFixture('api/branches/branches.json'), + tags: getJSONFixture('api/tags/tags.json'), + commit: getJSONFixture('api/commits/commit.json'), + }; + + const projectId = '8'; + + let wrapper; + let branchesApiCallSpy; + let tagsApiCallSpy; + let commitApiCallSpy; + + const createComponent = () => { + wrapper = mount(RefSelector, { + propsData: { + projectId, + value: '', + }, + listeners: { + // simulate a parent component v-model binding + input: selectedRef => { + wrapper.setProps({ value: selectedRef }); + }, + }, + stubs: { + GlSearchBoxByType: true, + }, + localVue, + store: createStore(), + }); + }; + + beforeEach(() => { + const mock = new MockAdapter(axios); + gon.api_version = 'v4'; + + branchesApiCallSpy = jest + .fn() + .mockReturnValue([200, fixtures.branches, { [X_TOTAL_HEADER]: '123' }]); + tagsApiCallSpy = jest.fn().mockReturnValue([200, fixtures.tags, { [X_TOTAL_HEADER]: '456' }]); + commitApiCallSpy = jest.fn().mockReturnValue([200, fixtures.commit]); + + mock + .onGet(`/api/v4/projects/${projectId}/repository/branches`) + .reply(config => branchesApiCallSpy(config)); + mock + .onGet(`/api/v4/projects/${projectId}/repository/tags`) + .reply(config => tagsApiCallSpy(config)); + mock + .onGet(new RegExp(`/api/v4/projects/${projectId}/repository/commits/.*`)) + .reply(config => commitApiCallSpy(config)); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + // + // Finders + // + const findButtonContent = () => wrapper.find('[data-testid="button-content"]'); + + const findNoResults = () => wrapper.find('[data-testid="no-results"]'); + + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); + + const findBranchesSection = () => wrapper.find('[data-testid="branches-section"]'); + const findBranchDropdownItems = () => findBranchesSection().findAll(GlNewDropdownItem); + const findFirstBranchDropdownItem = () => findBranchDropdownItems().at(0); + + const findTagsSection = () => wrapper.find('[data-testid="tags-section"]'); + const findTagDropdownItems = () => findTagsSection().findAll(GlNewDropdownItem); + const findFirstTagDropdownItem = () => findTagDropdownItems().at(0); + + const findCommitsSection = () => wrapper.find('[data-testid="commits-section"]'); + const findCommitDropdownItems = () => findCommitsSection().findAll(GlNewDropdownItem); + const findFirstCommitDropdownItem = () => findCommitDropdownItems().at(0); + + // + // Expecters + // + const branchesSectionContainsErrorMessage = () => { + const branchesSection = findBranchesSection(); + + return branchesSection.text().includes(DEFAULT_I18N.branchesErrorMessage); + }; + + const tagsSectionContainsErrorMessage = () => { + const tagsSection = findTagsSection(); + + return tagsSection.text().includes(DEFAULT_I18N.tagsErrorMessage); + }; + + const commitsSectionContainsErrorMessage = () => { + const commitsSection = findCommitsSection(); + + return commitsSection.text().includes(DEFAULT_I18N.commitsErrorMessage); + }; + + // + // Convenience methods + // + const updateQuery = newQuery => { + wrapper.find(GlSearchBoxByType).vm.$emit('input', newQuery); + }; + + const selectFirstBranch = () => { + findFirstBranchDropdownItem().vm.$emit('click'); + }; + + const selectFirstTag = () => { + findFirstTagDropdownItem().vm.$emit('click'); + }; + + const selectFirstCommit = () => { + findFirstCommitDropdownItem().vm.$emit('click'); + }; + + const waitForRequests = ({ andClearMocks } = { andClearMocks: false }) => + axios.waitForAll().then(() => { + if (andClearMocks) { + branchesApiCallSpy.mockClear(); + tagsApiCallSpy.mockClear(); + commitApiCallSpy.mockClear(); + } + }); + + describe('initialization behavior', () => { + beforeEach(createComponent); + + it('initializes the dropdown with branches and tags when mounted', () => { + return waitForRequests().then(() => { + expect(branchesApiCallSpy).toHaveBeenCalledTimes(1); + expect(tagsApiCallSpy).toHaveBeenCalledTimes(1); + expect(commitApiCallSpy).not.toHaveBeenCalled(); + }); + }); + + it('shows a spinner while network requests are in progress', () => { + expect(findLoadingIcon().exists()).toBe(true); + + return waitForRequests().then(() => { + expect(findLoadingIcon().exists()).toBe(false); + }); + }); + }); + + describe('post-initialization behavior', () => { + describe('when the search query is updated', () => { + beforeEach(() => { + createComponent(); + + return waitForRequests({ andClearMocks: true }); + }); + + it('requeries the endpoints when the search query is updated', () => { + updateQuery('v1.2.3'); + + return waitForRequests().then(() => { + expect(branchesApiCallSpy).toHaveBeenCalledTimes(1); + expect(tagsApiCallSpy).toHaveBeenCalledTimes(1); + }); + }); + + it("does not make a call to the commit endpoint if the query doesn't look like a SHA", () => { + updateQuery('not a sha'); + + return waitForRequests().then(() => { + expect(commitApiCallSpy).not.toHaveBeenCalled(); + }); + }); + + it('searches for a commit if the query could potentially be a SHA', () => { + updateQuery('abcdef'); + + return waitForRequests().then(() => { + expect(commitApiCallSpy).toHaveBeenCalled(); + }); + }); + }); + + describe('when no results are found', () => { + beforeEach(() => { + branchesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]); + tagsApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]); + commitApiCallSpy = jest.fn().mockReturnValue([404]); + + createComponent(); + + return waitForRequests(); + }); + + describe('when the search query is empty', () => { + it('renders a "no results" message', () => { + expect(findNoResults().text()).toBe(DEFAULT_I18N.noResults); + }); + }); + + describe('when the search query is not empty', () => { + const query = 'hello'; + + beforeEach(() => { + updateQuery(query); + + return waitForRequests(); + }); + + it('renders a "no results" message that includes the search query', () => { + expect(findNoResults().text()).toBe(sprintf(DEFAULT_I18N.noResultsWithQuery, { query })); + }); + }); + }); + + describe('branches', () => { + describe('when the branches search returns results', () => { + beforeEach(() => { + createComponent(); + + return waitForRequests(); + }); + + it('renders the branches section in the dropdown', () => { + expect(findBranchesSection().exists()).toBe(true); + }); + + it('renders the "Branches" heading with a total number indicator', () => { + expect( + findBranchesSection() + .find('[data-testid="section-header"]') + .text(), + ).toBe('Branches 123'); + }); + + it("does not render an error message in the branches section's body", () => { + expect(branchesSectionContainsErrorMessage()).toBe(false); + }); + + it('renders each non-default branch as a selectable item', () => { + const dropdownItems = findBranchDropdownItems(); + + fixtures.branches.forEach((b, i) => { + if (!b.default) { + expect(dropdownItems.at(i).text()).toBe(b.name); + } + }); + }); + + it('renders the default branch as a selectable item with a "default" badge', () => { + const dropdownItems = findBranchDropdownItems(); + + const defaultBranch = fixtures.branches.find(b => b.default); + const defaultBranchIndex = fixtures.branches.indexOf(defaultBranch); + + expect(trimText(dropdownItems.at(defaultBranchIndex).text())).toBe( + `${defaultBranch.name} default`, + ); + }); + }); + + describe('when the branches search returns no results', () => { + beforeEach(() => { + branchesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]); + + createComponent(); + + return waitForRequests(); + }); + + it('does not render the branches section in the dropdown', () => { + expect(findBranchesSection().exists()).toBe(false); + }); + }); + + describe('when the branches search returns an error', () => { + beforeEach(() => { + branchesApiCallSpy = jest.fn().mockReturnValue([500]); + + createComponent(); + + return waitForRequests(); + }); + + it('renders the branches section in the dropdown', () => { + expect(findBranchesSection().exists()).toBe(true); + }); + + it("renders an error message in the branches section's body", () => { + expect(branchesSectionContainsErrorMessage()).toBe(true); + }); + }); + }); + + describe('tags', () => { + describe('when the tags search returns results', () => { + beforeEach(() => { + createComponent(); + + return waitForRequests(); + }); + + it('renders the tags section in the dropdown', () => { + expect(findTagsSection().exists()).toBe(true); + }); + + it('renders the "Tags" heading with a total number indicator', () => { + expect( + findTagsSection() + .find('[data-testid="section-header"]') + .text(), + ).toBe('Tags 456'); + }); + + it("does not render an error message in the tags section's body", () => { + expect(tagsSectionContainsErrorMessage()).toBe(false); + }); + + it('renders each tag as a selectable item', () => { + const dropdownItems = findTagDropdownItems(); + + fixtures.tags.forEach((t, i) => { + expect(dropdownItems.at(i).text()).toBe(t.name); + }); + }); + }); + + describe('when the tags search returns no results', () => { + beforeEach(() => { + tagsApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]); + + createComponent(); + + return waitForRequests(); + }); + + it('does not render the tags section in the dropdown', () => { + expect(findTagsSection().exists()).toBe(false); + }); + }); + + describe('when the tags search returns an error', () => { + beforeEach(() => { + tagsApiCallSpy = jest.fn().mockReturnValue([500]); + + createComponent(); + + return waitForRequests(); + }); + + it('renders the tags section in the dropdown', () => { + expect(findTagsSection().exists()).toBe(true); + }); + + it("renders an error message in the tags section's body", () => { + expect(tagsSectionContainsErrorMessage()).toBe(true); + }); + }); + }); + + describe('commits', () => { + describe('when the commit search returns results', () => { + beforeEach(() => { + createComponent(); + + updateQuery('abcd1234'); + + return waitForRequests(); + }); + + it('renders the commit section in the dropdown', () => { + expect(findCommitsSection().exists()).toBe(true); + }); + + it('renders the "Commits" heading with a total number indicator', () => { + expect( + findCommitsSection() + .find('[data-testid="section-header"]') + .text(), + ).toBe('Commits 1'); + }); + + it("does not render an error message in the comits section's body", () => { + expect(commitsSectionContainsErrorMessage()).toBe(false); + }); + + it('renders each commit as a selectable item with the short SHA and commit title', () => { + const dropdownItems = findCommitDropdownItems(); + + const { commit } = fixtures; + + expect(dropdownItems.at(0).text()).toBe(`${commit.short_id} ${commit.title}`); + }); + }); + + describe('when the commit search returns no results (i.e. a 404)', () => { + beforeEach(() => { + commitApiCallSpy = jest.fn().mockReturnValue([404]); + + createComponent(); + + updateQuery('abcd1234'); + + return waitForRequests(); + }); + + it('does not render the commits section in the dropdown', () => { + expect(findCommitsSection().exists()).toBe(false); + }); + }); + + describe('when the commit search returns an error (other than a 404)', () => { + beforeEach(() => { + commitApiCallSpy = jest.fn().mockReturnValue([500]); + + createComponent(); + + updateQuery('abcd1234'); + + return waitForRequests(); + }); + + it('renders the commits section in the dropdown', () => { + expect(findCommitsSection().exists()).toBe(true); + }); + + it("renders an error message in the commits section's body", () => { + expect(commitsSectionContainsErrorMessage()).toBe(true); + }); + }); + }); + + describe('selection', () => { + beforeEach(() => { + createComponent(); + + updateQuery(fixtures.commit.short_id); + + return waitForRequests(); + }); + + it('renders a checkmark by the selected item', () => { + expect(findFirstBranchDropdownItem().find(GlIcon).element).toHaveClass( + 'gl-visibility-hidden', + ); + + selectFirstBranch(); + + return localVue.nextTick().then(() => { + expect(findFirstBranchDropdownItem().find(GlIcon).element).not.toHaveClass( + 'gl-visibility-hidden', + ); + }); + }); + + describe('when a branch is seleceted', () => { + it("displays the branch name in the dropdown's button", () => { + expect(findButtonContent().text()).toBe(DEFAULT_I18N.noRefSelected); + + selectFirstBranch(); + + return localVue.nextTick().then(() => { + expect(findButtonContent().text()).toBe(fixtures.branches[0].name); + }); + }); + + it("updates the v-model binding with the branch's name", () => { + expect(wrapper.vm.value).toEqual(''); + + selectFirstBranch(); + + expect(wrapper.vm.value).toEqual(fixtures.branches[0].name); + }); + }); + + describe('when a tag is seleceted', () => { + it("displays the tag name in the dropdown's button", () => { + expect(findButtonContent().text()).toBe(DEFAULT_I18N.noRefSelected); + + selectFirstTag(); + + return localVue.nextTick().then(() => { + expect(findButtonContent().text()).toBe(fixtures.tags[0].name); + }); + }); + + it("updates the v-model binding with the tag's name", () => { + expect(wrapper.vm.value).toEqual(''); + + selectFirstTag(); + + expect(wrapper.vm.value).toEqual(fixtures.tags[0].name); + }); + }); + + describe('when a commit is selected', () => { + it("displays the full SHA in the dropdown's button", () => { + expect(findButtonContent().text()).toBe(DEFAULT_I18N.noRefSelected); + + selectFirstCommit(); + + return localVue.nextTick().then(() => { + expect(findButtonContent().text()).toBe(fixtures.commit.id); + }); + }); + + it("updates the v-model binding with the commit's full SHA", () => { + expect(wrapper.vm.value).toEqual(''); + + selectFirstCommit(); + + expect(wrapper.vm.value).toEqual(fixtures.commit.id); + }); + }); + }); + }); +}); diff --git a/spec/frontend/ref/stores/actions_spec.js b/spec/frontend/ref/stores/actions_spec.js new file mode 100644 index 00000000000..32966354c95 --- /dev/null +++ b/spec/frontend/ref/stores/actions_spec.js @@ -0,0 +1,180 @@ +import testAction from 'helpers/vuex_action_helper'; +import createState from '~/ref/stores/state'; +import * as actions from '~/ref/stores/actions'; +import * as types from '~/ref/stores/mutation_types'; + +let mockBranchesReturnValue; +let mockTagsReturnValue; +let mockCommitReturnValue; + +jest.mock('~/api', () => ({ + // `__esModule: true` is required when mocking modules with default exports: + // https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options + __esModule: true, + default: { + branches: () => mockBranchesReturnValue, + tags: () => mockTagsReturnValue, + commit: () => mockCommitReturnValue, + }, +})); + +describe('Ref selector Vuex store actions', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + describe('setProjectId', () => { + it(`commits ${types.SET_PROJECT_ID} with the new project ID`, () => { + const projectId = '4'; + testAction(actions.setProjectId, projectId, state, [ + { type: types.SET_PROJECT_ID, payload: projectId }, + ]); + }); + }); + + describe('setSelectedRef', () => { + it(`commits ${types.SET_SELECTED_REF} with the new selected ref name`, () => { + const selectedRef = 'v1.2.3'; + testAction(actions.setSelectedRef, selectedRef, state, [ + { type: types.SET_SELECTED_REF, payload: selectedRef }, + ]); + }); + }); + + describe('search', () => { + it(`commits ${types.SET_QUERY} with the new search query`, () => { + const query = 'hello'; + testAction( + actions.search, + query, + state, + [{ type: types.SET_QUERY, payload: query }], + [{ type: 'searchBranches' }, { type: 'searchTags' }, { type: 'searchCommits' }], + ); + }); + }); + + describe('searchBranches', () => { + describe('when the search is successful', () => { + const branchesApiResponse = { data: [{ name: 'my-feature-branch' }] }; + + beforeEach(() => { + mockBranchesReturnValue = Promise.resolve(branchesApiResponse); + }); + + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_BRANCHES_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchBranches, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_BRANCHES_SUCCESS, payload: branchesApiResponse }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + + describe('when the search fails', () => { + const error = new Error('Something went wrong!'); + + beforeEach(() => { + mockBranchesReturnValue = Promise.reject(error); + }); + + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_BRANCHES_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchBranches, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_BRANCHES_ERROR, payload: error }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + }); + + describe('searchTags', () => { + describe('when the search is successful', () => { + const tagsApiResponse = { data: [{ name: 'v1.2.3' }] }; + + beforeEach(() => { + mockTagsReturnValue = Promise.resolve(tagsApiResponse); + }); + + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_TAGS_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchTags, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_TAGS_SUCCESS, payload: tagsApiResponse }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + + describe('when the search fails', () => { + const error = new Error('Something went wrong!'); + + beforeEach(() => { + mockTagsReturnValue = Promise.reject(error); + }); + + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_TAGS_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchTags, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_TAGS_ERROR, payload: error }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + }); + + describe('searchCommits', () => { + describe('when the search query potentially matches a commit SHA', () => { + beforeEach(() => { + state.isQueryPossiblyASha = true; + }); + + describe('when the search is successful', () => { + const commitApiResponse = { data: [{ id: 'abcd1234' }] }; + + beforeEach(() => { + mockCommitReturnValue = Promise.resolve(commitApiResponse); + }); + + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_COMMITS_SUCCESS} with the response from the API, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchCommits, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_COMMITS_SUCCESS, payload: commitApiResponse }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + + describe('when the search fails', () => { + const error = new Error('Something went wrong!'); + + beforeEach(() => { + mockCommitReturnValue = Promise.reject(error); + }); + + describe('when the search query might match a commit SHA', () => { + it(`commits ${types.REQUEST_START}, ${types.RECEIVE_COMMITS_ERROR} with the error object, and ${types.REQUEST_FINISH}`, () => { + return testAction(actions.searchCommits, undefined, state, [ + { type: types.REQUEST_START }, + { type: types.RECEIVE_COMMITS_ERROR, payload: error }, + { type: types.REQUEST_FINISH }, + ]); + }); + }); + }); + }); + + describe('when the search query will not match a commit SHA', () => { + beforeEach(() => { + state.isQueryPossiblyASha = false; + }); + + it(`commits ${types.RESET_COMMIT_MATCHES}`, () => { + return testAction(actions.searchCommits, undefined, state, [ + { type: types.RESET_COMMIT_MATCHES }, + ]); + }); + }); + }); +}); diff --git a/spec/frontend/ref/stores/getters_spec.js b/spec/frontend/ref/stores/getters_spec.js new file mode 100644 index 00000000000..49d74e5b9e4 --- /dev/null +++ b/spec/frontend/ref/stores/getters_spec.js @@ -0,0 +1,36 @@ +import * as getters from '~/ref/stores/getters'; + +describe('Ref selector Vuex store getters', () => { + describe('isQueryPossiblyASha', () => { + it.each` + query | isPossiblyASha + ${'abcd'} | ${true} + ${'ABCD'} | ${true} + ${'0123456789abcdef0123456789abcdef01234567'} | ${true} + ${'0123456789abcdef0123456789abcdef012345678'} | ${false} + ${'abc'} | ${false} + ${'ghij'} | ${false} + ${' abcd'} | ${false} + ${''} | ${false} + ${null} | ${false} + ${undefined} | ${false} + `( + 'returns true when the query potentially refers to a commit SHA', + ({ query, isPossiblyASha }) => { + expect(getters.isQueryPossiblyASha({ query })).toBe(isPossiblyASha); + }, + ); + }); + + describe('isLoading', () => { + it.each` + requestCount | isLoading + ${2} | ${true} + ${1} | ${true} + ${0} | ${false} + ${-1} | ${false} + `('returns true when at least one request is in progress', ({ requestCount, isLoading }) => { + expect(getters.isLoading({ requestCount })).toBe(isLoading); + }); + }); +}); diff --git a/spec/frontend/ref/stores/mutations_spec.js b/spec/frontend/ref/stores/mutations_spec.js new file mode 100644 index 00000000000..78117436c33 --- /dev/null +++ b/spec/frontend/ref/stores/mutations_spec.js @@ -0,0 +1,274 @@ +import createState from '~/ref/stores/state'; +import mutations from '~/ref/stores/mutations'; +import * as types from '~/ref/stores/mutation_types'; +import { X_TOTAL_HEADER } from '~/ref/constants'; + +describe('Ref selector Vuex store mutations', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + describe('initial state', () => { + it('is created with the correct structure and initial values', () => { + expect(state).toEqual({ + projectId: null, + + query: '', + matches: { + branches: { + list: [], + totalCount: 0, + error: null, + }, + tags: { + list: [], + totalCount: 0, + error: null, + }, + commits: { + list: [], + totalCount: 0, + error: null, + }, + }, + selectedRef: null, + requestCount: 0, + }); + }); + }); + + describe(`${types.SET_PROJECT_ID}`, () => { + it('updates the project ID', () => { + const newProjectId = '4'; + mutations[types.SET_PROJECT_ID](state, newProjectId); + + expect(state.projectId).toBe(newProjectId); + }); + }); + + describe(`${types.SET_SELECTED_REF}`, () => { + it('updates the selected ref', () => { + const newSelectedRef = 'my-feature-branch'; + mutations[types.SET_SELECTED_REF](state, newSelectedRef); + + expect(state.selectedRef).toBe(newSelectedRef); + }); + }); + + describe(`${types.SET_QUERY}`, () => { + it('updates the search query', () => { + const newQuery = 'hello'; + mutations[types.SET_QUERY](state, newQuery); + + expect(state.query).toBe(newQuery); + }); + }); + + describe(`${types.REQUEST_START}`, () => { + it('increments requestCount by 1', () => { + mutations[types.REQUEST_START](state); + expect(state.requestCount).toBe(1); + + mutations[types.REQUEST_START](state); + expect(state.requestCount).toBe(2); + + mutations[types.REQUEST_START](state); + expect(state.requestCount).toBe(3); + }); + }); + + describe(`${types.REQUEST_FINISH}`, () => { + it('decrements requestCount by 1', () => { + state.requestCount = 3; + + mutations[types.REQUEST_FINISH](state); + expect(state.requestCount).toBe(2); + + mutations[types.REQUEST_FINISH](state); + expect(state.requestCount).toBe(1); + + mutations[types.REQUEST_FINISH](state); + expect(state.requestCount).toBe(0); + }); + }); + + describe(`${types.RECEIVE_BRANCHES_SUCCESS}`, () => { + it('updates state.matches.branches based on the provided API response', () => { + const response = { + data: [ + { + name: 'master', + default: true, + + // everything except "name" and "default" should be stripped + merged: false, + protected: true, + }, + { + name: 'my-feature-branch', + default: false, + }, + ], + headers: { + [X_TOTAL_HEADER]: 37, + }, + }; + + mutations[types.RECEIVE_BRANCHES_SUCCESS](state, response); + + expect(state.matches.branches).toEqual({ + list: [ + { + name: 'master', + default: true, + }, + { + name: 'my-feature-branch', + default: false, + }, + ], + totalCount: 37, + error: null, + }); + }); + }); + + describe(`${types.RECEIVE_BRANCHES_ERROR}`, () => { + it('updates state.matches.branches to an empty state with the error object', () => { + const error = new Error('Something went wrong!'); + + state.matches.branches = { + list: [{ name: 'my-feature-branch' }], + totalCount: 1, + error: null, + }; + + mutations[types.RECEIVE_BRANCHES_ERROR](state, error); + + expect(state.matches.branches).toEqual({ + list: [], + totalCount: 0, + error, + }); + }); + }); + + describe(`${types.RECEIVE_REQUEST_TAGS_SUCCESS}`, () => { + it('updates state.matches.tags based on the provided API response', () => { + const response = { + data: [ + { + name: 'v1.2', + + // everything except "name" should be stripped + target: '2695effb5807a22ff3d138d593fd856244e155e7', + }, + ], + headers: { + [X_TOTAL_HEADER]: 23, + }, + }; + + mutations[types.RECEIVE_TAGS_SUCCESS](state, response); + + expect(state.matches.tags).toEqual({ + list: [ + { + name: 'v1.2', + }, + ], + totalCount: 23, + error: null, + }); + }); + }); + + describe(`${types.RECEIVE_TAGS_ERROR}`, () => { + it('updates state.matches.tags to an empty state with the error object', () => { + const error = new Error('Something went wrong!'); + + state.matches.tags = { + list: [{ name: 'v1.2' }], + totalCount: 1, + error: null, + }; + + mutations[types.RECEIVE_TAGS_ERROR](state, error); + + expect(state.matches.tags).toEqual({ + list: [], + totalCount: 0, + error, + }); + }); + }); + + describe(`${types.RECEIVE_COMMITS_SUCCESS}`, () => { + it('updates state.matches.commits based on the provided API response', () => { + const response = { + data: { + id: '2695effb5807a22ff3d138d593fd856244e155e7', + short_id: '2695effb580', + title: 'Initial commit', + + // everything except "id", "short_id", and "title" should be stripped + author_name: 'Example User', + }, + }; + + mutations[types.RECEIVE_COMMITS_SUCCESS](state, response); + + expect(state.matches.commits).toEqual({ + list: [ + { + name: '2695effb580', + value: '2695effb5807a22ff3d138d593fd856244e155e7', + subtitle: 'Initial commit', + }, + ], + totalCount: 1, + error: null, + }); + }); + }); + + describe(`${types.RECEIVE_COMMITS_ERROR}`, () => { + it('updates state.matches.commits to an empty state with the error object', () => { + const error = new Error('Something went wrong!'); + + state.matches.commits = { + list: [{ name: 'abcd0123' }], + totalCount: 1, + error: null, + }; + + mutations[types.RECEIVE_COMMITS_ERROR](state, error); + + expect(state.matches.commits).toEqual({ + list: [], + totalCount: 0, + error, + }); + }); + }); + + describe(`${types.RESET_COMMIT_MATCHES}`, () => { + it('resets the commit results back to their original (empty) state', () => { + state.matches.commits = { + list: [{ name: 'abcd0123' }], + totalCount: 1, + error: null, + }; + + mutations[types.RESET_COMMIT_MATCHES](state); + + expect(state.matches.commits).toEqual({ + list: [], + totalCount: 0, + error: null, + }); + }); + }); +}); |