diff --git a/app/assets/javascripts/pipelines/components/dag/dag.vue b/app/assets/javascripts/pipelines/components/dag/dag.vue index 475dd3bf36ee5d8a844ccde101a570bc2e3e3262..be12df68f762cec16fe0540b55f7a2cf801319ad 100644 --- a/app/assets/javascripts/pipelines/components/dag/dag.vue +++ b/app/assets/javascripts/pipelines/components/dag/dag.vue @@ -29,7 +29,7 @@ export default { dagDocPath: { default: null, }, - emptySvgPath: { + emptyDagSvgPath: { default: '', }, pipelineIid: { @@ -213,7 +213,7 @@ export default { /> diff --git a/ee/app/assets/javascripts/pipelines/pipeline_tabs.js b/ee/app/assets/javascripts/pipelines/pipeline_tabs.js index e0a886834cab5380feb25fb6befe2ef817859309..fca1459413ae345b7b6a7382dd9b72dbfd475f39 100644 --- a/ee/app/assets/javascripts/pipelines/pipeline_tabs.js +++ b/ee/app/assets/javascripts/pipelines/pipeline_tabs.js @@ -9,12 +9,12 @@ import { __ } from '~/locale'; Vue.use(VueRouter); -export const createAppOptions = (selector, apolloProvider) => { +export const createAppOptions = (selector, apolloProvider, router) => { const el = document.querySelector(selector); if (!el) return null; - const appOptionsCE = createAppOptionsCE(selector, apolloProvider); + const appOptionsCE = createAppOptionsCE(selector, apolloProvider, router); const { dataset } = el; @@ -33,7 +33,6 @@ export const createAppOptions = (selector, apolloProvider) => { } return merge({}, appOptionsCE, { - router: new VueRouter(), provide: vulnerabilityReportProvides, }); }; diff --git a/ee/app/assets/javascripts/pipelines/routes.js b/ee/app/assets/javascripts/pipelines/routes.js new file mode 100644 index 0000000000000000000000000000000000000000..e0641a73200f2d2121f7690e2a997c7c275b7bae --- /dev/null +++ b/ee/app/assets/javascripts/pipelines/routes.js @@ -0,0 +1,12 @@ +import LicenseReportApp from 'ee/vue_shared/license_compliance/mr_widget_license_report.vue'; +import CodequalityReportAppWrapper from 'ee/pipelines/components/codequality_report_app_wrapper.vue'; +import { codeQualityTabName, licensesTabName, securityTabName } from '~/pipelines/constants'; +import { routes as ceRoutes } from '~/pipelines/routes'; +import PipelineSecurityDashboard from 'ee/security_dashboard/components/pipeline/pipeline_security_dashboard.vue'; + +export const routes = [ + ...ceRoutes, + { name: securityTabName, path: '/security', component: PipelineSecurityDashboard }, + { name: licensesTabName, path: '/licenses', component: LicenseReportApp }, + { name: codeQualityTabName, path: '/codequality_report', component: CodequalityReportAppWrapper }, +]; diff --git a/ee/app/controllers/ee/projects/pipelines_controller.rb b/ee/app/controllers/ee/projects/pipelines_controller.rb index 1a0ec1c74ce1ff3376380cfe3ec2a48e1aa4e875..19d2d713accf8009d9f7af518208217fe4c5ca60 100644 --- a/ee/app/controllers/ee/projects/pipelines_controller.rb +++ b/ee/app/controllers/ee/projects/pipelines_controller.rb @@ -23,11 +23,7 @@ module PipelinesController def security if pipeline.expose_security_dashboard? - if ::Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(pipeline, tab: 'security') - else - render_show - end + render_show else redirect_to pipeline_path(pipeline) end @@ -39,11 +35,7 @@ def licenses respond_to do |format| format.html do - if ::Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(pipeline, tab: 'licenses') - else - render_show - end + render_show end format.json do render status: :ok, json: LicenseScanningReportsSerializer.new.represent( @@ -54,11 +46,7 @@ def licenses end def codequality_report - if ::Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(pipeline, tab: 'codequality_report') - else - render_show - end + render_show end private diff --git a/ee/spec/controllers/projects/pipelines_controller_spec.rb b/ee/spec/controllers/projects/pipelines_controller_spec.rb index 9d5089ef24059d3eb8e9d6b846bf7200efacb29a..12db99cf75655b3c6b58f62772907dc8cbdab3d6 100644 --- a/ee/spec/controllers/projects/pipelines_controller_spec.rb +++ b/ee/spec/controllers/projects/pipelines_controller_spec.rb @@ -26,8 +26,9 @@ get :security, params: { namespace_id: project.namespace, project_id: project, id: pipeline } end - it 'redirects to the pipeline page with the security tab query param' do - expect(response).to redirect_to(pipeline_path(pipeline, tab: 'security')) + it 'responds with a 200 and show the template' do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end @@ -36,7 +37,7 @@ get :security, params: { namespace_id: project.namespace, project_id: project, id: pipeline } end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end @@ -50,7 +51,7 @@ get :security, params: { namespace_id: project.namespace, project_id: project, id: pipeline } end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end @@ -60,7 +61,7 @@ get :security, params: { namespace_id: project.namespace, project_id: project, id: pipeline } end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end @@ -70,10 +71,11 @@ describe 'GET codequality_report' do let(:pipeline) { create(:ci_pipeline, project: project) } - it 'redirects to pipeline path with dag tab query param' do + it 'renders the show template' do get :codequality_report, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline, tab: 'codequality_report')) + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end @@ -97,8 +99,9 @@ licenses_with_html end - it 'redirects to the pipeline page with the licenses tab query param' do - expect(response).to redirect_to(pipeline_path(pipeline, tab: 'licenses')) + it 'responds with a 200 and show the template' do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end @@ -164,7 +167,7 @@ licenses_with_html end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end @@ -187,7 +190,7 @@ licenses_with_html end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end @@ -208,7 +211,7 @@ licenses_with_html end - it do + it 'redirects to the pipeline page' do expect(response).to redirect_to(pipeline_path(pipeline)) end end diff --git a/ee/spec/frontend/pipelines/components/codequality_report_app_wrapper_spec.js b/ee/spec/frontend/pipelines/components/codequality_report_app_wrapper_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a2c4a315bf8f4bcec59ac1a6132e645b21c92a05 --- /dev/null +++ b/ee/spec/frontend/pipelines/components/codequality_report_app_wrapper_spec.js @@ -0,0 +1,52 @@ +import { shallowMount } from '@vue/test-utils'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import CodequalityReportApp from 'ee/codequality_report/codequality_report.vue'; +import CodequalityReportAppGraphql from 'ee/codequality_report/codequality_report_graphql.vue'; +import CodequalityReportAppWrapper from 'ee/pipelines/components/codequality_report_app_wrapper.vue'; + +describe('Codequality report app wrapper', () => { + let wrapper; + + const findCodeQualityApp = () => wrapper.findComponent(CodequalityReportApp); + const findCodeQualityAppGraphql = () => wrapper.findComponent(CodequalityReportAppGraphql); + + const defaultProvide = { + codequalityProjectPath: '', + codequalityBlobPath: '', + codequalityReportDownloadPath: '', + pipelineIid: '0', + }; + + const createComponent = ({ provide = {} } = {}) => { + wrapper = extendedWrapper( + shallowMount(CodequalityReportAppWrapper, { + provide: { + ...defaultProvide, + ...provide, + }, + }), + ); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it.each` + ffEnabled + ${true} + ${false} + `('Show the correct code quality app When graphQL ff is $ffEnabled', ({ ffEnabled }) => { + createComponent({ + provide: { + canGenerateCodequalityReports: true, + glFeatures: { + graphqlCodeQualityFullReport: ffEnabled, + }, + }, + }); + + expect(findCodeQualityAppGraphql().exists()).toBe(ffEnabled); + expect(findCodeQualityApp().exists()).toBe(!ffEnabled); + }); +}); diff --git a/ee/spec/frontend/pipelines/components/pipeline_tabs_spec.js b/ee/spec/frontend/pipelines/components/pipeline_tabs_spec.js index 04cfdb72587cf4d256c2941a0dac663b313af788..f1de6fdcc97169de12087fddb8469af71f41da9c 100644 --- a/ee/spec/frontend/pipelines/components/pipeline_tabs_spec.js +++ b/ee/spec/frontend/pipelines/components/pipeline_tabs_spec.js @@ -4,10 +4,7 @@ import { shallowMount } from '@vue/test-utils'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import BasePipelineTabs from '~/pipelines/components/pipeline_tabs.vue'; import PipelineTabs from 'ee/pipelines/components/pipeline_tabs.vue'; -import CodequalityReportApp from 'ee/codequality_report/codequality_report.vue'; -import CodequalityReportAppGraphql from 'ee/codequality_report/codequality_report_graphql.vue'; -import LicenseReportApp from 'ee/vue_shared/license_compliance/mr_widget_license_report.vue'; -import PipelineSecurityDashboard from 'ee/security_dashboard/components/pipeline/pipeline_security_dashboard.vue'; +import CodequalityReportAppWrapper from 'ee/pipelines/components/codequality_report_app_wrapper.vue'; describe('The Pipeline Tabs', () => { let wrapper; @@ -20,31 +17,25 @@ describe('The Pipeline Tabs', () => { const findPipelineTab = () => wrapper.findByTestId('pipeline-tab'); const findSecurityTab = () => wrapper.findByTestId('security-tab'); const findTestsTab = () => wrapper.findByTestId('tests-tab'); - - const findCodeQualityApp = () => wrapper.findComponent(CodequalityReportApp); - const findCodeQualityAppGraphql = () => wrapper.findComponent(CodequalityReportAppGraphql); - const findLicenseApp = () => wrapper.findComponent(LicenseReportApp); - const findSecurityApp = () => wrapper.findComponent(PipelineSecurityDashboard); - const getLicenseCount = () => wrapper.findByTestId('license-counter').text(); const getCodequalityCount = () => wrapper.findByTestId('codequality-counter').text(); + const findCodeQualityRouterView = () => wrapper.findComponent({ ref: 'router-view-codequality' }); + const findLicensesRouterView = () => wrapper.findComponent({ ref: 'router-view-licenses' }); const defaultProvide = { canGenerateCodequalityReports: false, + canManageLicenses: true, codequalityReportDownloadPath: '', - codequalityProjectPath: '', - codequalityBlobPath: '', - pipelineIid: '0', defaultTabValue: '', exposeSecurityDashboard: false, exposeLicenseScanningData: false, + failedJobsCount: 1, + failedJobsSummary: [], isFullCodequalityReportAvailable: true, licenseManagementApiUrl: '/path/to/license_management_api_url', licensesApiPath: '/path/to/licenses_api', licenseManagementSettingsPath: '/path/to/license_management_settings', - canManageLicenses: true, - failedJobsCount: 1, - failedJobsSummary: [], + pipelineIid: '100', totalJobCount: 10, testsCount: 123, }; @@ -59,7 +50,7 @@ describe('The Pipeline Tabs', () => { }, stubs: { BasePipelineTabs, - TestReports: { template: '
' }, + RouterView: true, ...stubs, }, }), @@ -100,136 +91,94 @@ describe('The Pipeline Tabs', () => { describe('EE Tabs', () => { describe('visibility', () => { it.each` - tabName | tabComponent | appComponent | provideKey | isVisible | text - ${'Security'} | ${findSecurityTab} | ${findSecurityApp} | ${'exposeSecurityDashboard'} | ${true} | ${'shows'} - ${'Security'} | ${findSecurityTab} | ${findSecurityApp} | ${'exposeSecurityDashboard'} | ${false} | ${'hides'} - ${'License'} | ${findLicenseTab} | ${findLicenseApp} | ${'exposeLicenseScanningData'} | ${true} | ${'shows'} - ${'License'} | ${findLicenseTab} | ${findLicenseApp} | ${'exposeLicenseScanningData'} | ${false} | ${'hides'} + tabName | tabComponent | provideKey | isVisible | text + ${'Security'} | ${findSecurityTab} | ${'exposeSecurityDashboard'} | ${true} | ${'shows'} + ${'Security'} | ${findSecurityTab} | ${'exposeSecurityDashboard'} | ${false} | ${'hides'} + ${'License'} | ${findLicenseTab} | ${'exposeLicenseScanningData'} | ${true} | ${'shows'} + ${'License'} | ${findLicenseTab} | ${'exposeLicenseScanningData'} | ${false} | ${'hides'} `( - '$text $tabName and its associated component when $provideKey is $provideKey', - ({ tabComponent, appComponent, provideKey, isVisible }) => { + '$text $tabName tab when $provideKey is $provideKey', + ({ tabComponent, provideKey, isVisible }) => { createComponent({ provide: { [provideKey]: isVisible }, }); expect(tabComponent().exists()).toBe(isVisible); - expect(appComponent().exists()).toBe(isVisible); }, ); }); - describe('code quality visibility', () => { - describe('feature flags', () => { - describe('with `graphqlCodeQualityFullReport` enabled', () => { - beforeEach(() => { - createComponent({ - provide: { - canGenerateCodequalityReports: true, - glFeatures: { - graphqlCodeQualityFullReport: true, - }, - }, - stubs: { GlTab }, - }); - }); - - it('shows the graphql code quality report app', () => { - expect(findCodeQualityAppGraphql().exists()).toBe(true); - expect(findCodeQualityApp().exists()).toBe(false); - }); - - it('updates the codequality badge after a new count has been emitted', async () => { - const newLicenseCount = 100; - expect(getCodequalityCount()).toBe('0'); - - findCodeQualityAppGraphql().vm.$emit('updateBadgeCount', newLicenseCount); - await nextTick(); - - expect(getCodequalityCount()).toBe(`${newLicenseCount}`); - }); + it.each` + canGenerate | isVisible | codequalityReportDownloadPath | isReportAvailable | text + ${true} | ${true} | ${''} | ${true} | ${'shows'} + ${false} | ${false} | ${''} | ${true} | ${'hides'} + ${false} | ${true} | ${'/path'} | ${true} | ${'shows'} + ${true} | ${true} | ${'/path'} | ${true} | ${'shows'} + ${true} | ${false} | ${'/path'} | ${false} | ${'hides'} + `( + '$text Code Quality tab when canGenerateCodequalityReports is $canGenerate and codequalityReportDownloadPath is $codequalityReportDownloadPath', + ({ canGenerate, isReportAvailable, isVisible, codequalityReportDownloadPath }) => { + createComponent({ + provide: { + isFullCodequalityReportAvailable: isReportAvailable, + canGenerateCodequalityReports: canGenerate, + codequalityReportDownloadPath, + }, }); + expect(findCodeQualityTab().exists()).toBe(isVisible); + }, + ); + }); - describe('with `graphqlCodeQualityFullReport` disabled', () => { - beforeEach(() => { - createComponent({ - provide: { - canGenerateCodequalityReports: true, - glFeatures: { - graphqlCodeQualityFullReport: false, - }, - }, - stubs: { GlTab }, - }); - }); - - it('shows the default code quality report app', () => { - expect(findCodeQualityAppGraphql().exists()).toBe(false); - expect(findCodeQualityApp().exists()).toBe(true); - }); - - it('updates the codequality badge after a new count has been emitted', async () => { - const newLicenseCount = 100; - - expect(getCodequalityCount()).toBe('0'); + describe('codequality badge count', () => { + beforeEach(() => { + createComponent({ + provide: { + isFullCodequalityReportAvailable: true, + canGenerateCodequalityReports: true, + codequalityReportDownloadPath: '/dsda', + }, + stubs: { GlTab, CodequalityReportAppWrapper }, + }); + }); - findCodeQualityApp().vm.$emit('updateBadgeCount', newLicenseCount); - await nextTick(); + it('updates the codequality badge after a new count has been emitted', async () => { + const newLicenseCount = 100; + expect(getCodequalityCount()).toBe('0'); - expect(getCodequalityCount()).toBe(`${newLicenseCount}`); - }); - }); - }); + findCodeQualityRouterView().vm.$emit('updateBadgeCount', newLicenseCount); + await nextTick(); - it.each` - provideValue | isVisible | codequalityReportDownloadPath | isReportAvailable | text - ${true} | ${true} | ${''} | ${true} | ${'shows'} - ${false} | ${false} | ${''} | ${true} | ${'hides'} - ${false} | ${true} | ${'/path'} | ${true} | ${'shows'} - ${true} | ${true} | ${'/path'} | ${true} | ${'shows'} - ${true} | ${false} | ${'/path'} | ${false} | ${'hides'} - `( - '$text Code Quality and its associated component when canGenerateCodequalityReports is $provideValue and codequalityReportDownloadPath is $codequalityReportDownloadPath', - ({ provideValue, isReportAvailable, isVisible, codequalityReportDownloadPath }) => { - createComponent({ - provide: { - isFullCodequalityReportAvailable: isReportAvailable, - canGenerateCodequalityReports: provideValue, - codequalityReportDownloadPath, - }, - }); - expect(findCodeQualityTab().exists()).toBe(isVisible); - expect(findCodeQualityApp().exists()).toBe(isVisible); - }, - ); + expect(getCodequalityCount()).toBe(`${newLicenseCount}`); }); + }); - describe('license compliance', () => { - beforeEach(() => { - createComponent({ - provide: { exposeLicenseScanningData: true }, - stubs: { GlTab }, - }); + describe('license compliance', () => { + beforeEach(() => { + createComponent({ + provide: { exposeLicenseScanningData: true }, + stubs: { GlTab }, }); + }); - it('passes the correct props to the license report app', () => { - expect(findLicenseApp().props()).toMatchObject({ - apiUrl: defaultProvide.licenseManagementApiUrl, - licensesApiPath: defaultProvide.licensesApiPath, - licenseManagementSettingsPath: defaultProvide.licenseManagementSettingsPath, - canManageLicenses: defaultProvide.canManageLicenses, - alwaysOpen: true, - }); + it('passes down all props to the license app', () => { + expect(findLicensesRouterView().attributes()).toMatchObject({ + 'api-url': defaultProvide.licenseManagementApiUrl, + 'licenses-api-path': defaultProvide.licensesApiPath, + 'license-management-settings-path': defaultProvide.licenseManagementSettingsPath, + 'can-manage-licenses': defaultProvide.canManageLicenses.toString(), + 'always-open': 'true', }); + }); - it('updates the license count badge after a new count has been emitted', async () => { - const newLicenseCount = 100; + it('updates the license count badge after a new count has been emitted', async () => { + const newLicenseCount = 100; - expect(getLicenseCount()).toBe('0'); + expect(getLicenseCount()).toBe('0'); - findLicenseApp().vm.$emit('updateBadgeCount', newLicenseCount); - await nextTick(); + findLicensesRouterView().vm.$emit('updateBadgeCount', newLicenseCount); + await nextTick(); - expect(getLicenseCount()).toBe(`${newLicenseCount}`); - }); + expect(getLicenseCount()).toBe(`${newLicenseCount}`); }); }); }); diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index b132c0b5a692c1705f0757982045f860178af4a6..527cba9e618939562850ffe00df29ad2f4f2cbc9 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -20,23 +20,11 @@ end shared_examples 'the show page' do |param| - it 'redirects to pipeline path with param' do + it 'renders the show template' do get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline, tab: param)) - end - - context 'when the FF pipeline_tabs_vue is disabled' do - before do - stub_feature_flags(pipeline_tabs_vue: false) - end - - it 'renders the show template' do - get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template :show - end + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end @@ -710,37 +698,25 @@ def create_build(stage, stage_idx, name, params = {}) describe 'GET failures' do let(:pipeline) { create(:ci_pipeline, project: project) } - context 'with ff `pipeline_tabs_vue` disabled' do + context 'with failed jobs' do before do - stub_feature_flags(pipeline_tabs_vue: false) - end - - context 'with failed jobs' do - before do - create(:ci_build, :failed, pipeline: pipeline, name: 'hello') - end - - it 'shows the page' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template :show - end + create(:ci_build, :failed, pipeline: pipeline, name: 'hello') end - context 'without failed jobs' do - it 'redirects to the main pipeline page' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + it 'shows the page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline)) - end + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end - it 'redirects to the pipeline page with `failures` query param' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + context 'without failed jobs' do + it 'redirects to the main pipeline page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline, tab: 'failures')) + expect(response).to redirect_to(pipeline_path(pipeline)) + end end end diff --git a/spec/frontend/pipelines/components/pipeline_tabs_spec.js b/spec/frontend/pipelines/components/pipeline_tabs_spec.js index 3680d9d62c703f04b9c90259dc656fcd8597827e..c2cb95d4320ecf84ec701a125e2059649916bd13 100644 --- a/spec/frontend/pipelines/components/pipeline_tabs_spec.js +++ b/spec/frontend/pipelines/components/pipeline_tabs_spec.js @@ -2,10 +2,6 @@ import { shallowMount } from '@vue/test-utils'; import { GlTab } from '@gitlab/ui'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import PipelineTabs from '~/pipelines/components/pipeline_tabs.vue'; -import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue'; -import Dag from '~/pipelines/components/dag/dag.vue'; -import JobsApp from '~/pipelines/components/jobs/jobs_app.vue'; -import TestReports from '~/pipelines/components/test_reports/test_reports.vue'; describe('The Pipeline Tabs', () => { let wrapper; @@ -16,12 +12,6 @@ describe('The Pipeline Tabs', () => { const findPipelineTab = () => wrapper.findByTestId('pipeline-tab'); const findTestsTab = () => wrapper.findByTestId('tests-tab'); - const findDagApp = () => wrapper.findComponent(Dag); - const findFailedJobsApp = () => wrapper.findComponent(JobsApp); - const findJobsApp = () => wrapper.findComponent(JobsApp); - const findPipelineApp = () => wrapper.findComponent(PipelineGraphWrapper); - const findTestsApp = () => wrapper.findComponent(TestReports); - const findFailedJobsBadge = () => wrapper.findByTestId('failed-builds-counter'); const findJobsBadge = () => wrapper.findByTestId('builds-counter'); const findTestsBadge = () => wrapper.findByTestId('tests-counter'); @@ -43,6 +33,7 @@ describe('The Pipeline Tabs', () => { }, stubs: { GlTab, + RouterView: true, }, }), ); @@ -54,17 +45,16 @@ describe('The Pipeline Tabs', () => { describe('Tabs', () => { it.each` - tabName | tabComponent | appComponent - ${'Pipeline'} | ${findPipelineTab} | ${findPipelineApp} - ${'Dag'} | ${findDagTab} | ${findDagApp} - ${'Jobs'} | ${findJobsTab} | ${findJobsApp} - ${'Failed Jobs'} | ${findFailedJobsTab} | ${findFailedJobsApp} - ${'Tests'} | ${findTestsTab} | ${findTestsApp} - `('shows $tabName tab with its associated component', ({ appComponent, tabComponent }) => { + tabName | tabComponent + ${'Pipeline'} | ${findPipelineTab} + ${'Dag'} | ${findDagTab} + ${'Jobs'} | ${findJobsTab} + ${'Failed Jobs'} | ${findFailedJobsTab} + ${'Tests'} | ${findTestsTab} + `('shows $tabName tab', ({ tabComponent }) => { createComponent(); expect(tabComponent().exists()).toBe(true); - expect(appComponent().exists()).toBe(true); }); describe('with no failed jobs', () => { diff --git a/spec/frontend/pipelines/pipeline_graph/utils_spec.js b/spec/frontend/pipelines/pipeline_graph/utils_spec.js index d6b13da3c3a5b87f9bce1b165b3b0c1d8fee64e3..41b020189d07de5e29b882582db05c92436adefd 100644 --- a/spec/frontend/pipelines/pipeline_graph/utils_spec.js +++ b/spec/frontend/pipelines/pipeline_graph/utils_spec.js @@ -1,5 +1,5 @@ import { createJobsHash, generateJobNeedsDict, getPipelineDefaultTab } from '~/pipelines/utils'; -import { TAB_QUERY_PARAM, validPipelineTabNames } from '~/pipelines/constants'; +import { validPipelineTabNames } from '~/pipelines/constants'; describe('utils functions', () => { const jobName1 = 'build_1'; @@ -173,18 +173,25 @@ describe('utils functions', () => { describe('getPipelineDefaultTab', () => { const baseUrl = 'http://gitlab.com/user/multi-projects-small/-/pipelines/332/'; - it('returns null if there was no `tab` params', () => { + it('returns null if there is only the base url', () => { expect(getPipelineDefaultTab(baseUrl)).toBe(null); }); - it('returns null if there was no valid tab param', () => { - expect(getPipelineDefaultTab(`${baseUrl}?${TAB_QUERY_PARAM}=invalid`)).toBe(null); + it('returns null if there was no valid last url part', () => { + expect(getPipelineDefaultTab(`${baseUrl}something`)).toBe(null); }); it('returns the correct tab name if present', () => { validPipelineTabNames.forEach((tabName) => { - expect(getPipelineDefaultTab(`${baseUrl}?${TAB_QUERY_PARAM}=${tabName}`)).toBe(tabName); + expect(getPipelineDefaultTab(`${baseUrl}${tabName}`)).toBe(tabName); }); }); + + it('returns the right value even with query params', () => { + const [tabName] = validPipelineTabNames; + expect(getPipelineDefaultTab(`${baseUrl}${tabName}?query="something"&query2="else"`)).toBe( + tabName, + ); + }); }); }); diff --git a/spec/frontend/pipelines/pipeline_tabs_spec.js b/spec/frontend/pipelines/pipeline_tabs_spec.js index b184ce31d20dd70962ffc3efb580b4c8c84a861e..099748a5ccacd6c6680789c8166f387d72cf5c6a 100644 --- a/spec/frontend/pipelines/pipeline_tabs_spec.js +++ b/spec/frontend/pipelines/pipeline_tabs_spec.js @@ -1,9 +1,7 @@ -import { createAppOptions, createPipelineTabs } from '~/pipelines/pipeline_tabs'; -import { updateHistory } from '~/lib/utils/url_utility'; +import { createAppOptions } from '~/pipelines/pipeline_tabs'; jest.mock('~/lib/utils/url_utility', () => ({ removeParams: () => 'gitlab.com', - updateHistory: jest.fn(), joinPaths: () => {}, setUrlFragment: () => {}, })); @@ -64,32 +62,4 @@ describe('~/pipelines/pipeline_tabs.js', () => { expect(createAppOptions('foo', null)).toBe(null); }); }); - - describe('createPipelineTabs', () => { - const title = 'Pipeline Tabs'; - - beforeAll(() => { - document.title = title; - }); - - afterAll(() => { - document.title = ''; - }); - - it('calls `updateHistory` with correct params', () => { - createPipelineTabs({}); - - expect(updateHistory).toHaveBeenCalledWith({ - title, - url: 'gitlab.com', - replace: true, - }); - }); - - it("returns early if options aren't provided", () => { - createPipelineTabs(); - - expect(updateHistory).not.toHaveBeenCalled(); - }); - }); }); diff --git a/spec/helpers/projects/pipeline_helper_spec.rb b/spec/helpers/projects/pipeline_helper_spec.rb index a70544ace1a01b7c8f81934accefca43feebc177..0d3466d6ed2757a63fe44c169566c03f70463e50 100644 --- a/spec/helpers/projects/pipeline_helper_spec.rb +++ b/spec/helpers/projects/pipeline_helper_spec.rb @@ -31,6 +31,7 @@ suite_endpoint: project_pipeline_test_path(project, pipeline, suite_name: 'suite', format: :json), blob_path: project_blob_path(project, pipeline.sha), has_test_report: pipeline.complete_and_has_reports?(Ci::JobArtifact.of_report_type(:test)), + empty_dag_svg_path: match_asset_path('illustrations/empty-state/empty-dag-md.svg'), empty_state_image_path: match_asset_path('illustrations/empty-state/empty-test-cases-lg.svg'), artifacts_expired_image_path: match_asset_path('illustrations/pipeline.svg'), tests_count: pipeline.test_report_summary.total[:count]