diff options
Diffstat (limited to 'spec/frontend/jira_connect')
-rw-r--r-- | spec/frontend/jira_connect/branches/components/new_branch_form_spec.js | 236 | ||||
-rw-r--r-- | spec/frontend/jira_connect/branches/pages/index_spec.js | 65 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/api_spec.js (renamed from spec/frontend/jira_connect/api_spec.js) | 6 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/__snapshots__/group_item_name_spec.js.snap (renamed from spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap) | 0 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/app_spec.js (renamed from spec/frontend/jira_connect/components/app_spec.js) | 8 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/group_item_name_spec.js (renamed from spec/frontend/jira_connect/components/group_item_name_spec.js) | 2 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js (renamed from spec/frontend/jira_connect/components/groups_list_item_spec.js) | 10 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js (renamed from spec/frontend/jira_connect/components/groups_list_spec.js) | 10 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js (renamed from spec/frontend/jira_connect/components/subscriptions_list_spec.js) | 12 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/index_spec.js (renamed from spec/frontend/jira_connect/index_spec.js) | 4 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/mock_data.js (renamed from spec/frontend/jira_connect/mock_data.js) | 0 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/store/mutations_spec.js (renamed from spec/frontend/jira_connect/store/mutations_spec.js) | 4 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/utils_spec.js (renamed from spec/frontend/jira_connect/utils_spec.js) | 4 |
13 files changed, 331 insertions, 30 deletions
diff --git a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js new file mode 100644 index 00000000000..7326b84ad54 --- /dev/null +++ b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js @@ -0,0 +1,236 @@ +import { GlAlert, GlForm, GlFormInput, GlButton } from '@gitlab/ui'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import NewBranchForm from '~/jira_connect/branches/components/new_branch_form.vue'; +import ProjectDropdown from '~/jira_connect/branches/components/project_dropdown.vue'; +import SourceBranchDropdown from '~/jira_connect/branches/components/source_branch_dropdown.vue'; +import { + CREATE_BRANCH_ERROR_GENERIC, + CREATE_BRANCH_ERROR_WITH_CONTEXT, +} from '~/jira_connect/branches/constants'; +import createBranchMutation from '~/jira_connect/branches/graphql/mutations/create_branch.mutation.graphql'; + +const mockProject = { + id: 'test', + fullPath: 'test-path', + repository: { + branchNames: ['main', 'f-test', 'release'], + rootRef: 'main', + }, +}; +const mockCreateBranchMutationResponse = { + data: { + createBranch: { + clientMutationId: 1, + errors: [], + }, + }, +}; +const mockCreateBranchMutationResponseWithErrors = { + data: { + createBranch: { + clientMutationId: 1, + errors: ['everything is broken, sorry.'], + }, + }, +}; +const mockCreateBranchMutationSuccess = jest + .fn() + .mockResolvedValue(mockCreateBranchMutationResponse); +const mockCreateBranchMutationWithErrors = jest + .fn() + .mockResolvedValue(mockCreateBranchMutationResponseWithErrors); +const mockCreateBranchMutationFailed = jest.fn().mockRejectedValue(new Error('GraphQL error')); +const mockMutationLoading = jest.fn().mockReturnValue(new Promise(() => {})); + +const localVue = createLocalVue(); + +describe('NewBranchForm', () => { + let wrapper; + + const findSourceBranchDropdown = () => wrapper.findComponent(SourceBranchDropdown); + const findProjectDropdown = () => wrapper.findComponent(ProjectDropdown); + const findAlert = () => wrapper.findComponent(GlAlert); + const findForm = () => wrapper.findComponent(GlForm); + const findInput = () => wrapper.findComponent(GlFormInput); + const findButton = () => wrapper.findComponent(GlButton); + + const completeForm = async () => { + await findInput().vm.$emit('input', 'cool-branch-name'); + await findProjectDropdown().vm.$emit('change', mockProject); + await findSourceBranchDropdown().vm.$emit('change', 'source-branch'); + }; + + function createMockApolloProvider({ + mockCreateBranchMutation = mockCreateBranchMutationSuccess, + } = {}) { + localVue.use(VueApollo); + + const mockApollo = createMockApollo([[createBranchMutation, mockCreateBranchMutation]]); + + return mockApollo; + } + + function createComponent({ mockApollo, provide } = {}) { + wrapper = shallowMount(NewBranchForm, { + localVue, + apolloProvider: mockApollo || createMockApolloProvider(), + provide: { + initialBranchName: '', + ...provide, + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when selecting items from dropdowns', () => { + describe('when a project is selected', () => { + it('sets the `selectedProject` prop for ProjectDropdown and SourceBranchDropdown', async () => { + createComponent(); + + const projectDropdown = findProjectDropdown(); + await projectDropdown.vm.$emit('change', mockProject); + + expect(projectDropdown.props('selectedProject')).toEqual(mockProject); + expect(findSourceBranchDropdown().props('selectedProject')).toEqual(mockProject); + }); + }); + + describe('when a source branch is selected', () => { + it('sets the `selectedBranchName` prop for SourceBranchDropdown', async () => { + createComponent(); + + const mockBranchName = 'main'; + const sourceBranchDropdown = findSourceBranchDropdown(); + await sourceBranchDropdown.vm.$emit('change', mockBranchName); + + expect(sourceBranchDropdown.props('selectedBranchName')).toBe(mockBranchName); + }); + }); + }); + + describe('when submitting form', () => { + describe('when form submission is loading', () => { + it('sets submit button `loading` prop to `true`', async () => { + createComponent({ + mockApollo: createMockApolloProvider({ + mockCreateBranchMutation: mockMutationLoading, + }), + }); + + await completeForm(); + + await findForm().vm.$emit('submit', new Event('submit')); + await waitForPromises(); + + expect(findButton().props('loading')).toBe(true); + }); + }); + + describe('when form submission is successful', () => { + beforeEach(async () => { + createComponent(); + + await completeForm(); + + await findForm().vm.$emit('submit', new Event('submit')); + await waitForPromises(); + }); + + it('emits `success` event', () => { + expect(wrapper.emitted('success')).toBeTruthy(); + }); + + it('called `createBranch` mutation correctly', () => { + expect(mockCreateBranchMutationSuccess).toHaveBeenCalledWith({ + name: 'cool-branch-name', + projectPath: mockProject.fullPath, + ref: 'source-branch', + }); + }); + + it('sets submit button `loading` prop to `false`', () => { + expect(findButton().props('loading')).toBe(false); + }); + }); + + describe('when form submission fails', () => { + describe.each` + scenario | mutation | alertTitle | alertText + ${'with errors-as-data'} | ${mockCreateBranchMutationWithErrors} | ${CREATE_BRANCH_ERROR_WITH_CONTEXT} | ${mockCreateBranchMutationResponseWithErrors.data.createBranch.errors[0]} + ${'top-level error'} | ${mockCreateBranchMutationFailed} | ${''} | ${CREATE_BRANCH_ERROR_GENERIC} + `('', ({ mutation, alertTitle, alertText }) => { + beforeEach(async () => { + createComponent({ + mockApollo: createMockApolloProvider({ + mockCreateBranchMutation: mutation, + }), + }); + + await completeForm(); + + await findForm().vm.$emit('submit', new Event('submit')); + await waitForPromises(); + }); + + it('displays an alert', () => { + const alert = findAlert(); + expect(alert.exists()).toBe(true); + expect(alert.text()).toBe(alertText); + expect(alert.props()).toMatchObject({ title: alertTitle, variant: 'danger' }); + }); + + it('sets submit button `loading` prop to `false`', () => { + expect(findButton().props('loading')).toBe(false); + }); + }); + }); + }); + + describe('when `initialBranchName` is specified', () => { + it('sets value of branch name input to `initialBranchName` by default', () => { + const mockInitialBranchName = 'ap1-test-branch-name'; + + createComponent({ provide: { initialBranchName: mockInitialBranchName } }); + expect(findInput().attributes('value')).toBe(mockInitialBranchName); + }); + }); + + describe('error handling', () => { + describe.each` + component | componentName + ${SourceBranchDropdown} | ${'SourceBranchDropdown'} + ${ProjectDropdown} | ${'ProjectDropdown'} + `('when $componentName emits error', ({ component }) => { + const mockErrorMessage = 'oh noes!'; + + beforeEach(async () => { + createComponent(); + await wrapper.findComponent(component).vm.$emit('error', { message: mockErrorMessage }); + }); + + it('displays an alert', () => { + const alert = findAlert(); + expect(alert.exists()).toBe(true); + expect(alert.text()).toBe(mockErrorMessage); + expect(alert.props('variant')).toBe('danger'); + }); + + describe('when alert is dismissed', () => { + it('hides alert', async () => { + const alert = findAlert(); + expect(alert.exists()).toBe(true); + + await alert.vm.$emit('dismiss'); + + expect(alert.exists()).toBe(false); + }); + }); + }); + }); +}); diff --git a/spec/frontend/jira_connect/branches/pages/index_spec.js b/spec/frontend/jira_connect/branches/pages/index_spec.js new file mode 100644 index 00000000000..92976dd28da --- /dev/null +++ b/spec/frontend/jira_connect/branches/pages/index_spec.js @@ -0,0 +1,65 @@ +import { GlEmptyState } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import NewBranchForm from '~/jira_connect/branches/components/new_branch_form.vue'; +import { + I18N_PAGE_TITLE_WITH_BRANCH_NAME, + I18N_PAGE_TITLE_DEFAULT, +} from '~/jira_connect/branches/constants'; +import JiraConnectNewBranchPage from '~/jira_connect/branches/pages/index.vue'; +import { sprintf } from '~/locale'; + +describe('NewBranchForm', () => { + let wrapper; + + const findPageTitle = () => wrapper.find('h1'); + const findNewBranchForm = () => wrapper.findComponent(NewBranchForm); + const findEmptyState = () => wrapper.findComponent(GlEmptyState); + + function createComponent({ provide } = {}) { + wrapper = shallowMount(JiraConnectNewBranchPage, { + provide: { + initialBranchName: '', + successStateSvgPath: '', + ...provide, + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + describe('page title', () => { + it.each` + initialBranchName | pageTitle + ${undefined} | ${I18N_PAGE_TITLE_DEFAULT} + ${'ap1-test-button'} | ${sprintf(I18N_PAGE_TITLE_WITH_BRANCH_NAME, { jiraIssue: 'ap1-test-button' })} + `( + 'sets page title to "$pageTitle" when initial branch name is "$initialBranchName"', + ({ initialBranchName, pageTitle }) => { + createComponent({ provide: { initialBranchName } }); + + expect(findPageTitle().text()).toBe(pageTitle); + }, + ); + }); + + it('renders NewBranchForm by default', () => { + createComponent(); + + expect(findNewBranchForm().exists()).toBe(true); + expect(findEmptyState().exists()).toBe(false); + }); + + describe('when `sucesss` event emitted from NewBranchForm', () => { + it('renders the success state', async () => { + createComponent(); + + const newBranchForm = findNewBranchForm(); + await newBranchForm.vm.$emit('success'); + + expect(findNewBranchForm().exists()).toBe(false); + expect(findEmptyState().exists()).toBe(true); + }); + }); +}); diff --git a/spec/frontend/jira_connect/api_spec.js b/spec/frontend/jira_connect/subscriptions/api_spec.js index 88922999715..57b11bdbc27 100644 --- a/spec/frontend/jira_connect/api_spec.js +++ b/spec/frontend/jira_connect/subscriptions/api_spec.js @@ -1,10 +1,10 @@ import MockAdapter from 'axios-mock-adapter'; -import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api'; -import { getJwt } from '~/jira_connect/utils'; +import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/subscriptions/api'; +import { getJwt } from '~/jira_connect/subscriptions/utils'; import axios from '~/lib/utils/axios_utils'; import httpStatus from '~/lib/utils/http_status'; -jest.mock('~/jira_connect/utils', () => ({ +jest.mock('~/jira_connect/subscriptions/utils', () => ({ getJwt: jest.fn().mockResolvedValue('jwt'), })); diff --git a/spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap b/spec/frontend/jira_connect/subscriptions/components/__snapshots__/group_item_name_spec.js.snap index 21c903f064d..21c903f064d 100644 --- a/spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap +++ b/spec/frontend/jira_connect/subscriptions/components/__snapshots__/group_item_name_spec.js.snap diff --git a/spec/frontend/jira_connect/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js index e0d61d8209b..8915a7697a5 100644 --- a/spec/frontend/jira_connect/components/app_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js @@ -1,12 +1,12 @@ import { GlAlert, GlButton, GlModal, GlLink } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; -import JiraConnectApp from '~/jira_connect/components/app.vue'; -import createStore from '~/jira_connect/store'; -import { SET_ALERT } from '~/jira_connect/store/mutation_types'; +import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue'; +import createStore from '~/jira_connect/subscriptions/store'; +import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; import { __ } from '~/locale'; -jest.mock('~/jira_connect/utils', () => ({ +jest.mock('~/jira_connect/subscriptions/utils', () => ({ retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }), getLocation: jest.fn(), })); diff --git a/spec/frontend/jira_connect/components/group_item_name_spec.js b/spec/frontend/jira_connect/subscriptions/components/group_item_name_spec.js index ea0067f8ed1..b5fe08486b1 100644 --- a/spec/frontend/jira_connect/components/group_item_name_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/group_item_name_spec.js @@ -1,6 +1,6 @@ import { shallowMount } from '@vue/test-utils'; -import GroupItemName from '~/jira_connect/components/group_item_name.vue'; +import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue'; import { mockGroup1 } from '../mock_data'; describe('GroupItemName', () => { diff --git a/spec/frontend/jira_connect/components/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js index bcc27cc2898..b69435df83a 100644 --- a/spec/frontend/jira_connect/components/groups_list_item_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js @@ -2,13 +2,13 @@ import { GlButton } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; -import * as JiraConnectApi from '~/jira_connect/api'; -import GroupItemName from '~/jira_connect/components/group_item_name.vue'; -import GroupsListItem from '~/jira_connect/components/groups_list_item.vue'; -import { persistAlert, reloadPage } from '~/jira_connect/utils'; +import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; +import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue'; +import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue'; +import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils'; import { mockGroup1 } from '../mock_data'; -jest.mock('~/jira_connect/utils'); +jest.mock('~/jira_connect/subscriptions/utils'); describe('GroupsListItem', () => { let wrapper; diff --git a/spec/frontend/jira_connect/components/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js index d583fb68771..d3a9a3bfd41 100644 --- a/spec/frontend/jira_connect/components/groups_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js @@ -2,10 +2,10 @@ import { GlAlert, GlLoadingIcon, GlSearchBoxByType, GlPagination } from '@gitlab import { shallowMount } from '@vue/test-utils'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import { fetchGroups } from '~/jira_connect/api'; -import GroupsList from '~/jira_connect/components/groups_list.vue'; -import GroupsListItem from '~/jira_connect/components/groups_list_item.vue'; -import { DEFAULT_GROUPS_PER_PAGE } from '~/jira_connect/constants'; +import { fetchGroups } from '~/jira_connect/subscriptions/api'; +import GroupsList from '~/jira_connect/subscriptions/components/groups_list.vue'; +import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue'; +import { DEFAULT_GROUPS_PER_PAGE } from '~/jira_connect/subscriptions/constants'; import { mockGroup1, mockGroup2 } from '../mock_data'; const createMockGroup = (groupId) => { @@ -19,7 +19,7 @@ const createMockGroups = (count) => { return [...new Array(count)].map((_, idx) => createMockGroup(idx)); }; -jest.mock('~/jira_connect/api', () => { +jest.mock('~/jira_connect/subscriptions/api', () => { return { fetchGroups: jest.fn(), }; diff --git a/spec/frontend/jira_connect/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js index ff86969367d..32b43765843 100644 --- a/spec/frontend/jira_connect/components/subscriptions_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js @@ -2,14 +2,14 @@ import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; -import * as JiraConnectApi from '~/jira_connect/api'; -import SubscriptionsList from '~/jira_connect/components/subscriptions_list.vue'; -import createStore from '~/jira_connect/store'; -import { SET_ALERT } from '~/jira_connect/store/mutation_types'; -import { reloadPage } from '~/jira_connect/utils'; +import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; +import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue'; +import createStore from '~/jira_connect/subscriptions/store'; +import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; +import { reloadPage } from '~/jira_connect/subscriptions/utils'; import { mockSubscription } from '../mock_data'; -jest.mock('~/jira_connect/utils'); +jest.mock('~/jira_connect/subscriptions/utils'); describe('SubscriptionsList', () => { let wrapper; diff --git a/spec/frontend/jira_connect/index_spec.js b/spec/frontend/jira_connect/subscriptions/index_spec.js index 0161cfa0273..786f3b4a7d3 100644 --- a/spec/frontend/jira_connect/index_spec.js +++ b/spec/frontend/jira_connect/subscriptions/index_spec.js @@ -1,6 +1,6 @@ -import { initJiraConnect } from '~/jira_connect'; +import { initJiraConnect } from '~/jira_connect/subscriptions'; -jest.mock('~/jira_connect/utils', () => ({ +jest.mock('~/jira_connect/subscriptions/utils', () => ({ getLocation: jest.fn().mockResolvedValue('test/location'), })); diff --git a/spec/frontend/jira_connect/mock_data.js b/spec/frontend/jira_connect/subscriptions/mock_data.js index 5247a3dc522..5247a3dc522 100644 --- a/spec/frontend/jira_connect/mock_data.js +++ b/spec/frontend/jira_connect/subscriptions/mock_data.js diff --git a/spec/frontend/jira_connect/store/mutations_spec.js b/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js index 584b17b36f7..84a33dbf0b5 100644 --- a/spec/frontend/jira_connect/store/mutations_spec.js +++ b/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js @@ -1,5 +1,5 @@ -import mutations from '~/jira_connect/store/mutations'; -import state from '~/jira_connect/store/state'; +import mutations from '~/jira_connect/subscriptions/store/mutations'; +import state from '~/jira_connect/subscriptions/store/state'; describe('JiraConnect store mutations', () => { let localState; diff --git a/spec/frontend/jira_connect/utils_spec.js b/spec/frontend/jira_connect/subscriptions/utils_spec.js index 7eae870478d..2dd95de1b8c 100644 --- a/spec/frontend/jira_connect/utils_spec.js +++ b/spec/frontend/jira_connect/subscriptions/utils_spec.js @@ -1,6 +1,6 @@ import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; -import { ALERT_LOCALSTORAGE_KEY } from '~/jira_connect/constants'; +import { ALERT_LOCALSTORAGE_KEY } from '~/jira_connect/subscriptions/constants'; import { persistAlert, retrieveAlert, @@ -8,7 +8,7 @@ import { getLocation, reloadPage, sizeToParent, -} from '~/jira_connect/utils'; +} from '~/jira_connect/subscriptions/utils'; describe('JiraConnect utils', () => { describe('alert utils', () => { |