summaryrefslogtreecommitdiff
path: root/spec/frontend/pipelines
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pipelines')
-rw-r--r--spec/frontend/pipelines/__snapshots__/utils_spec.js.snap11
-rw-r--r--spec/frontend/pipelines/components/dag/dag_annotations_spec.js19
-rw-r--r--spec/frontend/pipelines/components/dag/dag_spec.js9
-rw-r--r--spec/frontend/pipelines/components/jobs/jobs_app_spec.js13
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js37
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js23
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js58
-rw-r--r--spec/frontend/pipelines/graph/job_item_spec.js49
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js113
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js30
-rw-r--r--spec/frontend/pipelines/graph/mock_data.js12
-rw-r--r--spec/frontend/pipelines/header_component_spec.js5
-rw-r--r--spec/frontend/pipelines/mock_data.js680
-rw-r--r--spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js146
-rw-r--r--spec/frontend/pipelines/notification/mock_data.js33
-rw-r--r--spec/frontend/pipelines/pipeline_triggerer_spec.js8
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js349
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js20
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js50
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js5
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_table_spec.js7
23 files changed, 1338 insertions, 353 deletions
diff --git a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
index 52461885342..2d2e5db598a 100644
--- a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
+++ b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
@@ -30,6 +30,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "7",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -71,6 +72,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "12",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -112,6 +114,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "17",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -153,6 +156,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "22",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -178,6 +182,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "25",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -203,6 +208,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "28",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -237,6 +243,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "60",
+ "label": null,
"tooltip": null,
},
},
@@ -295,6 +302,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "35",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -348,6 +356,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "43",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -385,6 +394,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "50",
+ "label": "passed",
"tooltip": "passed",
},
},
@@ -423,6 +433,7 @@ Array [
"hasDetails": true,
"icon": "status_success",
"id": "64",
+ "label": null,
"tooltip": null,
},
},
diff --git a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
index 1941a7f2777..212f8e19a6d 100644
--- a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
@@ -1,5 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
import { singleNote, multiNote } from './mock_data';
@@ -82,26 +83,24 @@ describe('The DAG annotations', () => {
});
describe('clicking hide', () => {
- it('hides listed items and changes text to show', () => {
+ it('hides listed items and changes text to show', async () => {
expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
expect(getToggleButton().text()).toBe('Hide list');
getToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(getAllTextBlocks().length).toBe(0);
- expect(getToggleButton().text()).toBe('Show list');
- });
+ await nextTick();
+ expect(getAllTextBlocks().length).toBe(0);
+ expect(getToggleButton().text()).toBe('Show list');
});
});
describe('clicking show', () => {
- it('shows listed items and changes text to hide', () => {
+ it('shows listed items and changes text to hide', async () => {
getToggleButton().trigger('click');
getToggleButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
- expect(getToggleButton().text()).toBe('Hide list');
- });
+ await nextTick();
+ expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length);
+ expect(getToggleButton().text()).toBe('Hide list');
});
});
});
diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js
index 14030930657..d78df3eb35e 100644
--- a/spec/frontend/pipelines/components/dag/dag_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlEmptyState } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from '~/pipelines/components/dag/constants';
import Dag from '~/pipelines/components/dag/dag.vue';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
@@ -153,11 +154,11 @@ describe('Pipeline DAG graph wrapper', () => {
expect(getNotes().exists()).toBe(false);
getGraph().vm.$emit('update-annotation', { type: ADD_NOTE, data: currentNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(true);
getGraph().vm.$emit('update-annotation', { type: REMOVE_NOTE, data: currentNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(false);
});
@@ -165,11 +166,11 @@ describe('Pipeline DAG graph wrapper', () => {
expect(getNotes().exists()).toBe(false);
getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: multiNote });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(true);
getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: {} });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(getNotes().exists()).toBe(false);
});
});
diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
index 1ea6096c922..65814ad9a7f 100644
--- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
+++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
@@ -1,5 +1,6 @@
import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -9,8 +10,7 @@ import JobsTable from '~/jobs/components/table/jobs_table.vue';
import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql';
import { mockPipelineJobsQueryResponse } from '../../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
jest.mock('~/flash');
@@ -36,7 +36,6 @@ describe('Jobs app', () => {
fullPath: 'root/ci-project',
pipelineIid: 1,
},
- localVue,
apolloProvider: createMockApolloProvider(resolver),
});
};
@@ -74,16 +73,16 @@ describe('Jobs app', () => {
await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({
- message: 'An error occured while fetching the pipelines jobs.',
+ message: 'An error occurred while fetching the pipelines jobs.',
});
});
it('handles infinite scrolling by calling fetchMore', async () => {
createComponent(resolverSpy);
-
await waitForPromises();
triggerInfiniteScroll();
+ await waitForPromises();
expect(resolverSpy).toHaveBeenCalledWith({
after: 'eyJpZCI6Ijg0NyJ9',
@@ -96,10 +95,10 @@ describe('Jobs app', () => {
createComponent(resolverSpy);
expect(findSkeletonLoader().exists()).toBe(true);
-
await waitForPromises();
triggerInfiniteScroll();
+ await waitForPromises();
expect(findSkeletonLoader().exists()).toBe(false);
});
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 661c8d99477..97b59a09518 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -1,6 +1,7 @@
import { GlFilteredSearch } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue';
@@ -103,46 +104,42 @@ describe('Pipelines filtered search', () => {
expect(wrapper.emitted('filterPipelines')[0]).toEqual([mockSearch]);
});
- it('disables tag name token when branch name token is active', () => {
+ it('disables tag name token when branch name token is active', async () => {
findFilteredSearch().vm.$emit('input', [
{ type: 'ref', value: { data: 'branch-1', operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(true);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(true);
});
- it('disables branch name token when tag name token is active', () => {
+ it('disables branch name token when tag name token is active', async () => {
findFilteredSearch().vm.$emit('input', [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(true);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(true);
+ expect(findTagToken().disabled).toBe(false);
});
- it('resets tokens disabled state on clear', () => {
+ it('resets tokens disabled state on clear', async () => {
findFilteredSearch().vm.$emit('clearInput');
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(false);
});
- it('resets tokens disabled state when clearing tokens by backspace', () => {
+ it('resets tokens disabled state when clearing tokens by backspace', async () => {
findFilteredSearch().vm.$emit('input', [{ type: 'filtered-search-term', value: { data: '' } }]);
- return wrapper.vm.$nextTick().then(() => {
- expect(findBranchToken().disabled).toBe(false);
- expect(findTagToken().disabled).toBe(false);
- });
+ await nextTick();
+ expect(findBranchToken().disabled).toBe(false);
+ expect(findTagToken().disabled).toBe(false);
});
describe('Url query params', () => {
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index 177b026491c..fab6e6887b7 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
@@ -9,6 +10,7 @@ describe('pipeline graph action component', () => {
let wrapper;
let mock;
const findButton = () => wrapper.find(GlButton);
+ const findTooltipWrapper = () => wrapper.find('[data-testid="ci-action-icon-tooltip-wrapper"]');
beforeEach(() => {
mock = new MockAdapter(axios);
@@ -30,19 +32,14 @@ describe('pipeline graph action component', () => {
});
it('should render the provided title as a bootstrap tooltip', () => {
- expect(wrapper.attributes('title')).toBe('bar');
+ expect(findTooltipWrapper().attributes('title')).toBe('bar');
});
- it('should update bootstrap tooltip when title changes', (done) => {
+ it('should update bootstrap tooltip when title changes', async () => {
wrapper.setProps({ tooltipText: 'changed' });
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.attributes('title')).toBe('changed');
- })
- .then(done)
- .catch(done.fail);
+ await nextTick();
+ expect(findTooltipWrapper().attributes('title')).toBe('changed');
});
it('should render an svg', () => {
@@ -64,13 +61,11 @@ describe('pipeline graph action component', () => {
.catch(done.fail);
});
- it('renders a loading icon while waiting for request', (done) => {
+ it('renders a loading icon while waiting for request', async () => {
findButton().trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true);
- done();
- });
+ await nextTick();
+ expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 04e004dc6c1..8bc6c086b9d 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -1,10 +1,11 @@
import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
import axios from '~/lib/utils/axios_utils';
@@ -100,15 +101,6 @@ describe('Pipeline graph wrapper', () => {
wrapper.destroy();
});
- beforeAll(() => {
- jest.useFakeTimers();
- });
-
- afterAll(() => {
- jest.runOnlyPendingTimers();
- jest.useRealTimers();
- });
-
describe('when data is loading', () => {
it('displays the loading icon', () => {
createComponentWithApollo();
@@ -134,8 +126,7 @@ describe('Pipeline graph wrapper', () => {
describe('when data has loaded', () => {
beforeEach(async () => {
createComponentWithApollo();
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -163,8 +154,7 @@ describe('Pipeline graph wrapper', () => {
createComponentWithApollo({
getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -187,8 +177,7 @@ describe('Pipeline graph wrapper', () => {
pipelineIid: '',
},
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not display the loading icon', () => {
@@ -210,7 +199,7 @@ describe('Pipeline graph wrapper', () => {
createComponentWithApollo();
jest.spyOn(wrapper.vm.$apollo.queries.headerPipeline, 'refetch');
jest.spyOn(wrapper.vm.$apollo.queries.pipeline, 'refetch');
- await nextTick();
+ await waitForPromises();
getGraph().vm.$emit('refreshPipelineGraph');
});
@@ -224,8 +213,7 @@ describe('Pipeline graph wrapper', () => {
describe('when query times out', () => {
const advanceApolloTimers = async () => {
jest.runOnlyPendingTimers();
- await nextTick();
- await nextTick();
+ await waitForPromises();
};
beforeEach(async () => {
@@ -245,7 +233,7 @@ describe('Pipeline graph wrapper', () => {
.mockResolvedValueOnce(errorData);
createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail });
- await nextTick();
+ await waitForPromises();
});
it('shows correct errors and does not overwrite populated data when data is empty', async () => {
@@ -274,8 +262,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('appears when pipeline uses needs', () => {
@@ -318,7 +305,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('sets showLinks to true', async () => {
@@ -327,8 +314,9 @@ describe('Pipeline graph wrapper', () => {
expect(getLinksLayer().props('showLinks')).toBe(false);
expect(getViewSelector().props('type')).toBe(LAYER_VIEW);
await getDependenciesToggle().vm.$emit('change', true);
+
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true);
});
});
@@ -343,8 +331,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('shows the hover tip in the view selector', async () => {
@@ -365,7 +352,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not show the hover tip', async () => {
@@ -382,8 +369,7 @@ describe('Pipeline graph wrapper', () => {
mountFn: mount,
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
afterEach(() => {
@@ -411,8 +397,7 @@ describe('Pipeline graph wrapper', () => {
getPipelineDetailsHandler: jest.fn().mockResolvedValue(nonNeedsResponse),
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
afterEach(() => {
@@ -435,7 +420,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('does not appear when pipeline does not use needs', () => {
@@ -461,8 +446,7 @@ describe('Pipeline graph wrapper', () => {
describe('with no metrics path', () => {
beforeEach(async () => {
createComponentWithApollo();
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('is not called', () => {
@@ -505,8 +489,7 @@ describe('Pipeline graph wrapper', () => {
},
});
- jest.runOnlyPendingTimers();
- await nextTick();
+ await waitForPromises();
});
it('attempts to collect metrics', () => {
@@ -517,7 +500,7 @@ describe('Pipeline graph wrapper', () => {
});
describe('with duration and no error', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mock = new MockAdapter(axios);
mock.onPost(metricsPath).reply(200, {});
@@ -536,6 +519,7 @@ describe('Pipeline graph wrapper', () => {
currentViewType: LAYER_VIEW,
},
});
+ await waitForPromises();
});
afterEach(() => {
diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js
index 06f1fa4c827..23e7ed7ebb4 100644
--- a/spec/frontend/pipelines/graph/job_item_spec.js
+++ b/spec/frontend/pipelines/graph/job_item_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import JobItem from '~/pipelines/components/graph/job_item.vue';
describe('pipeline graph job item', () => {
@@ -6,6 +7,7 @@ describe('pipeline graph job item', () => {
const findJobWithoutLink = () => wrapper.find('[data-testid="job-without-link"]');
const findJobWithLink = () => wrapper.find('[data-testid="job-with-link"]');
+ const findActionComponent = () => wrapper.find('[data-testid="ci-action-component"]');
const createWrapper = (propsData) => {
wrapper = mount(JobItem, {
@@ -68,28 +70,38 @@ describe('pipeline graph job item', () => {
hasDetails: false,
},
};
+ const mockJobWithUnauthorizedAction = {
+ id: 4258,
+ name: 'stop-environment',
+ status: {
+ icon: 'status_manual',
+ label: 'manual stop action (not allowed)',
+ tooltip: 'manual action',
+ group: 'manual',
+ detailsPath: '/root/ci-mock/builds/4258',
+ hasDetails: true,
+ action: null,
+ },
+ };
afterEach(() => {
wrapper.destroy();
});
describe('name with link', () => {
- it('should render the job name and status with a link', (done) => {
+ it('should render the job name and status with a link', async () => {
createWrapper({ job: mockJob });
- wrapper.vm.$nextTick(() => {
- const link = wrapper.find('a');
-
- expect(link.attributes('href')).toBe(mockJob.status.detailsPath);
+ await nextTick();
+ const link = wrapper.find('a');
- expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`);
+ expect(link.attributes('href')).toBe(mockJob.status.detailsPath);
- expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
+ expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`);
- expect(wrapper.text()).toBe(mockJob.name);
+ expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
- done();
- });
+ expect(wrapper.text()).toBe(mockJob.name);
});
});
@@ -118,8 +130,21 @@ describe('pipeline graph job item', () => {
it('it should render the action icon', () => {
createWrapper({ job: mockJob });
- expect(wrapper.find('.ci-action-icon-container').exists()).toBe(true);
- expect(wrapper.find('.ci-action-icon-wrapper').exists()).toBe(true);
+ const actionComponent = findActionComponent();
+
+ expect(actionComponent.exists()).toBe(true);
+ expect(actionComponent.props('actionIcon')).toBe('retry');
+ expect(actionComponent.attributes('disabled')).not.toBe('disabled');
+ });
+
+ it('it should render disabled action icon when user cannot run the action', () => {
+ createWrapper({ job: mockJobWithUnauthorizedAction });
+
+ const actionComponent = findActionComponent();
+
+ expect(actionComponent.exists()).toBe(true);
+ expect(actionComponent.props('actionIcon')).toBe('stop');
+ expect(actionComponent.attributes('disabled')).toBe('disabled');
});
});
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index af5cd907dd8..d800a8c341e 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -9,6 +9,23 @@ import mockPipeline from './linked_pipelines_mock_data';
describe('Linked pipeline', () => {
let wrapper;
+ const downstreamProps = {
+ pipeline: {
+ ...mockPipeline,
+ multiproject: false,
+ },
+ columnTitle: 'Downstream',
+ type: DOWNSTREAM,
+ expanded: false,
+ isLoading: false,
+ };
+
+ const upstreamProps = {
+ ...downstreamProps,
+ columnTitle: 'Upstream',
+ type: UPSTREAM,
+ };
+
const findButton = () => wrapper.find(GlButton);
const findDownstreamPipelineTitle = () => wrapper.find('[data-testid="downstream-title"]');
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]');
@@ -86,91 +103,65 @@ describe('Linked pipeline', () => {
});
});
- describe('parent/child', () => {
- const downstreamProps = {
- pipeline: {
- ...mockPipeline,
- multiproject: false,
- },
- columnTitle: 'Downstream',
- type: DOWNSTREAM,
- expanded: false,
- isLoading: false,
- };
+ describe('upstream pipelines', () => {
+ beforeEach(() => {
+ createWrapper(upstreamProps);
+ });
- const upstreamProps = {
- ...downstreamProps,
- columnTitle: 'Upstream',
- type: UPSTREAM,
- };
+ it('should display parent label when pipeline project id is the same as triggered_by pipeline project id', () => {
+ expect(findPipelineLabel().exists()).toBe(true);
+ });
- it('parent/child label container should exist', () => {
+ it('upstream pipeline should contain the correct link', () => {
+ expect(findPipelineLink().attributes('href')).toBe(upstreamProps.pipeline.path);
+ });
+
+ it('applies the reverse-row css class to the card', () => {
+ expect(findLinkedPipeline().classes()).toContain('gl-flex-direction-row-reverse');
+ expect(findLinkedPipeline().classes()).not.toContain('gl-flex-direction-row');
+ });
+ });
+
+ describe('downstream pipelines', () => {
+ beforeEach(() => {
createWrapper(downstreamProps);
+ });
+
+ it('parent/child label container should exist', () => {
expect(findPipelineLabel().exists()).toBe(true);
});
it('should display child label when pipeline project id is the same as triggered pipeline project id', () => {
- createWrapper(downstreamProps);
expect(findPipelineLabel().exists()).toBe(true);
});
it('should have the name of the trigger job on the card when it is a child pipeline', () => {
- createWrapper(downstreamProps);
expect(findDownstreamPipelineTitle().text()).toBe(mockPipeline.sourceJob.name);
});
- it('should display parent label when pipeline project id is the same as triggered_by pipeline project id', () => {
- createWrapper(upstreamProps);
- expect(findPipelineLabel().exists()).toBe(true);
- });
-
it('downstream pipeline should contain the correct link', () => {
- createWrapper(downstreamProps);
expect(findPipelineLink().attributes('href')).toBe(downstreamProps.pipeline.path);
});
- it('upstream pipeline should contain the correct link', () => {
- createWrapper(upstreamProps);
- expect(findPipelineLink().attributes('href')).toBe(upstreamProps.pipeline.path);
+ it('applies the flex-row css class to the card', () => {
+ expect(findLinkedPipeline().classes()).toContain('gl-flex-direction-row');
+ expect(findLinkedPipeline().classes()).not.toContain('gl-flex-direction-row-reverse');
});
+ });
+ describe('expand button', () => {
it.each`
- presentClass | missingClass
- ${'gl-right-0'} | ${'gl-left-0'}
- ${'gl-border-l-1!'} | ${'gl-border-r-1!'}
- `(
- 'pipeline expand button should be postioned right when child pipeline',
- ({ presentClass, missingClass }) => {
- createWrapper(downstreamProps);
- expect(findExpandButton().classes()).toContain(presentClass);
- expect(findExpandButton().classes()).not.toContain(missingClass);
- },
- );
-
- it.each`
- presentClass | missingClass
- ${'gl-left-0'} | ${'gl-right-0'}
- ${'gl-border-r-1!'} | ${'gl-border-l-1!'}
- `(
- 'pipeline expand button should be postioned left when parent pipeline',
- ({ presentClass, missingClass }) => {
- createWrapper(upstreamProps);
- expect(findExpandButton().classes()).toContain(presentClass);
- expect(findExpandButton().classes()).not.toContain(missingClass);
- },
- );
-
- it.each`
- pipelineType | anglePosition | expanded
- ${downstreamProps} | ${'angle-right'} | ${false}
- ${downstreamProps} | ${'angle-left'} | ${true}
- ${upstreamProps} | ${'angle-left'} | ${false}
- ${upstreamProps} | ${'angle-right'} | ${true}
+ pipelineType | anglePosition | borderClass | expanded
+ ${downstreamProps} | ${'angle-right'} | ${'gl-border-l-1!'} | ${false}
+ ${downstreamProps} | ${'angle-left'} | ${'gl-border-l-1!'} | ${true}
+ ${upstreamProps} | ${'angle-left'} | ${'gl-border-r-1!'} | ${false}
+ ${upstreamProps} | ${'angle-right'} | ${'gl-border-r-1!'} | ${true}
`(
- '$pipelineType.columnTitle pipeline button icon should be $anglePosition if expanded state is $expanded',
- ({ pipelineType, anglePosition, expanded }) => {
+ '$pipelineType.columnTitle pipeline button icon should be $anglePosition with $borderClass if expanded state is $expanded',
+ ({ pipelineType, anglePosition, borderClass, expanded }) => {
createWrapper({ ...pipelineType, expanded });
expect(findExpandButton().props('icon')).toBe(anglePosition);
+ expect(findExpandButton().classes()).toContain(borderClass);
},
);
});
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 2f03b846525..1673065e09c 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -1,6 +1,8 @@
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import {
DOWNSTREAM,
@@ -40,13 +42,11 @@ describe('Linked Pipelines Column', () => {
const findPipelineGraph = () => wrapper.find(PipelineGraph);
const findExpandButton = () => wrapper.find('[data-testid="expand-pipeline-button"]');
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const createComponent = ({ apolloProvider, mountFn = shallowMount, props = {} } = {}) => {
wrapper = mountFn(LinkedPipelinesColumn, {
apolloProvider,
- localVue,
propsData: {
...defaultProps,
...props,
@@ -87,13 +87,7 @@ describe('Linked Pipelines Column', () => {
describe('click action', () => {
const clickExpandButton = async () => {
await findExpandButton().trigger('click');
- await wrapper.vm.$nextTick();
- };
-
- const clickExpandButtonAndAwaitTimers = async () => {
- await clickExpandButton();
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await waitForPromises();
};
describe('layer type rendering', () => {
@@ -106,9 +100,9 @@ describe('Linked Pipelines Column', () => {
it('calls listByLayers only once no matter how many times view is switched', async () => {
expect(layersFn).not.toHaveBeenCalled();
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
await wrapper.setProps({ viewType: LAYER_VIEW });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(layersFn).toHaveBeenCalledTimes(1);
await wrapper.setProps({ viewType: STAGE_VIEW });
await wrapper.setProps({ viewType: LAYER_VIEW });
@@ -132,7 +126,7 @@ describe('Linked Pipelines Column', () => {
});
it('shows the stage view, even when the main graph view type is layers', async () => {
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().props('viewType')).toBe(STAGE_VIEW);
});
});
@@ -145,7 +139,7 @@ describe('Linked Pipelines Column', () => {
it('toggles the pipeline visibility', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(true);
await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
@@ -167,7 +161,7 @@ describe('Linked Pipelines Column', () => {
it('does not show the pipeline', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
});
});
@@ -195,7 +189,7 @@ describe('Linked Pipelines Column', () => {
it('toggles the pipeline visibility', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(true);
await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
@@ -218,7 +212,7 @@ describe('Linked Pipelines Column', () => {
it('does not show the pipeline', async () => {
expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
+ await clickExpandButton();
expect(findPipelineGraph().exists()).toBe(false);
});
});
diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js
index 41823bfdb9f..0cf7dc507f4 100644
--- a/spec/frontend/pipelines/graph/mock_data.js
+++ b/spec/frontend/pipelines/graph/mock_data.js
@@ -57,6 +57,7 @@ export const mockPipelineResponse = {
id: '7',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1482',
group: 'success',
@@ -106,6 +107,7 @@ export const mockPipelineResponse = {
id: '12',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1515',
group: 'success',
@@ -155,6 +157,7 @@ export const mockPipelineResponse = {
id: '17',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1484',
group: 'success',
@@ -204,6 +207,7 @@ export const mockPipelineResponse = {
id: '22',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1485',
group: 'success',
@@ -235,6 +239,7 @@ export const mockPipelineResponse = {
id: '25',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1486',
group: 'success',
@@ -266,6 +271,7 @@ export const mockPipelineResponse = {
id: '28',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1487',
group: 'success',
@@ -330,6 +336,7 @@ export const mockPipelineResponse = {
id: '35',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1514',
group: 'success',
@@ -413,6 +420,7 @@ export const mockPipelineResponse = {
id: '43',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1489',
group: 'success',
@@ -498,6 +506,7 @@ export const mockPipelineResponse = {
id: '50',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/abcd-dag/-/jobs/1490',
group: 'success',
@@ -601,6 +610,7 @@ export const mockPipelineResponse = {
id: '60',
icon: 'status_success',
tooltip: null,
+ label: null,
hasDetails: true,
detailsPath: '/root/kinder-pipe/-/pipelines/154',
group: 'success',
@@ -643,6 +653,7 @@ export const mockPipelineResponse = {
id: '64',
icon: 'status_success',
tooltip: null,
+ label: null,
hasDetails: true,
detailsPath: '/root/abcd-dag/-/pipelines/153',
group: 'success',
@@ -850,6 +861,7 @@ export const wrappedPipelineReturn = {
id: '84',
icon: 'status_success',
tooltip: 'passed',
+ label: 'passed',
hasDetails: true,
detailsPath: '/root/elemenohpee/-/jobs/1662',
group: 'success',
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
index 9e51003da66..1d89f949564 100644
--- a/spec/frontend/pipelines/header_component_spec.js
+++ b/spec/frontend/pipelines/header_component_spec.js
@@ -4,6 +4,7 @@ import HeaderComponent from '~/pipelines/components/header_component.vue';
import cancelPipelineMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
import deletePipelineMutation from '~/pipelines/graphql/mutations/delete_pipeline.mutation.graphql';
import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
+import { BUTTON_TOOLTIP_RETRY } from '~/pipelines/constants';
import {
mockCancelledPipelineHeader,
mockFailedPipelineHeader,
@@ -113,6 +114,10 @@ describe('Pipeline details header', () => {
variables: { id: mockCancelledPipelineHeader.id },
});
});
+
+ it('should render retry action tooltip', () => {
+ expect(findRetryButton().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
+ });
});
describe('Cancel action', () => {
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index b9d20eb7ca5..8cb6cf3bed6 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -634,3 +634,683 @@ export const mockPipelineJobsQueryResponse = {
},
},
};
+
+export const mockPipeline = (projectPath) => {
+ return {
+ pipeline: {
+ id: 1,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: '',
+ web_url: 'http://0.0.0.0:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'merge_request_event',
+ created_at: '2021-10-19T21:17:38.698Z',
+ updated_at: '2021-10-21T18:00:42.758Z',
+ path: 'foo',
+ flags: {},
+ merge_request: {
+ iid: 1,
+ path: `/${projectPath}/1`,
+ title: 'commit',
+ source_branch: 'test-commit-name',
+ source_branch_path: `/${projectPath}`,
+ target_branch: 'main',
+ target_branch_path: `/${projectPath}/-/commit/main`,
+ },
+ ref: {
+ name: 'refs/merge-requests/1/head',
+ path: `/${projectPath}/-/commits/refs/merge-requests/1/head`,
+ tag: false,
+ branch: false,
+ merge_request: true,
+ },
+ commit: {
+ id: 'fd6df5b3229e213c97d308844a6f3e7fd71e8f8c',
+ short_id: 'fd6df5b3',
+ created_at: '2021-10-19T21:17:12.000+00:00',
+ parent_ids: ['7147906b84306e83cb3fec6582a25390b75713c6'],
+ title: 'Commit Title',
+ message: 'Commit',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2021-10-19T21:17:12.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2021-10-19T21:17:12.000+00:00',
+ trailers: {},
+ web_url: '',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: '',
+ web_url: '',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url: '',
+ commit_url: `/${projectPath}/fd6df5b3229e213c97d308844a6f3e7fd71e8f8c`,
+ commit_path: `/${projectPath}/commit/fd6df5b3229e213c97d308844a6f3e7fd71e8f8c`,
+ },
+ project: {
+ full_path: `/${projectPath}`,
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineTag = () => {
+ return {
+ pipeline: {
+ id: 311,
+ iid: 37,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-02-02T15:39:04.012Z',
+ updated_at: '2022-02-02T15:40:59.573Z',
+ path: '/root/mr-widgets/-/pipelines/311',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'accessibility',
+ title: 'accessibility: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#accessibility',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#accessibility',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=accessibility',
+ },
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/311#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/311#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/311/stage.json?stage=build',
+ },
+ ],
+ duration: 93,
+ finished_at: '2022-02-02T15:40:59.384Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'test',
+ path: '/root/mr-widgets/-/commits/test',
+ tag: true,
+ branch: false,
+ merge_request: false,
+ },
+ commit: {
+ id: '9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ short_id: '9b92b4f7',
+ created_at: '2022-01-13T13:59:03.000+00:00',
+ parent_ids: ['0ba763634114e207dc72c65c8e9459556b1204fb'],
+ title: 'Update hello_world.js',
+ message: 'Update hello_world.js',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2022-01-13T13:59:03.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2022-01-13T13:59:03.000+00:00',
+ trailers: {},
+ web_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ author: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commit_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ commit_path: '/root/mr-widgets/-/commit/9b92b4f730d1611bd9a086ca221ae206d5da1e59',
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/311/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/311',
+ failed_builds: [
+ {
+ id: 1696,
+ name: 'fmt',
+ started: '2022-02-02T15:39:45.192Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1696',
+ retry_path: '/root/mr-widgets/-/jobs/1696/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-02-02T15:39:04.136Z',
+ updated_at: '2022-02-02T15:39:57.969Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1696',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1696/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineBranch = () => {
+ return {
+ pipeline: {
+ id: 268,
+ iid: 34,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-01-14T17:40:27.866Z',
+ updated_at: '2022-01-14T18:02:35.850Z',
+ path: '/root/mr-widgets/-/pipelines/268',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
+ },
+ ],
+ duration: 75,
+ finished_at: '2022-01-14T18:02:35.842Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'update-ci',
+ path: '/root/mr-widgets/-/commits/update-ci',
+ tag: false,
+ branch: true,
+ merge_request: false,
+ },
+ commit: {
+ id: '96aef9ecec5752c09371c1ade5fc77860aafc863',
+ short_id: '96aef9ec',
+ created_at: '2022-01-14T17:40:26.000+00:00',
+ parent_ids: ['06860257572d4cf84b73806250b78169050aed83'],
+ title: 'Update main.tf',
+ message: 'Update main.tf',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2022-01-14T17:40:26.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2022-01-14T17:40:26.000+00:00',
+ trailers: {},
+ web_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ author: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commit_url:
+ 'http://gdk.test:3000/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ commit_path: '/root/mr-widgets/-/commit/96aef9ecec5752c09371c1ade5fc77860aafc863',
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/268/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/268',
+ failed_builds: [
+ {
+ id: 1260,
+ name: 'fmt',
+ started: '2022-01-14T17:40:36.435Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1260',
+ retry_path: '/root/mr-widgets/-/jobs/1260/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-01-14T17:40:27.879Z',
+ updated_at: '2022-01-14T17:40:42.129Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1260',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1260/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
+
+export const mockPipelineNoCommit = () => {
+ return {
+ pipeline: {
+ id: 268,
+ iid: 34,
+ user: {
+ id: 1,
+ username: 'root',
+ name: 'Administrator',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ active: false,
+ source: 'push',
+ created_at: '2022-01-14T17:40:27.866Z',
+ updated_at: '2022-01-14T18:02:35.850Z',
+ path: '/root/mr-widgets/-/pipelines/268',
+ flags: {
+ stuck: false,
+ auto_devops: false,
+ merge_request: false,
+ yaml_errors: false,
+ retryable: true,
+ cancelable: false,
+ failure_reason: false,
+ detached_merge_request_pipeline: false,
+ merge_request_pipeline: false,
+ merge_train_pipeline: false,
+ latest: true,
+ },
+ details: {
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ stages: [
+ {
+ name: 'validate',
+ title: 'validate: passed with warnings',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#validate',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#validate',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
+ },
+ {
+ name: 'test',
+ title: 'test: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#test',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
+ },
+ {
+ name: 'build',
+ title: 'build: passed',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/pipelines/268#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/root/mr-widgets/-/pipelines/268#build',
+ dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
+ },
+ ],
+ duration: 75,
+ finished_at: '2022-01-14T18:02:35.842Z',
+ name: 'Pipeline',
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'update-ci',
+ path: '/root/mr-widgets/-/commits/update-ci',
+ tag: false,
+ branch: true,
+ merge_request: false,
+ },
+ retry_path: '/root/mr-widgets/-/pipelines/268/retry',
+ delete_path: '/root/mr-widgets/-/pipelines/268',
+ failed_builds: [
+ {
+ id: 1260,
+ name: 'fmt',
+ started: '2022-01-14T17:40:36.435Z',
+ complete: true,
+ archived: false,
+ build_path: '/root/mr-widgets/-/jobs/1260',
+ retry_path: '/root/mr-widgets/-/jobs/1260/retry',
+ playable: false,
+ scheduled: false,
+ created_at: '2022-01-14T17:40:27.879Z',
+ updated_at: '2022-01-14T17:40:42.129Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed-with-warnings',
+ tooltip: 'failed - (script failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/root/mr-widgets/-/jobs/1260',
+ illustration: {
+ image:
+ '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/mr-widgets/-/jobs/1260/retry',
+ method: 'post',
+ button_title: 'Retry this job',
+ },
+ },
+ recoverable: false,
+ },
+ ],
+ project: {
+ id: 23,
+ name: 'mr-widgets',
+ full_path: '/root/mr-widgets',
+ full_name: 'Administrator / mr-widgets',
+ },
+ triggered_by: null,
+ triggered: [],
+ },
+ pipelineScheduleUrl: 'foo',
+ pipelineKey: 'id',
+ viewType: 'root',
+ };
+};
diff --git a/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js b/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js
new file mode 100644
index 00000000000..f626652a944
--- /dev/null
+++ b/spec/frontend/pipelines/notification/deprecated_type_keyword_notification_spec.js
@@ -0,0 +1,146 @@
+import VueApollo from 'vue-apollo';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import DeprecatedTypeKeywordNotification from '~/pipelines/components/notification/deprecated_type_keyword_notification.vue';
+import getPipelineWarnings from '~/pipelines/graphql/queries/get_pipeline_warnings.query.graphql';
+import {
+ mockWarningsWithoutDeprecation,
+ mockWarningsRootType,
+ mockWarningsType,
+ mockWarningsTypesAll,
+} from './mock_data';
+
+const defaultProvide = {
+ deprecatedKeywordsDocPath: '/help/ci/yaml/index.md#deprecated-keywords',
+ fullPath: '/namespace/my-project',
+ pipelineIid: 4,
+};
+
+let wrapper;
+
+const mockWarnings = jest.fn();
+
+const createComponent = ({ isLoading = false, options = {} } = {}) => {
+ return shallowMount(DeprecatedTypeKeywordNotification, {
+ stubs: {
+ GlSprintf,
+ },
+ provide: {
+ ...defaultProvide,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ warnings: {
+ loading: isLoading,
+ },
+ },
+ },
+ },
+ ...options,
+ });
+};
+
+const createComponentWithApollo = () => {
+ const localVue = createLocalVue();
+ localVue.use(VueApollo);
+
+ const handlers = [[getPipelineWarnings, mockWarnings]];
+ const mockApollo = createMockApollo(handlers);
+
+ return createComponent({
+ options: {
+ localVue,
+ apolloProvider: mockApollo,
+ mocks: {},
+ },
+ });
+};
+
+const findAlert = () => wrapper.findComponent(GlAlert);
+const findAlertItems = () => findAlert().findAll('li');
+
+afterEach(() => {
+ wrapper.destroy();
+});
+
+describe('Deprecated keyword notification', () => {
+ describe('while loading the pipeline warnings', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ isLoading: true });
+ });
+
+ it('does not display the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('if there is an error in the query', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue({ errors: ['It didnt work'] });
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('does not display the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('with a valid query result', () => {
+ describe('if there are no deprecation warnings', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsWithoutDeprecation);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('does not show the notification', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('with a root type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsRootType);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with one item', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(1);
+ expect(findAlertItems().at(0).text()).toContain('types');
+ });
+ });
+
+ describe('with a job type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsType);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with one item', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(1);
+ expect(findAlertItems().at(0).text()).toContain('type');
+ expect(findAlertItems().at(0).text()).not.toContain('types');
+ });
+ });
+
+ describe('with both the root types and job type deprecation message', () => {
+ beforeEach(async () => {
+ mockWarnings.mockResolvedValue(mockWarningsTypesAll);
+ wrapper = createComponentWithApollo();
+ await waitForPromises();
+ });
+ it('shows the notification with two items', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlertItems()).toHaveLength(2);
+ expect(findAlertItems().at(0).text()).toContain('types');
+ expect(findAlertItems().at(1).text()).toContain('type');
+ expect(findAlertItems().at(1).text()).not.toContain('types');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/notification/mock_data.js b/spec/frontend/pipelines/notification/mock_data.js
new file mode 100644
index 00000000000..e36f391a854
--- /dev/null
+++ b/spec/frontend/pipelines/notification/mock_data.js
@@ -0,0 +1,33 @@
+const randomWarning = {
+ content: 'another random warning',
+ id: 'gid://gitlab/Ci::PipelineMessage/272',
+};
+
+const rootTypeWarning = {
+ content: 'root `types` will be removed in 15.0.',
+ id: 'gid://gitlab/Ci::PipelineMessage/273',
+};
+
+const typeWarning = {
+ content: '`type` will be removed in 15.0.',
+ id: 'gid://gitlab/Ci::PipelineMessage/274',
+};
+
+function createWarningMock(warnings) {
+ return {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/28"',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/183',
+ warningMessages: warnings,
+ },
+ },
+ },
+ };
+}
+
+export const mockWarningsWithoutDeprecation = createWarningMock([randomWarning]);
+export const mockWarningsRootType = createWarningMock([rootTypeWarning]);
+export const mockWarningsType = createWarningMock([typeWarning]);
+export const mockWarningsTypesAll = createWarningMock([rootTypeWarning, typeWarning]);
diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js
index ffb2721f159..701b1691c7b 100644
--- a/spec/frontend/pipelines/pipeline_triggerer_spec.js
+++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import pipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_triggerer.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -47,15 +48,14 @@ describe('Pipelines Triggerer', () => {
});
});
- it('should render "API" when no triggerer is provided', () => {
+ it('should render "API" when no triggerer is provided', async () => {
wrapper.setProps({
pipeline: {
user: null,
},
});
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
- });
+ await nextTick();
+ expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
});
});
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index 912b5afe0e1..b24e2e09ea8 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -1,41 +1,48 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { trimText } from 'helpers/text_helper';
import PipelineUrlComponent from '~/pipelines/components/pipelines_list/pipeline_url.vue';
+import {
+ mockPipeline,
+ mockPipelineBranch,
+ mockPipelineTag,
+ mockPipelineNoCommit,
+} from './mock_data';
const projectPath = 'test/test';
describe('Pipeline Url Component', () => {
let wrapper;
- const findTableCell = () => wrapper.find('[data-testid="pipeline-url-table-cell"]');
- const findPipelineUrlLink = () => wrapper.find('[data-testid="pipeline-url-link"]');
- const findScheduledTag = () => wrapper.find('[data-testid="pipeline-url-scheduled"]');
- const findLatestTag = () => wrapper.find('[data-testid="pipeline-url-latest"]');
- const findYamlTag = () => wrapper.find('[data-testid="pipeline-url-yaml"]');
- const findFailureTag = () => wrapper.find('[data-testid="pipeline-url-failure"]');
- const findAutoDevopsTag = () => wrapper.find('[data-testid="pipeline-url-autodevops"]');
- const findAutoDevopsTagLink = () => wrapper.find('[data-testid="pipeline-url-autodevops-link"]');
- const findStuckTag = () => wrapper.find('[data-testid="pipeline-url-stuck"]');
- const findDetachedTag = () => wrapper.find('[data-testid="pipeline-url-detached"]');
- const findForkTag = () => wrapper.find('[data-testid="pipeline-url-fork"]');
- const findTrainTag = () => wrapper.find('[data-testid="pipeline-url-train"]');
-
- const defaultProps = {
- pipeline: {
- id: 1,
- path: 'foo',
- project: { full_path: `/${projectPath}` },
- flags: {},
- },
- pipelineScheduleUrl: 'foo',
- pipelineKey: 'id',
- };
-
- const createComponent = (props) => {
- wrapper = shallowMount(PipelineUrlComponent, {
+ const findTableCell = () => wrapper.findByTestId('pipeline-url-table-cell');
+ const findPipelineUrlLink = () => wrapper.findByTestId('pipeline-url-link');
+ const findScheduledTag = () => wrapper.findByTestId('pipeline-url-scheduled');
+ const findLatestTag = () => wrapper.findByTestId('pipeline-url-latest');
+ const findYamlTag = () => wrapper.findByTestId('pipeline-url-yaml');
+ const findFailureTag = () => wrapper.findByTestId('pipeline-url-failure');
+ const findAutoDevopsTag = () => wrapper.findByTestId('pipeline-url-autodevops');
+ const findAutoDevopsTagLink = () => wrapper.findByTestId('pipeline-url-autodevops-link');
+ const findStuckTag = () => wrapper.findByTestId('pipeline-url-stuck');
+ const findDetachedTag = () => wrapper.findByTestId('pipeline-url-detached');
+ const findForkTag = () => wrapper.findByTestId('pipeline-url-fork');
+ const findTrainTag = () => wrapper.findByTestId('pipeline-url-train');
+ const findRefName = () => wrapper.findByTestId('merge-request-ref');
+ const findCommitShortSha = () => wrapper.findByTestId('commit-short-sha');
+ const findCommitIcon = () => wrapper.findByTestId('commit-icon');
+ const findCommitIconType = () => wrapper.findByTestId('commit-icon-type');
+
+ const findCommitTitleContainer = () => wrapper.findByTestId('commit-title-container');
+ const findCommitTitle = () => wrapper.findByTestId('commit-title');
+
+ const defaultProps = mockPipeline(projectPath);
+
+ const createComponent = (props, rearrangePipelinesTable = false) => {
+ wrapper = shallowMountExtended(PipelineUrlComponent, {
propsData: { ...defaultProps, ...props },
provide: {
targetProjectFullPath: projectPath,
+ glFeatures: {
+ rearrangePipelinesTable,
+ },
},
});
};
@@ -45,158 +52,218 @@ describe('Pipeline Url Component', () => {
wrapper = null;
});
- it('should render pipeline url table cell', () => {
- createComponent();
+ describe('with the rearrangePipelinesTable feature flag turned off', () => {
+ it('should render pipeline url table cell', () => {
+ createComponent();
- expect(findTableCell().exists()).toBe(true);
- });
+ expect(findTableCell().exists()).toBe(true);
+ });
- it('should render a link the provided path and id', () => {
- createComponent();
+ it('should render a link the provided path and id', () => {
+ createComponent();
- expect(findPipelineUrlLink().attributes('href')).toBe('foo');
+ expect(findPipelineUrlLink().attributes('href')).toBe('foo');
- expect(findPipelineUrlLink().text()).toBe('#1');
- });
+ expect(findPipelineUrlLink().text()).toBe('#1');
+ });
- it('should not render tags when flags are not set', () => {
- createComponent();
-
- expect(findStuckTag().exists()).toBe(false);
- expect(findLatestTag().exists()).toBe(false);
- expect(findYamlTag().exists()).toBe(false);
- expect(findAutoDevopsTag().exists()).toBe(false);
- expect(findFailureTag().exists()).toBe(false);
- expect(findScheduledTag().exists()).toBe(false);
- expect(findForkTag().exists()).toBe(false);
- expect(findTrainTag().exists()).toBe(false);
- });
+ it('should not render tags when flags are not set', () => {
+ createComponent();
+
+ expect(findStuckTag().exists()).toBe(false);
+ expect(findLatestTag().exists()).toBe(false);
+ expect(findYamlTag().exists()).toBe(false);
+ expect(findAutoDevopsTag().exists()).toBe(false);
+ expect(findFailureTag().exists()).toBe(false);
+ expect(findScheduledTag().exists()).toBe(false);
+ expect(findForkTag().exists()).toBe(false);
+ expect(findTrainTag().exists()).toBe(false);
+ });
- it('should render the stuck tag when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- stuck: true,
- },
- },
+ it('should render the stuck tag when flag is provided', () => {
+ const stuckPipeline = defaultProps.pipeline;
+ stuckPipeline.flags.stuck = true;
+
+ createComponent({
+ ...stuckPipeline.pipeline,
+ });
+
+ expect(findStuckTag().text()).toContain('stuck');
});
- expect(findStuckTag().text()).toContain('stuck');
- });
+ it('should render latest tag when flag is provided', () => {
+ const latestPipeline = defaultProps.pipeline;
+ latestPipeline.flags.latest = true;
- it('should render latest tag when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- latest: true,
- },
- },
+ createComponent({
+ ...latestPipeline,
+ });
+
+ expect(findLatestTag().text()).toContain('latest');
});
- expect(findLatestTag().text()).toContain('latest');
- });
+ it('should render a yaml badge when it is invalid', () => {
+ const yamlPipeline = defaultProps.pipeline;
+ yamlPipeline.flags.yaml_errors = true;
- it('should render a yaml badge when it is invalid', () => {
- createComponent({
- pipeline: {
- flags: {
- yaml_errors: true,
- },
- },
+ createComponent({
+ ...yamlPipeline,
+ });
+
+ expect(findYamlTag().text()).toContain('yaml invalid');
});
- expect(findYamlTag().text()).toContain('yaml invalid');
- });
+ it('should render an autodevops badge when flag is provided', () => {
+ const autoDevopsPipeline = defaultProps.pipeline;
+ autoDevopsPipeline.flags.auto_devops = true;
- it('should render an autodevops badge when flag is provided', () => {
- createComponent({
- pipeline: {
- ...defaultProps.pipeline,
- flags: {
- auto_devops: true,
- },
- },
+ createComponent({
+ ...autoDevopsPipeline,
+ });
+
+ expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
+
+ expect(findAutoDevopsTagLink().attributes()).toMatchObject({
+ href: '/help/topics/autodevops/index.md',
+ target: '_blank',
+ });
});
- expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
+ it('should render a detached badge when flag is provided', () => {
+ const detachedMRPipeline = defaultProps.pipeline;
+ detachedMRPipeline.flags.detached_merge_request_pipeline = true;
- expect(findAutoDevopsTagLink().attributes()).toMatchObject({
- href: '/help/topics/autodevops/index.md',
- target: '_blank',
+ createComponent({
+ ...detachedMRPipeline,
+ });
+
+ expect(findDetachedTag().text()).toContain('detached');
});
- });
- it('should render a detached badge when flag is provided', () => {
- createComponent({
- pipeline: {
- flags: {
- detached_merge_request_pipeline: true,
- },
- },
+ it('should render error badge when pipeline has a failure reason set', () => {
+ const failedPipeline = defaultProps.pipeline;
+ failedPipeline.flags.failure_reason = true;
+ failedPipeline.failure_reason = 'some reason';
+
+ createComponent({
+ ...failedPipeline,
+ });
+
+ expect(findFailureTag().text()).toContain('error');
+ expect(findFailureTag().attributes('title')).toContain('some reason');
});
- expect(findDetachedTag().text()).toContain('detached');
- });
+ it('should render scheduled badge when pipeline was triggered by a schedule', () => {
+ const scheduledPipeline = defaultProps.pipeline;
+ scheduledPipeline.source = 'schedule';
- it('should render error badge when pipeline has a failure reason set', () => {
- createComponent({
- pipeline: {
- flags: {
- failure_reason: true,
- },
- failure_reason: 'some reason',
- },
+ createComponent({
+ ...scheduledPipeline,
+ });
+
+ expect(findScheduledTag().exists()).toBe(true);
+ expect(findScheduledTag().text()).toContain('Scheduled');
});
- expect(findFailureTag().text()).toContain('error');
- expect(findFailureTag().attributes('title')).toContain('some reason');
- });
+ it('should render the fork badge when the pipeline was run in a fork', () => {
+ const forkedPipeline = defaultProps.pipeline;
+ forkedPipeline.project.full_path = '/test/forked';
- it('should render scheduled badge when pipeline was triggered by a schedule', () => {
- createComponent({
- pipeline: {
- flags: {},
- source: 'schedule',
- },
+ createComponent({
+ ...forkedPipeline,
+ });
+
+ expect(findForkTag().exists()).toBe(true);
+ expect(findForkTag().text()).toBe('fork');
});
- expect(findScheduledTag().exists()).toBe(true);
- expect(findScheduledTag().text()).toContain('Scheduled');
- });
+ it('should render the train badge when the pipeline is a merge train pipeline', () => {
+ const mergeTrainPipeline = defaultProps.pipeline;
+ mergeTrainPipeline.flags.merge_train_pipeline = true;
- it('should render the fork badge when the pipeline was run in a fork', () => {
- createComponent({
- pipeline: {
- flags: {},
- project: { fullPath: '/test/forked' },
- },
+ createComponent({
+ ...mergeTrainPipeline,
+ });
+
+ expect(findTrainTag().text()).toContain('train');
});
- expect(findForkTag().exists()).toBe(true);
- expect(findForkTag().text()).toBe('fork');
- });
+ it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
+ const mergeTrainPipeline = defaultProps.pipeline;
+ mergeTrainPipeline.flags.merge_train_pipeline = false;
- it('should render the train badge when the pipeline is a merge train pipeline', () => {
- createComponent({
- pipeline: {
- flags: {
- merge_train_pipeline: true,
- },
- },
+ createComponent({
+ ...mergeTrainPipeline,
+ });
+
+ expect(findTrainTag().exists()).toBe(false);
});
- expect(findTrainTag().text()).toContain('train');
+ it('should not render the commit wrapper and commit-short-sha', () => {
+ createComponent();
+
+ expect(findCommitTitleContainer().exists()).toBe(false);
+ expect(findCommitShortSha().exists()).toBe(false);
+ });
});
- it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
- createComponent({
- pipeline: {
- flags: {
- merge_train_pipeline: false,
- },
+ describe('with the rearrangePipelinesTable feature flag turned on', () => {
+ it('should render the commit title, commit reference and commit-short-sha', () => {
+ createComponent({}, true);
+
+ const commitWrapper = findCommitTitleContainer();
+
+ expect(findCommitTitle(commitWrapper).exists()).toBe(true);
+ expect(findRefName().exists()).toBe(true);
+ expect(findCommitShortSha().exists()).toBe(true);
+ });
+
+ it('should render commit icon tooltip', () => {
+ createComponent({}, true);
+
+ expect(findCommitIcon().attributes('title')).toBe('Commit');
+ });
+
+ it.each`
+ pipeline | expectedTitle
+ ${mockPipelineTag()} | ${'Tag'}
+ ${mockPipelineBranch()} | ${'Branch'}
+ ${mockPipeline()} | ${'Merge Request'}
+ `(
+ 'should render tooltip $expectedTitle for commit icon type',
+ ({ pipeline, expectedTitle }) => {
+ createComponent(pipeline, true);
+
+ expect(findCommitIconType().attributes('title')).toBe(expectedTitle);
},
+ );
+
+ describe('with commit', () => {
+ beforeEach(() => {
+ createComponent({}, true);
+ });
+
+ it('displays commit title with link to pipeline', () => {
+ expect(findCommitTitle().attributes('href')).toBe(defaultProps.pipeline.path);
+ });
+
+ it('displays commit title text', () => {
+ expect(findCommitTitle().text()).toBe(defaultProps.pipeline.commit.title);
+ });
});
- expect(findTrainTag().exists()).toBe(false);
+ describe('without commit', () => {
+ beforeEach(() => {
+ createComponent(mockPipelineNoCommit(), true);
+ });
+
+ it('displays cant find head commit text', () => {
+ expect(findCommitTitle().text()).toBe("Can't find HEAD commit for this branch");
+ });
+
+ it('displays link to pipeline', () => {
+ expect(findCommitTitle().attributes('href')).toBe(mockPipelineNoCommit().pipeline.path);
+ });
+ });
});
});
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index c4bfec8ae14..9b2ee6b8278 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -1,14 +1,21 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipelines_manual_actions.vue';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
jest.mock('~/flash');
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
+ return {
+ confirmAction: jest.fn(),
+ };
+});
describe('Pipelines Actions dropdown', () => {
let wrapper;
@@ -35,6 +42,7 @@ describe('Pipelines Actions dropdown', () => {
wrapper = null;
mock.restore();
+ confirmAction.mockReset();
});
describe('manual actions', () => {
@@ -68,7 +76,7 @@ describe('Pipelines Actions dropdown', () => {
findAllDropdownItems().at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdown().props('loading')).toBe(true);
await waitForPromises();
@@ -80,7 +88,7 @@ describe('Pipelines Actions dropdown', () => {
findAllDropdownItems().at(0).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDropdown().props('loading')).toBe(true);
await waitForPromises();
@@ -111,11 +119,11 @@ describe('Pipelines Actions dropdown', () => {
it('makes post request after confirming', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
- jest.spyOn(window, 'confirm').mockReturnValue(true);
+ confirmAction.mockResolvedValueOnce(true);
findAllDropdownItems().at(0).vm.$emit('click');
- expect(window.confirm).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
await waitForPromises();
@@ -124,11 +132,11 @@ describe('Pipelines Actions dropdown', () => {
it('does not make post request if confirmation is cancelled', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
- jest.spyOn(window, 'confirm').mockReturnValue(false);
+ confirmAction.mockResolvedValueOnce(false);
findAllDropdownItems().at(0).vm.$emit('click');
- expect(window.confirm).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
await waitForPromises();
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index 6fdbe907aed..f200d683a7a 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -9,7 +9,11 @@ import PipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_tr
import PipelineUrl from '~/pipelines/components/pipelines_list/pipeline_url.vue';
import PipelinesTable from '~/pipelines/components/pipelines_list/pipelines_table.vue';
import PipelinesTimeago from '~/pipelines/components/pipelines_list/time_ago.vue';
-import { PipelineKeyOptions } from '~/pipelines/constants';
+import {
+ PipelineKeyOptions,
+ BUTTON_TOOLTIP_RETRY,
+ BUTTON_TOOLTIP_CANCEL,
+} from '~/pipelines/constants';
import eventHub from '~/pipelines/event_hub';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
@@ -33,13 +37,18 @@ describe('Pipelines Table', () => {
return pipelines.find((p) => p.user !== null && p.commit !== null);
};
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, rearrangePipelinesTable = false) => {
wrapper = extendedWrapper(
mount(PipelinesTable, {
propsData: {
...defaultProps,
...props,
},
+ provide: {
+ glFeatures: {
+ rearrangePipelinesTable,
+ },
+ },
}),
);
};
@@ -61,6 +70,8 @@ describe('Pipelines Table', () => {
const findStagesTh = () => wrapper.findByTestId('stages-th');
const findTimeAgoTh = () => wrapper.findByTestId('timeago-th');
const findActionsTh = () => wrapper.findByTestId('actions-th');
+ const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button');
+ const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button');
beforeEach(() => {
pipeline = createMockPipeline();
@@ -71,7 +82,7 @@ describe('Pipelines Table', () => {
wrapper = null;
});
- describe('Pipelines Table', () => {
+ describe('Pipelines Table with rearrangePipelinesTable feature flag turned off', () => {
beforeEach(() => {
createComponent({ pipelines: [pipeline], viewType: 'root' });
});
@@ -187,6 +198,39 @@ describe('Pipelines Table', () => {
it('should render pipeline operations', () => {
expect(findActions().exists()).toBe(true);
});
+
+ it('should render retry action tooltip', () => {
+ expect(findRetryBtn().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
+ });
+
+ it('should render cancel action tooltip', () => {
+ expect(findCancelBtn().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL);
+ });
+ });
+ });
+
+ describe('Pipelines Table with rearrangePipelinesTable feature flag turned on', () => {
+ beforeEach(() => {
+ createComponent({ pipelines: [pipeline], viewType: 'root' }, true);
+ });
+
+ it('should render table head with correct columns', () => {
+ expect(findStatusTh().text()).toBe('Status');
+ expect(findPipelineTh().text()).toBe('Pipeline');
+ expect(findStagesTh().text()).toBe('Stages');
+ expect(findActionsTh().text()).toBe('Actions');
+ });
+
+ describe('triggerer cell', () => {
+ it('should render the pipeline triggerer', () => {
+ expect(findTriggerer().exists()).toBe(true);
+ });
+ });
+
+ describe('commit cell', () => {
+ it('should not render commit information', () => {
+ expect(findCommit().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
index c995eb864d1..4b33c1522a5 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -1,11 +1,9 @@
import { GlModal } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
-const localVue = createLocalVue();
-
describe('Test case details', () => {
let wrapper;
const defaultTestCase = {
@@ -29,7 +27,6 @@ describe('Test case details', () => {
const createComponent = (testCase = {}) => {
wrapper = extendedWrapper(
shallowMount(TestCaseDetails, {
- localVue,
propsData: {
modalId: 'my-modal',
testCase: {
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index 384b7cf6930..e0daf8cb4b5 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -9,8 +10,7 @@ import TestSummary from '~/pipelines/components/test_reports/test_summary.vue';
import TestSummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports app', () => {
let wrapper;
@@ -44,7 +44,6 @@ describe('Test reports app', () => {
wrapper = extendedWrapper(
shallowMount(TestReports, {
store,
- localVue,
}),
);
};
diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
index 793bad6b82a..97241e14129 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
@@ -8,8 +9,7 @@ import * as getters from '~/pipelines/stores/test_reports/getters';
import { formatFilePath } from '~/pipelines/stores/test_reports/utils';
import skippedTestCases from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports suite table', () => {
let wrapper;
@@ -47,7 +47,6 @@ describe('Test reports suite table', () => {
wrapper = shallowMount(SuiteTable, {
store,
- localVue,
stubs: { GlFriendlyWrap },
});
};
diff --git a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
index 0813739d72f..1598d5c337f 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
@@ -1,11 +1,11 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import testReports from 'test_fixtures/pipelines/test_report.json';
import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Test reports summary table', () => {
let wrapper;
@@ -29,7 +29,6 @@ describe('Test reports summary table', () => {
wrapper = mount(SummaryTable, {
propsData: defaultProps,
store,
- localVue,
});
};