Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pipelines/pipeline_details_header_spec.js')
-rw-r--r--spec/frontend/pipelines/pipeline_details_header_spec.js210
1 files changed, 205 insertions, 5 deletions
diff --git a/spec/frontend/pipelines/pipeline_details_header_spec.js b/spec/frontend/pipelines/pipeline_details_header_spec.js
index 08ae35fe808..7141e10fb17 100644
--- a/spec/frontend/pipelines/pipeline_details_header_spec.js
+++ b/spec/frontend/pipelines/pipeline_details_header_spec.js
@@ -1,23 +1,59 @@
-import { GlBadge, GlLoadingIcon } from '@gitlab/ui';
-import Vue from 'vue';
+import { GlAlert, GlBadge, GlLoadingIcon, GlModal } from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PipelineDetailsHeader from '~/pipelines/components/pipeline_details_header.vue';
+import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL } from '~/pipelines/constants';
import TimeAgo from '~/pipelines/components/pipelines_list/time_ago.vue';
import CiBadgeLink from '~/vue_shared/components/ci_badge_link.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 getPipelineDetailsQuery from '~/pipelines/graphql/queries/get_pipeline_header_data.query.graphql';
-import { pipelineHeaderSuccess, pipelineHeaderRunning } from './mock_data';
+import {
+ pipelineHeaderSuccess,
+ pipelineHeaderRunning,
+ pipelineHeaderFailed,
+ pipelineRetryMutationResponseSuccess,
+ pipelineCancelMutationResponseSuccess,
+ pipelineDeleteMutationResponseSuccess,
+ pipelineRetryMutationResponseFailed,
+ pipelineCancelMutationResponseFailed,
+ pipelineDeleteMutationResponseFailed,
+} from './mock_data';
Vue.use(VueApollo);
describe('Pipeline details header', () => {
let wrapper;
+ let glModalDirective;
const successHandler = jest.fn().mockResolvedValue(pipelineHeaderSuccess);
const runningHandler = jest.fn().mockResolvedValue(pipelineHeaderRunning);
+ const failedHandler = jest.fn().mockResolvedValue(pipelineHeaderFailed);
+ const retryMutationHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(pipelineRetryMutationResponseSuccess);
+ const cancelMutationHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(pipelineCancelMutationResponseSuccess);
+ const deleteMutationHandlerSuccess = jest
+ .fn()
+ .mockResolvedValue(pipelineDeleteMutationResponseSuccess);
+ const retryMutationHandlerFailed = jest
+ .fn()
+ .mockResolvedValue(pipelineRetryMutationResponseFailed);
+ const cancelMutationHandlerFailed = jest
+ .fn()
+ .mockResolvedValue(pipelineCancelMutationResponseFailed);
+ const deleteMutationHandlerFailed = jest
+ .fn()
+ .mockResolvedValue(pipelineDeleteMutationResponseFailed);
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
const findStatus = () => wrapper.findComponent(CiBadgeLink);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findTimeAgo = () => wrapper.findComponent(TimeAgo);
@@ -28,6 +64,10 @@ describe('Pipeline details header', () => {
const findCommitLink = () => wrapper.findByTestId('commit-link');
const findPipelineRunningText = () => wrapper.findByTestId('pipeline-running-text').text();
const findPipelineRefText = () => wrapper.findByTestId('pipeline-ref-text').text();
+ const findRetryButton = () => wrapper.findByTestId('retry-pipeline');
+ const findCancelButton = () => wrapper.findByTestId('cancel-pipeline');
+ const findDeleteButton = () => wrapper.findByTestId('delete-pipeline');
+ const findDeleteModal = () => wrapper.findComponent(GlModal);
const defaultHandlers = [[getPipelineDetailsQuery, successHandler]];
@@ -58,7 +98,7 @@ describe('Pipeline details header', () => {
stuck: false,
},
refText:
- 'For merge request <a class="mr-iid" href="/root/ci-project/-/merge_requests/1">!1</a> to merge <a class="ref-name" href="/root/ci-project/-/commits/test">test</a>',
+ 'Related merge request <a class="mr-iid" href="/root/ci-project/-/merge_requests/1">!1</a> to merge <a class="ref-name" href="/root/ci-project/-/commits/test">test</a>',
};
const createMockApolloProvider = (handlers) => {
@@ -66,6 +106,8 @@ describe('Pipeline details header', () => {
};
const createComponent = (handlers = defaultHandlers, props = defaultProps) => {
+ glModalDirective = jest.fn();
+
wrapper = shallowMountExtended(PipelineDetailsHeader, {
provide: {
...defaultProvideOptions,
@@ -73,6 +115,13 @@ describe('Pipeline details header', () => {
propsData: {
...props,
},
+ directives: {
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
+ },
apolloProvider: createMockApolloProvider(handlers),
});
};
@@ -125,7 +174,7 @@ describe('Pipeline details header', () => {
});
it('displays ref text', () => {
- expect(findPipelineRefText()).toBe('For merge request !1 to merge test');
+ expect(findPipelineRefText()).toBe('Related merge request !1 to merge test');
});
});
@@ -164,4 +213,155 @@ describe('Pipeline details header', () => {
expect(findPipelineRunningText()).toBe('In progress, queued for 3600 seconds');
});
});
+
+ describe('actions', () => {
+ describe('retry action', () => {
+ beforeEach(async () => {
+ createComponent([
+ [getPipelineDetailsQuery, failedHandler],
+ [retryPipelineMutation, retryMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+ });
+
+ it('should call retryPipeline Mutation with pipeline id', () => {
+ findRetryButton().vm.$emit('click');
+
+ expect(retryMutationHandlerSuccess).toHaveBeenCalledWith({
+ id: pipelineHeaderFailed.data.project.pipeline.id,
+ });
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should render retry action tooltip', () => {
+ expect(findRetryButton().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
+ });
+ });
+
+ describe('retry action failed', () => {
+ beforeEach(async () => {
+ createComponent([
+ [getPipelineDetailsQuery, failedHandler],
+ [retryPipelineMutation, retryMutationHandlerFailed],
+ ]);
+
+ await waitForPromises();
+ });
+
+ it('should display error message on failure', async () => {
+ findRetryButton().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('retry button loading state should reset on error', async () => {
+ findRetryButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(findRetryButton().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findRetryButton().props('loading')).toBe(false);
+ });
+ });
+
+ describe('cancel action', () => {
+ it('should call cancelPipeline Mutation with pipeline id', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, runningHandler],
+ [cancelPipelineMutation, cancelMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+
+ findCancelButton().vm.$emit('click');
+
+ expect(cancelMutationHandlerSuccess).toHaveBeenCalledWith({
+ id: pipelineHeaderRunning.data.project.pipeline.id,
+ });
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should render cancel action tooltip', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, runningHandler],
+ [cancelPipelineMutation, cancelMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+
+ expect(findCancelButton().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL);
+ });
+
+ it('should display error message on failure', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, runningHandler],
+ [cancelPipelineMutation, cancelMutationHandlerFailed],
+ ]);
+
+ await waitForPromises();
+
+ findCancelButton().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
+ describe('delete action', () => {
+ it('displays delete modal when clicking on delete and does not call the delete action', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, successHandler],
+ [deletePipelineMutation, deleteMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+
+ findDeleteButton().vm.$emit('click');
+
+ const modalId = 'pipeline-delete-modal';
+
+ expect(findDeleteModal().props('modalId')).toBe(modalId);
+ expect(glModalDirective).toHaveBeenCalledWith(modalId);
+ expect(deleteMutationHandlerSuccess).not.toHaveBeenCalled();
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should call deletePipeline Mutation with pipeline id when modal is submitted', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, successHandler],
+ [deletePipelineMutation, deleteMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+
+ findDeleteModal().vm.$emit('primary');
+
+ expect(deleteMutationHandlerSuccess).toHaveBeenCalledWith({
+ id: pipelineHeaderSuccess.data.project.pipeline.id,
+ });
+ });
+
+ it('should display error message on failure', async () => {
+ createComponent([
+ [getPipelineDetailsQuery, successHandler],
+ [deletePipelineMutation, deleteMutationHandlerFailed],
+ ]);
+
+ await waitForPromises();
+
+ findDeleteModal().vm.$emit('primary');
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+ });
});