diff options
Diffstat (limited to 'spec/frontend/ci/pipeline_details')
7 files changed, 109 insertions, 80 deletions
diff --git a/spec/frontend/ci/pipeline_details/graph/components/job_item_spec.js b/spec/frontend/ci/pipeline_details/graph/components/job_item_spec.js index 10db7f398fe..432775d469c 100644 --- a/spec/frontend/ci/pipeline_details/graph/components/job_item_spec.js +++ b/spec/frontend/ci/pipeline_details/graph/components/job_item_spec.js @@ -5,7 +5,7 @@ import JobItem from '~/ci/pipeline_details/graph/components/job_item.vue'; import axios from '~/lib/utils/axios_utils'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import ActionComponent from '~/ci/common/private/job_action_component.vue'; -import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { diff --git a/spec/frontend/ci/pipeline_details/graph/components/job_name_component_spec.js b/spec/frontend/ci/pipeline_details/graph/components/job_name_component_spec.js index 1da85ad9f78..b84ca77081a 100644 --- a/spec/frontend/ci/pipeline_details/graph/components/job_name_component_spec.js +++ b/spec/frontend/ci/pipeline_details/graph/components/job_name_component_spec.js @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; import jobNameComponent from '~/ci/common/private/job_name_component.vue'; -import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue'; describe('job name component', () => { let wrapper; diff --git a/spec/frontend/ci/pipeline_details/graph/components/linked_pipeline_spec.js b/spec/frontend/ci/pipeline_details/graph/components/linked_pipeline_spec.js index 72be51575d7..e6f89910a97 100644 --- a/spec/frontend/ci/pipeline_details/graph/components/linked_pipeline_spec.js +++ b/spec/frontend/ci/pipeline_details/graph/components/linked_pipeline_spec.js @@ -10,7 +10,7 @@ import { ACTION_FAILURE, UPSTREAM, DOWNSTREAM } from '~/ci/pipeline_details/grap import LinkedPipelineComponent from '~/ci/pipeline_details/graph/components/linked_pipeline.vue'; import CancelPipelineMutation from '~/ci/pipeline_details/graphql/mutations/cancel_pipeline.mutation.graphql'; import RetryPipelineMutation from '~/ci/pipeline_details/graphql/mutations/retry_pipeline.mutation.graphql'; -import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue'; import mockPipeline from './linked_pipelines_mock_data'; describe('Linked pipeline', () => { diff --git a/spec/frontend/ci/pipeline_details/header/pipeline_details_header_spec.js b/spec/frontend/ci/pipeline_details/header/pipeline_details_header_spec.js index e8e178ed148..86b8c416a07 100644 --- a/spec/frontend/ci/pipeline_details/header/pipeline_details_header_spec.js +++ b/spec/frontend/ci/pipeline_details/header/pipeline_details_header_spec.js @@ -7,7 +7,7 @@ import waitForPromises from 'helpers/wait_for_promises'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import PipelineDetailsHeader from '~/ci/pipeline_details/header/pipeline_details_header.vue'; import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL } from '~/ci/constants'; -import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue'; import cancelPipelineMutation from '~/ci/pipeline_details/graphql/mutations/cancel_pipeline.mutation.graphql'; import deletePipelineMutation from '~/ci/pipeline_details/graphql/mutations/delete_pipeline.mutation.graphql'; import retryPipelineMutation from '~/ci/pipeline_details/graphql/mutations/retry_pipeline.mutation.graphql'; @@ -15,6 +15,7 @@ import getPipelineDetailsQuery from '~/ci/pipeline_details/header/graphql/querie import { pipelineHeaderSuccess, pipelineHeaderRunning, + pipelineHeaderRunningNoPermissions, pipelineHeaderRunningWithDuration, pipelineHeaderFailed, pipelineRetryMutationResponseSuccess, @@ -33,6 +34,9 @@ describe('Pipeline details header', () => { const successHandler = jest.fn().mockResolvedValue(pipelineHeaderSuccess); const runningHandler = jest.fn().mockResolvedValue(pipelineHeaderRunning); + const runningHandlerNoPermissions = jest + .fn() + .mockResolvedValue(pipelineHeaderRunningNoPermissions); const runningHandlerWithDuration = jest.fn().mockResolvedValue(pipelineHeaderRunningWithDuration); const failedHandler = jest.fn().mockResolvedValue(pipelineHeaderFailed); @@ -65,7 +69,6 @@ describe('Pipeline details header', () => { const findPipelineName = () => wrapper.findByTestId('pipeline-name'); const findCommitTitle = () => wrapper.findByTestId('pipeline-commit-title'); const findTotalJobs = () => wrapper.findByTestId('total-jobs'); - const findComputeMinutes = () => wrapper.findByTestId('compute-minutes'); const findCommitLink = () => wrapper.findByTestId('commit-link'); const findPipelineRunningText = () => wrapper.findByTestId('pipeline-running-text').text(); const findPipelineRefText = () => wrapper.findByTestId('pipeline-ref-text').text(); @@ -82,31 +85,12 @@ describe('Pipeline details header', () => { paths: { pipelinesPath: '/namespace/my-project/-/pipelines', fullProject: '/namespace/my-project', - triggeredByPath: '', }, }; const defaultProps = { - name: 'Ruby 3.0 master branch pipeline', - totalJobs: '50', - computeMinutes: '0.65', - yamlErrors: 'errors', - failureReason: 'pipeline failed', - badges: { - schedule: true, - trigger: false, - child: false, - latest: true, - mergeTrainPipeline: false, - mergedResultsPipeline: false, - invalid: false, - failed: false, - autoDevops: false, - detached: false, - stuck: false, - }, - refText: - '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>', + yamlErrors: '', + trigger: false, }; const createMockApolloProvider = (handlers) => { @@ -159,11 +143,11 @@ describe('Pipeline details header', () => { }); it('displays pipeline name', () => { - expect(findPipelineName().text()).toBe(defaultProps.name); + expect(findPipelineName().text()).toBe('Build pipeline'); }); it('displays total jobs', () => { - expect(findTotalJobs().text()).toBe('50 Jobs'); + expect(findTotalJobs().text()).toBe('3 Jobs'); }); it('has link to commit', () => { @@ -178,13 +162,13 @@ describe('Pipeline details header', () => { it('displays correct badges', () => { expect(findAllBadges()).toHaveLength(2); - expect(wrapper.findByText('latest').exists()).toBe(true); + expect(wrapper.findByText('merged results').exists()).toBe(true); expect(wrapper.findByText('Scheduled').exists()).toBe(true); expect(wrapper.findByText('trigger token').exists()).toBe(false); }); it('displays ref text', () => { - expect(findPipelineRefText()).toBe('Related merge request !1 to merge test'); + expect(findPipelineRefText()).toBe('Related merge request !1 to merge master into feature'); }); it('displays pipeline user link with required user popover attributes', () => { @@ -209,7 +193,7 @@ describe('Pipeline details header', () => { beforeEach(async () => { createComponent(defaultHandlers, { ...defaultProps, - badges: { ...defaultProps.badges, trigger: true }, + trigger: true, }); await waitForPromises(); @@ -222,7 +206,7 @@ describe('Pipeline details header', () => { describe('without pipeline name', () => { it('displays commit title', async () => { - createComponent(defaultHandlers, { ...defaultProps, name: '' }); + createComponent([[getPipelineDetailsQuery, runningHandler]]); await waitForPromises(); @@ -234,22 +218,6 @@ describe('Pipeline details header', () => { }); describe('finished pipeline', () => { - it('displays compute minutes when not zero', async () => { - createComponent(); - - await waitForPromises(); - - expect(findComputeMinutes().text()).toBe('0.65'); - }); - - it('does not display compute minutes when zero', async () => { - createComponent(defaultHandlers, { ...defaultProps, computeMinutes: '0.0' }); - - await waitForPromises(); - - expect(findComputeMinutes().exists()).toBe(false); - }); - it('does not display created time ago', async () => { createComponent(); @@ -284,10 +252,6 @@ describe('Pipeline details header', () => { await waitForPromises(); }); - it('does not display compute minutes', () => { - expect(findComputeMinutes().exists()).toBe(false); - }); - it('does not display finished time ago', () => { expect(findFinishedTimeAgo().exists()).toBe(false); }); @@ -374,46 +338,58 @@ describe('Pipeline details header', () => { }); describe('cancel action', () => { - it('should call cancelPipeline Mutation with pipeline id', async () => { - createComponent([ - [getPipelineDetailsQuery, runningHandler], - [cancelPipelineMutation, cancelMutationHandlerSuccess], - ]); + describe('with permissions', () => { + it('should call cancelPipeline Mutation with pipeline id', async () => { + createComponent([ + [getPipelineDetailsQuery, runningHandler], + [cancelPipelineMutation, cancelMutationHandlerSuccess], + ]); - await waitForPromises(); + await waitForPromises(); - findCancelButton().vm.$emit('click'); + findCancelButton().vm.$emit('click'); - expect(cancelMutationHandlerSuccess).toHaveBeenCalledWith({ - id: pipelineHeaderRunning.data.project.pipeline.id, + expect(cancelMutationHandlerSuccess).toHaveBeenCalledWith({ + id: pipelineHeaderRunning.data.project.pipeline.id, + }); + expect(findAlert().exists()).toBe(false); }); - expect(findAlert().exists()).toBe(false); - }); - it('should render cancel action tooltip', async () => { - createComponent([ - [getPipelineDetailsQuery, runningHandler], - [cancelPipelineMutation, cancelMutationHandlerSuccess], - ]); + it('should render cancel action tooltip', async () => { + createComponent([ + [getPipelineDetailsQuery, runningHandler], + [cancelPipelineMutation, cancelMutationHandlerSuccess], + ]); - await waitForPromises(); + await waitForPromises(); - expect(findCancelButton().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL); - }); + expect(findCancelButton().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL); + }); - it('should display error message on failure', async () => { - createComponent([ - [getPipelineDetailsQuery, runningHandler], - [cancelPipelineMutation, cancelMutationHandlerFailed], - ]); + it('should display error message on failure', async () => { + createComponent([ + [getPipelineDetailsQuery, runningHandler], + [cancelPipelineMutation, cancelMutationHandlerFailed], + ]); - await waitForPromises(); + await waitForPromises(); - findCancelButton().vm.$emit('click'); + findCancelButton().vm.$emit('click'); - await waitForPromises(); + await waitForPromises(); - expect(findAlert().exists()).toBe(true); + expect(findAlert().exists()).toBe(true); + }); + }); + + describe('without permissions', () => { + it('should not display cancel pipeline button', async () => { + createComponent([[getPipelineDetailsQuery, runningHandlerNoPermissions]]); + + await waitForPromises(); + + expect(findCancelButton().exists()).toBe(false); + }); }); }); diff --git a/spec/frontend/ci/pipeline_details/mock_data.js b/spec/frontend/ci/pipeline_details/mock_data.js index 56365622544..48570b2515f 100644 --- a/spec/frontend/ci/pipeline_details/mock_data.js +++ b/spec/frontend/ci/pipeline_details/mock_data.js @@ -1,5 +1,7 @@ +// pipeline header fixtures located in spec/frontend/fixtures/pipeline_header.rb import pipelineHeaderSuccess from 'test_fixtures/graphql/pipelines/pipeline_header_success.json'; import pipelineHeaderRunning from 'test_fixtures/graphql/pipelines/pipeline_header_running.json'; +import pipelineHeaderRunningNoPermissions from 'test_fixtures/graphql/pipelines/pipeline_header_running_no_permissions.json'; import pipelineHeaderRunningWithDuration from 'test_fixtures/graphql/pipelines/pipeline_header_running_with_duration.json'; import pipelineHeaderFailed from 'test_fixtures/graphql/pipelines/pipeline_header_failed.json'; @@ -13,6 +15,7 @@ threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21); export { pipelineHeaderSuccess, pipelineHeaderRunning, + pipelineHeaderRunningNoPermissions, pipelineHeaderRunningWithDuration, pipelineHeaderFailed, }; diff --git a/spec/frontend/ci/pipeline_details/test_reports/stores/utils_spec.js b/spec/frontend/ci/pipeline_details/test_reports/stores/utils_spec.js index c0ffc2b34fb..ecc61ab43c0 100644 --- a/spec/frontend/ci/pipeline_details/test_reports/stores/utils_spec.js +++ b/spec/frontend/ci/pipeline_details/test_reports/stores/utils_spec.js @@ -36,5 +36,33 @@ describe('Test reports utils', () => { expect(result).toBe('4.82s'); }); }); + + describe('when time is greater than a minute', () => { + it('should return time in minutes', () => { + const result = formattedTime(99); + expect(result).toBe('1m 39s'); + }); + }); + + describe('when time is greater than a hour', () => { + it('should return time in hours', () => { + const result = formattedTime(3606); + expect(result).toBe('1h 6s'); + }); + }); + + describe('when time is exact a hour', () => { + it('should return time as one hour', () => { + const result = formattedTime(3600); + expect(result).toBe('1h'); + }); + }); + + describe('when time is greater than a hour with some minutes', () => { + it('should return time in hours', () => { + const result = formattedTime(3662); + expect(result).toBe('1h 1m 2s'); + }); + }); }); }); diff --git a/spec/frontend/ci/pipeline_details/test_reports/test_reports_spec.js b/spec/frontend/ci/pipeline_details/test_reports/test_reports_spec.js index 8ff060026da..d318aa36bcf 100644 --- a/spec/frontend/ci/pipeline_details/test_reports/test_reports_spec.js +++ b/spec/frontend/ci/pipeline_details/test_reports/test_reports_spec.js @@ -5,6 +5,7 @@ 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'; +import { getParameterValues } from '~/lib/utils/url_utility'; import EmptyState from '~/ci/pipeline_details/test_reports/empty_state.vue'; import TestReports from '~/ci/pipeline_details/test_reports/test_reports.vue'; import TestSummary from '~/ci/pipeline_details/test_reports/test_summary.vue'; @@ -13,6 +14,11 @@ import * as getters from '~/ci/pipeline_details/stores/test_reports/getters'; Vue.use(Vuex); +jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), + getParameterValues: jest.fn().mockReturnValue([]), +})); + describe('Test reports app', () => { let wrapper; let store; @@ -100,6 +106,22 @@ describe('Test reports app', () => { }); }); + describe('when a job name is provided as a query parameter', () => { + beforeEach(() => { + getParameterValues.mockReturnValue(['javascript']); + createComponent(); + }); + + it('shows tests details', () => { + expect(testsDetail().exists()).toBe(true); + }); + + it('should call setSelectedSuiteIndex and fetchTestSuite', () => { + expect(actionSpies.setSelectedSuiteIndex).toHaveBeenCalled(); + expect(actionSpies.fetchTestSuite).toHaveBeenCalled(); + }); + }); + describe('when a suite is clicked', () => { beforeEach(() => { createComponent({ state: { hasFullReport: true } }); |