text: import { GlModal, GlLoadingIcon } from '@gitlab/ui';
  import { shallowMount } from '@vue/test-utils';
  import { nextTick } from 'vue';
  import waitForPromises from 'helpers/wait_for_promises';
  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,
    mockFailedPipelineNoPermissions,
    mockRunningPipelineHeader,
    mockRunningPipelineNoPermissions,
    mockSuccessfulPipelineHeader,
  } from './mock_data';
  
  describe('Pipeline details header', () => {
    let wrapper;
    let glModalDirective;
    let mutate = jest.fn();
  
    const findDeleteModal = () => wrapper.find(GlModal);
    const findRetryButton = () => wrapper.find('[data-testid="retryPipeline"]');
    const findCancelButton = () => wrapper.find('[data-testid="cancelPipeline"]');
    const findDeleteButton = () => wrapper.find('[data-testid="deletePipeline"]');
    const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
  
    const defaultProvideOptions = {
      pipelineId: '14',
      pipelineIid: 1,
      paths: {
        pipelinesPath: '/namespace/my-project/-/pipelines',
        fullProject: '/namespace/my-project',
      },
    };
  
    const createComponent = (pipelineMock = mockRunningPipelineHeader, { isLoading } = false) => {
      glModalDirective = jest.fn();
  
      const $apollo = {
        queries: {
          pipeline: {
            loading: isLoading,
            stopPolling: jest.fn(),
            startPolling: jest.fn(),
          },
        },
        mutate,
      };
  
      return shallowMount(HeaderComponent, {
        data() {
          return {
            pipeline: pipelineMock,
          };
        },
        provide: {
          ...defaultProvideOptions,
        },
        directives: {
          glModal: {
            bind(_, { value }) {
              glModalDirective(value);
            },
          },
        },
        mocks: { $apollo },
      });
    };
  
    afterEach(() => {
      wrapper.destroy();
      wrapper = null;
    });
  
    describe('initial loading', () => {
      beforeEach(() => {
        wrapper = createComponent(null, { isLoading: true });
      });
  
      it('shows a loading state while graphQL is fetching initial data', () => {
        expect(findLoadingIcon().exists()).toBe(true);
      });
    });
  
    describe('visible state', () => {
      it.each`
        state           | pipelineData                    | retryValue | cancelValue
        ${'cancelled'}  | ${mockCancelledPipelineHeader}  | ${true}    | ${false}
        ${'failed'}     | ${mockFailedPipelineHeader}     | ${true}    | ${false}
        ${'running'}    | ${mockRunningPipelineHeader}    | ${false}   | ${true}
        ${'successful'} | ${mockSuccessfulPipelineHeader} | ${false}   | ${false}
      `(
        'with a $state pipeline, it will show actions: retry $retryValue and cancel $cancelValue',
        ({ pipelineData, retryValue, cancelValue }) => {
          wrapper = createComponent(pipelineData);
  
          expect(findRetryButton().exists()).toBe(retryValue);
          expect(findCancelButton().exists()).toBe(cancelValue);
        },
      );
    });
  
    describe('actions', () => {
      describe('Retry action', () => {
        beforeEach(() => {
          wrapper = createComponent(mockCancelledPipelineHeader);
        });
  
        it('should call retryPipeline Mutation with pipeline id', () => {
          findRetryButton().vm.$emit('click');
  
          expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
            mutation: retryPipelineMutation,
            variables: { id: mockCancelledPipelineHeader.id },
          });
        });
  
        it('should render retry action tooltip', () => {
          expect(findRetryButton().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
        });
      });
  
      describe('Retry action failed', () => {
        beforeEach(() => {
          mutate = jest.fn().mockRejectedValue('error');
  
          wrapper = createComponent(mockCancelledPipelineHeader);
        });
  
        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', () => {
        beforeEach(() => {
          wrapper = createComponent(mockRunningPipelineHeader);
        });
  
        it('should call cancelPipeline Mutation with pipeline id', () => {
          findCancelButton().vm.$emit('click');
  
          expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
            mutation: cancelPipelineMutation,
            variables: { id: mockRunningPipelineHeader.id },
          });
        });
      });
  
      describe('Delete action', () => {
        beforeEach(() => {
          wrapper = createComponent(mockFailedPipelineHeader);
        });
  
        it('displays delete modal when clicking on delete and does not call the delete action', () => {
          findDeleteButton().vm.$emit('click');
  
          expect(findDeleteModal().props('modalId')).toBe(wrapper.vm.$options.DELETE_MODAL_ID);
          expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.$options.DELETE_MODAL_ID);
          expect(wrapper.vm.$apollo.mutate).not.toHaveBeenCalled();
        });
  
        it('should call deletePipeline Mutation with pipeline id when modal is submitted', () => {
          findDeleteModal().vm.$emit('ok');
  
          expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
            mutation: deletePipelineMutation,
            variables: { id: mockFailedPipelineHeader.id },
          });
        });
      });
  
      describe('Permissions', () => {
        it('should not display the cancel action if user does not have permission', () => {
          wrapper = createComponent(mockRunningPipelineNoPermissions);
  
          expect(findCancelButton().exists()).toBe(false);
        });
  
        it('should not display the retry action if user does not have permission', () => {
          wrapper = createComponent(mockFailedPipelineNoPermissions);
  
          expect(findRetryButton().exists()).toBe(false);
        });
      });
    });
  });
  