summaryrefslogtreecommitdiff
path: root/spec/frontend/projects
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/frontend/projects
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
downloadgitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/frontend/projects')
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js4
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js13
-rw-r--r--spec/frontend/projects/commit/components/form_trigger_spec.js2
-rw-r--r--spec/frontend/projects/commit/store/actions_spec.js6
-rw-r--r--spec/frontend/projects/commit/store/mutations_spec.js2
-rw-r--r--spec/frontend/projects/commit_box/info/load_branches_spec.js2
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js2
-rw-r--r--spec/frontend/projects/commits/store/actions_spec.js4
-rw-r--r--spec/frontend/projects/compare/components/app_spec.js116
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js92
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap4
-rw-r--r--spec/frontend/projects/components/shared/delete_button_spec.js2
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js4
-rw-r--r--spec/frontend/projects/members/utils_spec.js14
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js168
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js94
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js72
-rw-r--r--spec/frontend/projects/pipelines/charts/mock_data.js10
-rw-r--r--spec/frontend/projects/settings/access_dropdown_spec.js1
-rw-r--r--spec/frontend/projects/settings/components/shared_runners_toggle_spec.js2
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js236
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js190
-rw-r--r--spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js111
23 files changed, 677 insertions, 474 deletions
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
index 9fa7d658405..7686c28c7fc 100644
--- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -1,8 +1,8 @@
+import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
Vue.use(Vuex);
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 1c37b82fed3..1569f5b4bbe 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -1,12 +1,13 @@
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount, mount, createWrapper } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { GlModal, GlForm, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
import { within } from '@testing-library/dom';
+import { shallowMount, mount, createWrapper } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/projects/commit/event_hub';
-import CommitFormModal from '~/projects/commit/components/form_modal.vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
+import CommitFormModal from '~/projects/commit/components/form_modal.vue';
+import eventHub from '~/projects/commit/event_hub';
import createStore from '~/projects/commit/store';
import mockData from '../mock_data';
@@ -64,7 +65,7 @@ describe('CommitFormModal', () => {
wrapper.vm.show();
- expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', mockData.modalPropsData.modalId);
+ expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, mockData.modalPropsData.modalId);
});
it('Clears the modal state once modal is hidden', () => {
diff --git a/spec/frontend/projects/commit/components/form_trigger_spec.js b/spec/frontend/projects/commit/components/form_trigger_spec.js
index ca51419d6a5..4503493c0a6 100644
--- a/spec/frontend/projects/commit/components/form_trigger_spec.js
+++ b/spec/frontend/projects/commit/components/form_trigger_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import FormTrigger from '~/projects/commit/components/form_trigger.vue';
import eventHub from '~/projects/commit/event_hub';
diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js
index ec528d4ee88..458372229cf 100644
--- a/spec/frontend/projects/commit/store/actions_spec.js
+++ b/spec/frontend/projects/commit/store/actions_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
-import getInitialState from '~/projects/commit/store/state';
+import axios from '~/lib/utils/axios_utils';
+import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
import * as actions from '~/projects/commit/store/actions';
import * as types from '~/projects/commit/store/mutation_types';
+import getInitialState from '~/projects/commit/store/state';
import mockData from '../mock_data';
-import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
jest.mock('~/flash.js');
diff --git a/spec/frontend/projects/commit/store/mutations_spec.js b/spec/frontend/projects/commit/store/mutations_spec.js
index 59ab3d9a74a..2ea50e71772 100644
--- a/spec/frontend/projects/commit/store/mutations_spec.js
+++ b/spec/frontend/projects/commit/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/projects/commit/store/mutations';
import * as types from '~/projects/commit/store/mutation_types';
+import mutations from '~/projects/commit/store/mutations';
describe('Commit form modal mutations', () => {
let stateCopy;
diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js
index ebd4ee45dab..8100200cbdd 100644
--- a/spec/frontend/projects/commit_box/info/load_branches_spec.js
+++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js
@@ -1,6 +1,6 @@
import axios from 'axios';
-import waitForPromises from 'helpers/wait_for_promises';
import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
import { loadBranches } from '~/projects/commit_box/info/load_branches';
const mockCommitPath = '/commit/abcd/branches';
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index 63920ddfd72..9a8f7ff7582 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -1,6 +1,6 @@
+import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import * as urlUtility from '~/lib/utils/url_utility';
import AuthorSelect from '~/projects/commits/components/author_select.vue';
import { createStore } from '~/projects/commits/store';
diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js
index a842aaa2a76..e2c993b8395 100644
--- a/spec/frontend/projects/commits/store/actions_spec.js
+++ b/spec/frontend/projects/commits/store/actions_spec.js
@@ -1,10 +1,10 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import * as types from '~/projects/commits/store/mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import actions from '~/projects/commits/store/actions';
+import * as types from '~/projects/commits/store/mutation_types';
import createState from '~/projects/commits/store/state';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js
new file mode 100644
index 00000000000..d28a30e93b1
--- /dev/null
+++ b/spec/frontend/projects/compare/components/app_spec.js
@@ -0,0 +1,116 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import CompareApp from '~/projects/compare/components/app.vue';
+import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+const projectCompareIndexPath = 'some/path';
+const refsProjectPath = 'some/refs/path';
+const paramsFrom = 'master';
+const paramsTo = 'master';
+
+describe('CompareApp component', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(CompareApp, {
+ propsData: {
+ projectCompareIndexPath,
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ projectMergeRequestPath: '',
+ createMrPath: '',
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders component with prop', () => {
+ expect(wrapper.props()).toEqual(
+ expect.objectContaining({
+ projectCompareIndexPath,
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ }),
+ );
+ });
+
+ it('contains the correct form attributes', () => {
+ expect(wrapper.attributes('action')).toBe(projectCompareIndexPath);
+ expect(wrapper.attributes('method')).toBe('POST');
+ });
+
+ it('has input with csrf token', () => {
+ expect(wrapper.find('input[name="authenticity_token"]').attributes('value')).toBe(
+ 'mock-csrf-token',
+ );
+ });
+
+ it('has ellipsis', () => {
+ expect(wrapper.find('[data-testid="ellipsis"]').exists()).toBe(true);
+ });
+
+ it('render Source and Target BranchDropdown components', () => {
+ const branchDropdowns = wrapper.findAll(RevisionDropdown);
+
+ expect(branchDropdowns.length).toBe(2);
+ expect(branchDropdowns.at(0).props('revisionText')).toBe('Source');
+ expect(branchDropdowns.at(1).props('revisionText')).toBe('Target');
+ });
+
+ describe('compare button', () => {
+ const findCompareButton = () => wrapper.find(GlButton);
+
+ it('renders button', () => {
+ expect(findCompareButton().exists()).toBe(true);
+ });
+
+ it('submits form', () => {
+ findCompareButton().vm.$emit('click');
+ expect(wrapper.find('form').element.submit).toHaveBeenCalled();
+ });
+
+ it('has compare text', () => {
+ expect(findCompareButton().text()).toBe('Compare');
+ });
+ });
+
+ describe('merge request buttons', () => {
+ const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
+ const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
+
+ it('does not have merge request buttons', () => {
+ createComponent();
+ expect(findProjectMrButton().exists()).toBe(false);
+ expect(findCreateMrButton().exists()).toBe(false);
+ });
+
+ it('has "View open merge request" button', () => {
+ createComponent({
+ projectMergeRequestPath: 'some/project/merge/request/path',
+ });
+ expect(findProjectMrButton().exists()).toBe(true);
+ expect(findCreateMrButton().exists()).toBe(false);
+ });
+
+ it('has "Create merge request" button', () => {
+ createComponent({
+ createMrPath: 'some/create/create/mr/path',
+ });
+ expect(findProjectMrButton().exists()).toBe(false);
+ expect(findCreateMrButton().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
new file mode 100644
index 00000000000..f3ff5e26d2b
--- /dev/null
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -0,0 +1,92 @@
+import { GlDropdown } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
+
+const defaultProps = {
+ refsProjectPath: 'some/refs/path',
+ revisionText: 'Target',
+ paramsName: 'from',
+ paramsBranch: 'master',
+};
+
+jest.mock('~/flash');
+
+describe('RevisionDropdown component', () => {
+ let wrapper;
+ let axiosMock;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(RevisionDropdown, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ axiosMock.restore();
+ });
+
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+
+ it('sets hidden input', () => {
+ createComponent();
+ expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe(
+ defaultProps.paramsBranch,
+ );
+ });
+
+ it('update the branches on success', async () => {
+ const Branches = ['branch-1', 'branch-2'];
+ const Tags = ['tag-1', 'tag-2', 'tag-3'];
+
+ axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(200, {
+ Branches,
+ Tags,
+ });
+
+ createComponent();
+
+ await axios.waitForAll();
+
+ expect(wrapper.vm.branches).toEqual(Branches);
+ expect(wrapper.vm.tags).toEqual(Tags);
+ });
+
+ it('shows flash message on error', async () => {
+ axiosMock.onGet('some/invalid/path').replyOnce(404);
+
+ createComponent();
+
+ await wrapper.vm.fetchBranchesAndTags();
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ describe('GlDropdown component', () => {
+ it('renders props', () => {
+ createComponent();
+ expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps));
+ });
+
+ it('display default text', () => {
+ createComponent({
+ paramsBranch: null,
+ });
+ expect(findGlDropdown().props('text')).toBe('Select branch/tag');
+ });
+
+ it('display params branch text', () => {
+ createComponent();
+ expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch);
+ });
+ });
+});
diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
index 0b9f095a700..f0d72124379 100644
--- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
@@ -53,12 +53,12 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
variant="danger"
>
<gl-sprintf-stub
- message="Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+ message="Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
/>
</gl-alert-stub>
<p>
- This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc.
+ This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc.
</p>
<p
diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js
index cf7e41a2df2..3e491584670 100644
--- a/spec/frontend/projects/components/shared/delete_button_spec.js
+++ b/spec/frontend/projects/components/shared/delete_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
index 9a5f200f5a9..b4ae50341d4 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBreadcrumb } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import App from '~/projects/experiment_new_project_creation/components/app.vue';
-import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
import LegacyContainer from '~/projects/experiment_new_project_creation/components/legacy_container.vue';
+import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
describe('Experimental new project creation app', () => {
let wrapper;
diff --git a/spec/frontend/projects/members/utils_spec.js b/spec/frontend/projects/members/utils_spec.js
new file mode 100644
index 00000000000..813e8455e85
--- /dev/null
+++ b/spec/frontend/projects/members/utils_spec.js
@@ -0,0 +1,14 @@
+import { projectMemberRequestFormatter } from '~/projects/members/utils';
+
+describe('project member utils', () => {
+ describe('projectMemberRequestFormatter', () => {
+ it('returns expected format', () => {
+ expect(
+ projectMemberRequestFormatter({
+ accessLevel: 50,
+ expires_at: '2020-10-16',
+ }),
+ ).toEqual({ project_member: { access_level: 50, expires_at: '2020-10-16' } });
+ });
+ });
+});
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 44329944097..e8aace14db4 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,32 +1,19 @@
-import { merge } from 'lodash';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
import { GlTabs, GlTab } from '@gitlab/ui';
-import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMount } from '@vue/test-utils';
+import { merge } from 'lodash';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import { TEST_HOST } from 'helpers/test_constants';
+import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import Component from '~/projects/pipelines/charts/components/app.vue';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
-import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql';
-import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql';
-import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
-const projectPath = 'gitlab-org/gitlab';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
- function createMockApolloProvider() {
- const requestHandlers = [
- [getPipelineCountByStatus, jest.fn().mockResolvedValue(mockPipelineCount)],
- [getProjectPipelineStatistics, jest.fn().mockResolvedValue(mockPipelineStatistics)],
- ];
-
- return createMockApollo(requestHandlers);
- }
-
function createComponent(mountOptions = {}) {
wrapper = shallowMount(
Component,
@@ -34,11 +21,8 @@ describe('ProjectsPipelinesChartsApp', () => {
{},
{
provide: {
- projectPath,
shouldRenderDeploymentFrequencyCharts: false,
},
- localVue,
- apolloProvider: createMockApolloProvider(),
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
},
@@ -57,52 +41,15 @@ describe('ProjectsPipelinesChartsApp', () => {
wrapper = null;
});
- describe('pipelines charts', () => {
- it('displays the pipeline charts', () => {
- const chart = wrapper.find(PipelineCharts);
- const analytics = mockPipelineStatistics.data.project.pipelineAnalytics;
-
- const {
- totalPipelines: total,
- successfulPipelines: success,
- failedPipelines: failed,
- } = mockPipelineCount.data.project;
-
- expect(chart.exists()).toBe(true);
- expect(chart.props()).toMatchObject({
- counts: {
- failed: failed.count,
- success: success.count,
- total: total.count,
- successRatio: (success.count / (success.count + failed.count)) * 100,
- },
- lastWeek: {
- labels: analytics.weekPipelinesLabels,
- totals: analytics.weekPipelinesTotals,
- success: analytics.weekPipelinesSuccessful,
- },
- lastMonth: {
- labels: analytics.monthPipelinesLabels,
- totals: analytics.monthPipelinesTotals,
- success: analytics.monthPipelinesSuccessful,
- },
- lastYear: {
- labels: analytics.yearPipelinesLabels,
- totals: analytics.yearPipelinesTotals,
- success: analytics.yearPipelinesSuccessful,
- },
- timesChart: {
- labels: analytics.pipelineTimesLabels,
- values: analytics.pipelineTimesValues,
- },
- });
- });
- });
-
- const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findGlTabs = () => wrapper.find(GlTabs);
const findAllGlTab = () => wrapper.findAll(GlTab);
const findGlTabAt = (i) => findAllGlTab().at(i);
+ const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
+ const findPipelineCharts = () => wrapper.find(PipelineCharts);
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
+ });
describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
beforeEach(() => {
@@ -115,6 +62,97 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findGlTabAt(1).attributes('title')).toBe('Deployments');
expect(findDeploymentFrequencyCharts().exists()).toBe(true);
});
+
+ it('sets the tab and url when a tab is clicked', async () => {
+ let chartsPath;
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
+
+ mergeUrlParams.mockImplementation(({ chart }, path) => {
+ expect(chart).toBe('deployments');
+ expect(path).toBe(window.location.pathname);
+ chartsPath = `${path}?chart=${chart}`;
+ return chartsPath;
+ });
+
+ updateHistory.mockImplementation(({ url }) => {
+ expect(url).toBe(chartsPath);
+ });
+ const tabs = findGlTabs();
+
+ expect(tabs.attributes('value')).toBe('0');
+
+ tabs.vm.$emit('input', 1);
+
+ await wrapper.vm.$nextTick();
+
+ expect(tabs.attributes('value')).toBe('1');
+ });
+
+ it('should not try to push history if the tab does not change', async () => {
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
+
+ mergeUrlParams.mockImplementation(({ chart }, path) => `${path}?chart=${chart}`);
+
+ const tabs = findGlTabs();
+
+ expect(tabs.attributes('value')).toBe('0');
+
+ tabs.vm.$emit('input', 0);
+
+ await wrapper.vm.$nextTick();
+
+ expect(updateHistory).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when provided with a query param', () => {
+ it.each`
+ chart | tab
+ ${'deployments'} | ${'1'}
+ ${'pipelines'} | ${'0'}
+ ${'fake'} | ${'0'}
+ ${''} | ${'0'}
+ `('shows the correct tab for URL parameter "$chart"', ({ chart, tab }) => {
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts?chart=${chart}`);
+ getParameterValues.mockImplementation((name) => {
+ expect(name).toBe('chart');
+ return chart ? [chart] : [];
+ });
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ expect(findGlTabs().attributes('value')).toBe(tab);
+ });
+
+ it('should set the tab when the back button is clicked', async () => {
+ let popstateHandler;
+
+ window.addEventListener = jest.fn();
+
+ window.addEventListener.mockImplementation((event, handler) => {
+ if (event === 'popstate') {
+ popstateHandler = handler;
+ }
+ });
+
+ getParameterValues.mockImplementation((name) => {
+ expect(name).toBe('chart');
+ return [];
+ });
+
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+
+ expect(findGlTabs().attributes('value')).toBe('0');
+
+ getParameterValues.mockImplementationOnce((name) => {
+ expect(name).toBe('chart');
+ return ['deployments'];
+ });
+
+ popstateHandler();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlTabs().attributes('value')).toBe('1');
+ });
});
describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
new file mode 100644
index 00000000000..037530ddd48
--- /dev/null
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
@@ -0,0 +1,94 @@
+import { GlSegmentedControl } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
+import CiCdAnalyticsCharts from '~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue';
+import { transformedAreaChartData, chartOptions } from '../mock_data';
+
+const DEFAULT_PROPS = {
+ chartOptions,
+ charts: [
+ {
+ range: 'test range 1',
+ title: 'title 1',
+ data: transformedAreaChartData,
+ },
+ {
+ range: 'test range 2',
+ title: 'title 2',
+ data: transformedAreaChartData,
+ },
+ {
+ range: 'test range 3',
+ title: 'title 3',
+ data: transformedAreaChartData,
+ },
+ ],
+};
+
+describe('~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue', () => {
+ let wrapper;
+
+ const createWrapper = (props = {}) =>
+ shallowMount(CiCdAnalyticsCharts, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('segmented control', () => {
+ let segmentedControl;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ segmentedControl = wrapper.find(GlSegmentedControl);
+ });
+
+ it('should default to the first chart', () => {
+ expect(segmentedControl.props('checked')).toBe(0);
+ });
+
+ it('should use the title and index as values', () => {
+ const options = segmentedControl.props('options');
+ expect(options).toHaveLength(3);
+ expect(options).toEqual([
+ {
+ text: 'title 1',
+ value: 0,
+ },
+ {
+ text: 'title 2',
+ value: 1,
+ },
+ {
+ text: 'title 3',
+ value: 2,
+ },
+ ]);
+ });
+
+ it('should select a different chart on change', async () => {
+ segmentedControl.vm.$emit('input', 1);
+
+ const chart = wrapper.find(CiCdAnalyticsAreaChart);
+
+ await nextTick();
+
+ expect(chart.props('chartData')).toEqual(transformedAreaChartData);
+ expect(chart.text()).toBe('Date range: test range 2');
+ });
+ });
+
+ it('should not display charts if there are no charts', () => {
+ wrapper = createWrapper({ charts: [] });
+ expect(wrapper.find(CiCdAnalyticsAreaChart).exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
index 598055d5828..c5cfe783569 100644
--- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
@@ -1,35 +1,37 @@
-import { shallowMount } from '@vue/test-utils';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import CiCdAnalyticsCharts from '~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
-import {
- counts,
- timesChartData as timesChart,
- areaChartData as lastWeek,
- areaChartData as lastMonth,
- lastYearChartData as lastYear,
-} from '../mock_data';
+import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
+import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql';
+import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql';
+import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
+
+const projectPath = 'gitlab-org/gitlab';
+const localVue = createLocalVue();
+localVue.use(VueApollo);
-describe('ProjectsPipelinesChartsApp', () => {
+describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => {
let wrapper;
+ function createMockApolloProvider() {
+ const requestHandlers = [
+ [getPipelineCountByStatus, jest.fn().mockResolvedValue(mockPipelineCount)],
+ [getProjectPipelineStatistics, jest.fn().mockResolvedValue(mockPipelineStatistics)],
+ ];
+
+ return createMockApollo(requestHandlers);
+ }
+
beforeEach(() => {
wrapper = shallowMount(PipelineCharts, {
- propsData: {
- counts,
- timesChart,
- lastWeek,
- lastMonth,
- lastYear,
- },
provide: {
- projectPath: 'test/project',
- shouldRenderDeploymentFrequencyCharts: true,
- },
- stubs: {
- DeploymentFrequencyCharts: true,
+ projectPath,
},
+ localVue,
+ apolloProvider: createMockApolloProvider(),
});
});
@@ -43,7 +45,12 @@ describe('ProjectsPipelinesChartsApp', () => {
const list = wrapper.find(StatisticsList);
expect(list.exists()).toBe(true);
- expect(list.props('counts')).toBe(counts);
+ expect(list.props('counts')).toEqual({
+ total: 34,
+ success: 23,
+ failed: 1,
+ successRatio: (23 / (23 + 1)) * 100,
+ });
});
it('displays the commit duration chart', () => {
@@ -58,20 +65,17 @@ describe('ProjectsPipelinesChartsApp', () => {
});
describe('pipelines charts', () => {
- it('displays 3 area charts', () => {
- expect(wrapper.findAll(CiCdAnalyticsAreaChart)).toHaveLength(3);
+ it('displays the charts components', () => {
+ expect(wrapper.find(CiCdAnalyticsCharts).exists()).toBe(true);
});
describe('displays individual correctly', () => {
it('renders with the correct data', () => {
- const charts = wrapper.findAll(CiCdAnalyticsAreaChart);
- for (let i = 0; i < charts.length; i += 1) {
- const chart = charts.at(i);
-
- expect(chart.exists()).toBeTruthy();
- expect(chart.props('chartData')).toBe(wrapper.vm.areaCharts[i].data);
- expect(chart.text()).toBe(wrapper.vm.areaCharts[i].title);
- }
+ const charts = wrapper.find(CiCdAnalyticsCharts);
+ expect(charts.props()).toEqual({
+ charts: wrapper.vm.areaCharts,
+ chartOptions: wrapper.vm.$options.areaChartOptions,
+ });
});
});
});
diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js
index 3bc09f0b0a0..2e2c594102c 100644
--- a/spec/frontend/projects/pipelines/charts/mock_data.js
+++ b/spec/frontend/projects/pipelines/charts/mock_data.js
@@ -57,6 +57,16 @@ export const mockPipelineCount = {
},
};
+export const chartOptions = {
+ xAxis: {
+ name: 'X axis title',
+ type: 'category',
+ },
+ yAxis: {
+ name: 'Y axis title',
+ },
+};
+
export const mockPipelineStatistics = {
data: {
project: {
diff --git a/spec/frontend/projects/settings/access_dropdown_spec.js b/spec/frontend/projects/settings/access_dropdown_spec.js
index 8a57930ac83..236968a3736 100644
--- a/spec/frontend/projects/settings/access_dropdown_spec.js
+++ b/spec/frontend/projects/settings/access_dropdown_spec.js
@@ -14,7 +14,6 @@ describe('AccessDropdown', () => {
`);
const $dropdown = $('#dummy-dropdown');
$dropdown.data('defaultLabel', defaultLabel);
- gon.features = { deployKeysOnProtectedBranches: true };
const options = {
$dropdown,
accessLevelsData: {
diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
index 1fac3d07b16..2d6efe7ae83 100644
--- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
+++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
@@ -2,8 +2,8 @@ import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
import axios from '~/lib/utils/axios_utils';
+import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
const TEST_UPDATE_PATH = '/test/update_shared_runners';
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
index c83b1852147..f9fbb1b3016 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
@@ -1,20 +1,36 @@
-import { mount } from '@vue/test-utils';
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue';
-import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue';
+import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
describe('ServiceDeskRoot', () => {
- const endpoint = '/gitlab-org/gitlab-test/service_desk';
- const initialIncomingEmail = 'servicedeskaddress@example.com';
let axiosMock;
let wrapper;
let spy;
+ const provideData = {
+ customEmail: 'custom.email@example.com',
+ customEmailEnabled: true,
+ endpoint: '/gitlab-org/gitlab-test/service_desk',
+ initialIncomingEmail: 'servicedeskaddress@example.com',
+ initialIsEnabled: true,
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ selectedTemplate: 'Bug',
+ templates: ['Bug', 'Documentation'],
+ };
+
+ const getAlertText = () => wrapper.find(GlAlert).text();
+
+ const createComponent = () => shallowMount(ServiceDeskRoot, { provide: provideData });
+
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
+ spy = jest.spyOn(axios, 'put');
});
afterEach(() => {
@@ -25,156 +41,122 @@ describe('ServiceDeskRoot', () => {
}
});
- it('sends a request to toggle service desk off when the toggle is clicked from the on state', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ describe('ServiceDeskSetting component', () => {
+ it('is rendered', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find(ServiceDeskSetting).props()).toEqual({
+ customEmail: provideData.customEmail,
+ customEmailEnabled: provideData.customEmailEnabled,
+ incomingEmail: provideData.initialIncomingEmail,
+ initialOutgoingName: provideData.outgoingName,
+ initialProjectKey: provideData.projectKey,
+ initialSelectedTemplate: provideData.selectedTemplate,
+ isEnabled: provideData.initialIsEnabled,
+ isTemplateSaving: false,
+ templates: provideData.templates,
+ });
+ });
+
+ describe('toggle event', () => {
+ describe('when toggling service desk on', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('toggle', true);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- initialIncomingEmail,
- endpoint,
- },
- });
+ await waitForPromises();
+ });
+
+ it('sends a request to turn service desk on', () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- wrapper.find('button.gl-toggle').trigger('click');
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: true });
+ });
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: false });
+ it('shows a message when there is an error', () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
+
+ expect(getAlertText()).toContain('An error occurred while enabling Service Desk.');
+ });
});
- });
- it('sends a request to toggle service desk on when the toggle is clicked from the off state', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ describe('when toggling service desk off', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('toggle', false);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: false,
- initialIncomingEmail: '',
- endpoint,
- },
- });
+ await waitForPromises();
+ });
- wrapper.find('button.gl-toggle').trigger('click');
+ it('sends a request to turn service desk off', () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- return wrapper.vm.$nextTick(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: true });
- });
- });
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: false });
+ });
- it('shows an error message when there is an issue toggling service desk on', () => {
- axiosMock.onPut(endpoint).networkError();
+ it('shows a message when there is an error', () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: false,
- initialIncomingEmail: '',
- endpoint,
- },
+ expect(getAlertText()).toContain('An error occurred while disabling Service Desk.');
+ });
+ });
});
- wrapper.find('button.gl-toggle').trigger('click');
+ describe('save event', () => {
+ describe('successful request', () => {
+ beforeEach(async () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('An error occurred while enabling Service Desk.');
- });
- });
+ wrapper = createComponent();
- it('sends a request to update template when the "Save template" button is clicked', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ const payload = {
+ selectedTemplate: 'Bug',
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ };
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- templates: ['Bug', 'Documentation'],
- projectKey: 'key',
- },
- });
+ await waitForPromises();
+ });
- wrapper.find('button.btn-success').trigger('click');
+ it('sends a request to update template', async () => {
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, {
+ issue_template_key: 'Bug',
+ outgoing_name: 'GitLab Support Bot',
+ project_key: 'key',
+ service_desk_enabled: true,
+ });
+ });
- return wrapper.vm.$nextTick(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, {
- issue_template_key: 'Bug',
- outgoing_name: 'GitLab Support Bot',
- project_key: 'key',
- service_desk_enabled: true,
+ it('shows success message', () => {
+ expect(getAlertText()).toContain('Changes saved.');
+ });
});
- });
- });
- it('saves the template when the "Save template" button is clicked', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- templates: ['Bug', 'Documentation'],
- },
- });
+ describe('unsuccessful request', () => {
+ beforeEach(async () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
- wrapper.find('button.btn-success').trigger('click');
+ wrapper = createComponent();
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('Changes saved.');
- });
- });
+ const payload = {
+ selectedTemplate: 'Bug',
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ };
- it('shows an error message when there is an issue saving the template', () => {
- axiosMock.onPut(endpoint).networkError();
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- templates: ['Bug', 'Documentation'],
- },
- });
+ wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
- wrapper.find('button.btn-success').trigger('click');
+ await waitForPromises();
+ });
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('An error occured while saving changes:');
+ it('shows an error message', () => {
+ expect(getAlertText()).toContain('An error occured while saving changes:');
+ });
});
- });
-
- it('passes customEmail through updatedCustomEmail correctly', () => {
- const customEmail = 'foo';
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- customEmail,
- },
});
-
- expect(wrapper.find(ServiceDeskSetting).props('customEmail')).toEqual(customEmail);
});
});
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index ddd9a7b2fad..f6744f4971e 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
@@ -1,63 +1,68 @@
+import { GlButton, GlFormSelect, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
-import eventHub from '~/projects/settings_service_desk/event_hub';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('ServiceDeskSetting', () => {
let wrapper;
+ const findButton = () => wrapper.find(GlButton);
+ const findClipboardButton = () => wrapper.find(ClipboardButton);
+ const findIncomingEmail = () => wrapper.findByTestId('incoming-email');
+ const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-describer');
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findTemplateDropdown = () => wrapper.find(GlFormSelect);
+ const findToggle = () => wrapper.find(GlToggle);
+
+ const createComponent = ({ props = {}, mountFunction = shallowMount } = {}) =>
+ extendedWrapper(
+ mountFunction(ServiceDeskSetting, {
+ propsData: {
+ isEnabled: true,
+ ...props,
+ },
+ }),
+ );
+
afterEach(() => {
if (wrapper) {
wrapper.destroy();
}
});
- const findTemplateDropdown = () => wrapper.find('#service-desk-template-select');
- const findIncomingEmail = () => wrapper.find('[data-testid="incoming-email"]');
-
describe('when isEnabled=true', () => {
describe('only isEnabled', () => {
describe('as project admin', () => {
beforeEach(() => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
});
it('should see activation checkbox', () => {
- expect(wrapper.find('#service-desk-checkbox').exists()).toBe(true);
+ expect(findToggle().exists()).toBe(true);
});
it('should see main panel with the email info', () => {
- expect(wrapper.find('#incoming-email-describer').exists()).toBe(true);
+ expect(findIncomingEmailLabel().exists()).toBe(true);
});
it('should see loading spinner and not the incoming email', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(findLoadingIcon().exists()).toBe(true);
expect(findIncomingEmail().exists()).toBe(false);
});
});
});
describe('service desk toggle', () => {
- it('emits an event to turn on Service Desk when clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: false,
- },
- });
+ it('emits an event to turn on Service Desk when clicked', async () => {
+ wrapper = createComponent();
- wrapper.find('#service-desk-checkbox').trigger('click');
+ findToggle().vm.$emit('change', true);
- expect(eventSpy).toHaveBeenCalledWith(true);
+ await nextTick();
- eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('toggle')[0]).toEqual([true]);
});
});
@@ -65,23 +70,23 @@ describe('ServiceDeskSetting', () => {
const incomingEmail = 'foo@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail,
- },
+ wrapper = createComponent({
+ props: { incomingEmail },
});
});
it('should see email and not the loading spinner', () => {
expect(findIncomingEmail().element.value).toEqual(incomingEmail);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(findLoadingIcon().exists()).toBe(false);
});
it('renders a copy to clipboard button', () => {
- expect(wrapper.find('.qa-clipboard-button').exists()).toBe(true);
- expect(wrapper.find('.qa-clipboard-button').element.dataset.clipboardText).toBe(
- incomingEmail,
+ expect(findClipboardButton().exists()).toBe(true);
+ expect(findClipboardButton().props()).toEqual(
+ expect.objectContaining({
+ title: 'Copy',
+ text: incomingEmail,
+ }),
);
});
});
@@ -92,12 +97,8 @@ describe('ServiceDeskSetting', () => {
const customEmail = 'custom@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail,
- customEmail,
- },
+ wrapper = createComponent({
+ props: { incomingEmail, customEmail },
});
});
@@ -110,12 +111,8 @@ describe('ServiceDeskSetting', () => {
const email = 'foo@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail: email,
- customEmail: email,
- },
+ wrapper = createComponent({
+ props: { incomingEmail: email, customEmail: email },
});
});
@@ -127,21 +124,13 @@ describe('ServiceDeskSetting', () => {
describe('templates dropdown', () => {
it('renders a dropdown to choose a template', () => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
- expect(wrapper.find('#service-desk-template-select').exists()).toBe(true);
+ expect(findTemplateDropdown().exists()).toBe(true);
});
it('renders a dropdown with a default value of ""', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent({ mountFunction: mount });
expect(findTemplateDropdown().element.value).toEqual('');
});
@@ -149,23 +138,18 @@ describe('ServiceDeskSetting', () => {
it('renders a dropdown with a value of "Bug" when it is the initial value', () => {
const templates = ['Bug', 'Documentation', 'Security release'];
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- initialSelectedTemplate: 'Bug',
- templates,
- },
+ wrapper = createComponent({
+ props: { initialSelectedTemplate: 'Bug', templates },
+ mountFunction: mount,
});
expect(findTemplateDropdown().element.value).toEqual('Bug');
});
it('renders a dropdown with no options when the project has no templates', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- templates: [],
- },
+ wrapper = createComponent({
+ props: { templates: [] },
+ mountFunction: mount,
});
// The dropdown by default has one empty option
@@ -174,11 +158,10 @@ describe('ServiceDeskSetting', () => {
it('renders a dropdown with options when the project has templates', () => {
const templates = ['Bug', 'Documentation', 'Security release'];
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- templates,
- },
+
+ wrapper = createComponent({
+ props: { templates },
+ mountFunction: mount,
});
// An empty-named template is prepended so the user can select no template
@@ -199,78 +182,59 @@ describe('ServiceDeskSetting', () => {
describe('save button', () => {
it('renders a save button to save a template', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
- expect(wrapper.find('button.btn-success').text()).toContain('Save changes');
+ expect(findButton().text()).toContain('Save changes');
});
- it('emits a save event with the chosen template when the save button is clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskTemplateSave', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
+ it('emits a save event with the chosen template when the save button is clicked', async () => {
+ wrapper = createComponent({
+ props: {
initialSelectedTemplate: 'Bug',
initialOutgoingName: 'GitLab Support Bot',
initialProjectKey: 'key',
},
});
- wrapper.find('button.btn-success').trigger('click');
+ findButton().vm.$emit('click');
+
+ await nextTick();
- expect(eventSpy).toHaveBeenCalledWith({
+ const payload = {
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
projectKey: 'key',
- });
+ };
- eventHub.$off('serviceDeskTemplateSave', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('save')[0]).toEqual([payload]);
});
});
describe('when isEnabled=false', () => {
beforeEach(() => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: false,
- },
+ wrapper = createComponent({
+ props: { isEnabled: false },
});
});
it('does not render email panel', () => {
- expect(wrapper.find('#incoming-email-describer').exists()).toBe(false);
+ expect(findIncomingEmailLabel().exists()).toBe(false);
});
it('does not render template dropdown', () => {
- expect(wrapper.find('#service-desk-template-select').exists()).toBe(false);
+ expect(findTemplateDropdown().exists()).toBe(false);
});
it('does not render template save button', () => {
- expect(wrapper.find('button.btn-success').exists()).toBe(false);
+ expect(findButton().exists()).toBe(false);
});
- it('emits an event to turn on Service Desk when the toggle is clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
-
- wrapper.find('#service-desk-checkbox').trigger('click');
+ it('emits an event to turn on Service Desk when the toggle is clicked', async () => {
+ findToggle().vm.$emit('change', false);
- expect(eventSpy).toHaveBeenCalledWith(false);
+ await nextTick();
- eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('toggle')[0]).toEqual([false]);
});
});
});
diff --git a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js b/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
deleted file mode 100644
index d5340df03fe..00000000000
--- a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import AxiosMockAdapter from 'axios-mock-adapter';
-import ServiceDeskService from '~/projects/settings_service_desk/services/service_desk_service';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
-
-describe('ServiceDeskService', () => {
- const endpoint = `/gitlab-org/gitlab-test/service_desk`;
- const dummyResponse = { message: 'Dummy response' };
- const errorMessage = 'Network Error';
- let axiosMock;
- let service;
-
- beforeEach(() => {
- axiosMock = new AxiosMockAdapter(axios);
- service = new ServiceDeskService(endpoint);
- });
-
- afterEach(() => {
- axiosMock.restore();
- });
-
- describe('toggleServiceDesk', () => {
- it('makes a request to set service desk', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- return service.toggleServiceDesk(true).then((response) => {
- expect(response.data).toEqual(dummyResponse);
- });
- });
-
- it('fails on error response', () => {
- axiosMock.onPut(endpoint).networkError();
-
- return service.toggleServiceDesk(true).catch((error) => {
- expect(error.message).toBe(errorMessage);
- });
- });
-
- it('makes a request with the expected body', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- const spy = jest.spyOn(axios, 'put');
-
- service.toggleServiceDesk(true);
-
- expect(spy).toHaveBeenCalledWith(endpoint, {
- service_desk_enabled: true,
- });
-
- spy.mockRestore();
- });
- });
-
- describe('updateTemplate', () => {
- it('makes a request to update template', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- return service
- .updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- },
- true,
- )
- .then((response) => {
- expect(response.data).toEqual(dummyResponse);
- });
- });
-
- it('fails on error response', () => {
- axiosMock.onPut(endpoint).networkError();
-
- return service
- .updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- },
- true,
- )
- .catch((error) => {
- expect(error.message).toBe(errorMessage);
- });
- });
-
- it('makes a request with the expected body', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- const spy = jest.spyOn(axios, 'put');
-
- service.updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- projectKey: 'key',
- },
- true,
- );
-
- expect(spy).toHaveBeenCalledWith(endpoint, {
- issue_template_key: 'Bug',
- outgoing_name: 'GitLab Support Bot',
- project_key: 'key',
- service_desk_enabled: true,
- });
-
- spy.mockRestore();
- });
- });
-});