diff options
Diffstat (limited to 'spec/frontend/pipelines')
-rw-r--r-- | spec/frontend/pipelines/__snapshots__/utils_spec.js.snap | 47 | ||||
-rw-r--r-- | spec/frontend/pipelines/components/jobs/jobs_app_spec.js | 106 | ||||
-rw-r--r-- | spec/frontend/pipelines/graph/graph_component_wrapper_spec.js | 44 | ||||
-rw-r--r-- | spec/frontend/pipelines/graph/graph_view_selector_spec.js | 36 | ||||
-rw-r--r-- | spec/frontend/pipelines/graph/mock_data.js | 81 | ||||
-rw-r--r-- | spec/frontend/pipelines/mock_data.js | 141 |
6 files changed, 424 insertions, 31 deletions
diff --git a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap index 60625d301c0..99de0d2a3ef 100644 --- a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap +++ b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap @@ -6,9 +6,11 @@ Array [ "groups": Array [ Object { "__typename": "CiGroup", + "id": "4", "jobs": Array [ Object { "__typename": "CiJob", + "id": "6", "name": "build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl", "needs": Array [], "scheduledAt": null, @@ -18,6 +20,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "8", "path": "/root/abcd-dag/-/jobs/1482/retry", "title": "Retry", }, @@ -25,6 +28,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "7", "tooltip": "passed", }, }, @@ -36,14 +40,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "5", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "9", "jobs": Array [ Object { "__typename": "CiJob", + "id": "11", "name": "build_b", "needs": Array [], "scheduledAt": null, @@ -53,6 +60,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "13", "path": "/root/abcd-dag/-/jobs/1515/retry", "title": "Retry", }, @@ -60,6 +68,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "12", "tooltip": "passed", }, }, @@ -71,14 +80,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "10", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "14", "jobs": Array [ Object { "__typename": "CiJob", + "id": "16", "name": "build_c", "needs": Array [], "scheduledAt": null, @@ -88,6 +100,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "18", "path": "/root/abcd-dag/-/jobs/1484/retry", "title": "Retry", }, @@ -95,6 +108,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "17", "tooltip": "passed", }, }, @@ -106,14 +120,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "15", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "19", "jobs": Array [ Object { "__typename": "CiJob", + "id": "21", "name": "build_d 1/3", "needs": Array [], "scheduledAt": null, @@ -123,6 +140,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "23", "path": "/root/abcd-dag/-/jobs/1485/retry", "title": "Retry", }, @@ -130,11 +148,13 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "22", "tooltip": "passed", }, }, Object { "__typename": "CiJob", + "id": "24", "name": "build_d 2/3", "needs": Array [], "scheduledAt": null, @@ -144,6 +164,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "26", "path": "/root/abcd-dag/-/jobs/1486/retry", "title": "Retry", }, @@ -151,11 +172,13 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "25", "tooltip": "passed", }, }, Object { "__typename": "CiJob", + "id": "27", "name": "build_d 3/3", "needs": Array [], "scheduledAt": null, @@ -165,6 +188,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "29", "path": "/root/abcd-dag/-/jobs/1487/retry", "title": "Retry", }, @@ -172,6 +196,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "28", "tooltip": "passed", }, }, @@ -183,14 +208,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "20", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "57", "jobs": Array [ Object { "__typename": "CiJob", + "id": "59", "name": "test_c", "needs": Array [], "scheduledAt": null, @@ -201,6 +229,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "60", "tooltip": null, }, }, @@ -212,6 +241,7 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "58", "label": null, }, }, @@ -226,9 +256,11 @@ Array [ "groups": Array [ Object { "__typename": "CiGroup", + "id": "32", "jobs": Array [ Object { "__typename": "CiJob", + "id": "34", "name": "test_a", "needs": Array [ "build_c", @@ -242,6 +274,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "36", "path": "/root/abcd-dag/-/jobs/1514/retry", "title": "Retry", }, @@ -249,6 +282,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "35", "tooltip": "passed", }, }, @@ -260,14 +294,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "33", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "40", "jobs": Array [ Object { "__typename": "CiJob", + "id": "42", "name": "test_b 1/2", "needs": Array [ "build_d 3/3", @@ -283,6 +320,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "44", "path": "/root/abcd-dag/-/jobs/1489/retry", "title": "Retry", }, @@ -290,11 +328,13 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "43", "tooltip": "passed", }, }, Object { "__typename": "CiJob", + "id": "67", "name": "test_b 2/2", "needs": Array [ "build_d 3/3", @@ -310,6 +350,7 @@ Array [ "__typename": "StatusAction", "buttonTitle": "Retry this job", "icon": "retry", + "id": "51", "path": "/root/abcd-dag/-/jobs/1490/retry", "title": "Retry", }, @@ -317,6 +358,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "50", "tooltip": "passed", }, }, @@ -328,14 +370,17 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "41", "label": "passed", }, }, Object { "__typename": "CiGroup", + "id": "61", "jobs": Array [ Object { "__typename": "CiJob", + "id": "53", "name": "test_d", "needs": Array [ "build_b", @@ -348,6 +393,7 @@ Array [ "group": "success", "hasDetails": true, "icon": "status_success", + "id": "64", "tooltip": null, }, }, @@ -359,6 +405,7 @@ Array [ "__typename": "DetailedStatus", "group": "success", "icon": "status_success", + "id": "62", "label": null, }, }, diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js new file mode 100644 index 00000000000..1ea6096c922 --- /dev/null +++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js @@ -0,0 +1,106 @@ +import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import createFlash from '~/flash'; +import JobsApp from '~/pipelines/components/jobs/jobs_app.vue'; +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); + +jest.mock('~/flash'); + +describe('Jobs app', () => { + let wrapper; + let resolverSpy; + + const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader); + const findJobsTable = () => wrapper.findComponent(JobsTable); + + const triggerInfiniteScroll = () => + wrapper.findComponent(GlIntersectionObserver).vm.$emit('appear'); + + const createMockApolloProvider = (resolver) => { + const requestHandlers = [[getPipelineJobsQuery, resolver]]; + + return createMockApollo(requestHandlers); + }; + + const createComponent = (resolver) => { + wrapper = shallowMount(JobsApp, { + provide: { + fullPath: 'root/ci-project', + pipelineIid: 1, + }, + localVue, + apolloProvider: createMockApolloProvider(resolver), + }); + }; + + beforeEach(() => { + resolverSpy = jest.fn().mockResolvedValue(mockPipelineJobsQueryResponse); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('displays the loading state', () => { + createComponent(resolverSpy); + + expect(findSkeletonLoader().exists()).toBe(true); + expect(findJobsTable().exists()).toBe(false); + }); + + it('displays the jobs table', async () => { + createComponent(resolverSpy); + + await waitForPromises(); + + expect(findJobsTable().exists()).toBe(true); + expect(findSkeletonLoader().exists()).toBe(false); + expect(createFlash).not.toHaveBeenCalled(); + }); + + it('handles job fetch error correctly', async () => { + resolverSpy = jest.fn().mockRejectedValue(new Error('GraphQL error')); + + createComponent(resolverSpy); + + await waitForPromises(); + + expect(createFlash).toHaveBeenCalledWith({ + message: 'An error occured while fetching the pipelines jobs.', + }); + }); + + it('handles infinite scrolling by calling fetchMore', async () => { + createComponent(resolverSpy); + + await waitForPromises(); + + triggerInfiniteScroll(); + + expect(resolverSpy).toHaveBeenCalledWith({ + after: 'eyJpZCI6Ijg0NyJ9', + fullPath: 'root/ci-project', + iid: 1, + }); + }); + + it('does not display main loading state again after fetchMore', async () => { + createComponent(resolverSpy); + + expect(findSkeletonLoader().exists()).toBe(true); + + await waitForPromises(); + + triggerInfiniteScroll(); + + expect(findSkeletonLoader().exists()).toBe(false); + }); +}); diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js index db4de6deeb7..04e004dc6c1 100644 --- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js +++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js @@ -1,7 +1,7 @@ -import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; +import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -98,7 +98,6 @@ describe('Pipeline graph wrapper', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); beforeAll(() => { @@ -136,7 +135,7 @@ describe('Pipeline graph wrapper', () => { beforeEach(async () => { createComponentWithApollo(); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('does not display the loading icon', () => { @@ -165,7 +164,7 @@ describe('Pipeline graph wrapper', () => { getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')), }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('does not display the loading icon', () => { @@ -189,7 +188,7 @@ describe('Pipeline graph wrapper', () => { }, }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('does not display the loading icon', () => { @@ -211,7 +210,7 @@ describe('Pipeline graph wrapper', () => { createComponentWithApollo(); jest.spyOn(wrapper.vm.$apollo.queries.headerPipeline, 'refetch'); jest.spyOn(wrapper.vm.$apollo.queries.pipeline, 'refetch'); - await wrapper.vm.$nextTick(); + await nextTick(); getGraph().vm.$emit('refreshPipelineGraph'); }); @@ -225,8 +224,8 @@ describe('Pipeline graph wrapper', () => { describe('when query times out', () => { const advanceApolloTimers = async () => { jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); - await wrapper.vm.$nextTick(); + await nextTick(); + await nextTick(); }; beforeEach(async () => { @@ -246,7 +245,7 @@ describe('Pipeline graph wrapper', () => { .mockResolvedValueOnce(errorData); createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('shows correct errors and does not overwrite populated data when data is empty', async () => { @@ -276,7 +275,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('appears when pipeline uses needs', () => { @@ -319,7 +318,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('sets showLinks to true', async () => { @@ -329,7 +328,7 @@ describe('Pipeline graph wrapper', () => { expect(getViewSelector().props('type')).toBe(LAYER_VIEW); await getDependenciesToggle().vm.$emit('change', true); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true); }); }); @@ -345,7 +344,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('shows the hover tip in the view selector', async () => { @@ -366,7 +365,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('does not show the hover tip', async () => { @@ -384,7 +383,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -393,9 +392,10 @@ describe('Pipeline graph wrapper', () => { it('reads the view type from localStorage when available', () => { const viewSelectorNeedsSegment = wrapper - .findAll('[data-testid="pipeline-view-selector"] > label') + .find(GlButtonGroup) + .findAllComponents(GlButton) .at(1); - expect(viewSelectorNeedsSegment.classes()).toContain('active'); + expect(viewSelectorNeedsSegment.classes()).toContain('selected'); }); }); @@ -412,7 +412,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -435,7 +435,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('does not appear when pipeline does not use needs', () => { @@ -462,7 +462,7 @@ describe('Pipeline graph wrapper', () => { beforeEach(async () => { createComponentWithApollo(); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('is not called', () => { @@ -506,7 +506,7 @@ describe('Pipeline graph wrapper', () => { }); jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('attempts to collect metrics', () => { diff --git a/spec/frontend/pipelines/graph/graph_view_selector_spec.js b/spec/frontend/pipelines/graph/graph_view_selector_spec.js index f4faa25545b..f574f4dccc5 100644 --- a/spec/frontend/pipelines/graph/graph_view_selector_spec.js +++ b/spec/frontend/pipelines/graph/graph_view_selector_spec.js @@ -1,4 +1,4 @@ -import { GlAlert, GlLoadingIcon, GlSegmentedControl } from '@gitlab/ui'; +import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import { LAYER_VIEW, STAGE_VIEW } from '~/pipelines/components/graph/constants'; import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue'; @@ -7,9 +7,9 @@ describe('the graph view selector component', () => { let wrapper; const findDependenciesToggle = () => wrapper.find('[data-testid="show-links-toggle"]'); - const findViewTypeSelector = () => wrapper.findComponent(GlSegmentedControl); - const findStageViewLabel = () => findViewTypeSelector().findAll('label').at(0); - const findLayersViewLabel = () => findViewTypeSelector().findAll('label').at(1); + const findViewTypeSelector = () => wrapper.findComponent(GlButtonGroup); + const findStageViewButton = () => findViewTypeSelector().findAllComponents(GlButton).at(0); + const findLayerViewButton = () => findViewTypeSelector().findAllComponents(GlButton).at(1); const findSwitcherLoader = () => wrapper.find('[data-testid="switcher-loading-state"]'); const findToggleLoader = () => findDependenciesToggle().find(GlLoadingIcon); const findHoverTip = () => wrapper.findComponent(GlAlert); @@ -51,8 +51,13 @@ describe('the graph view selector component', () => { createComponent({ mountFn: mount }); }); - it('shows the Stage view label as active in the selector', () => { - expect(findStageViewLabel().classes()).toContain('active'); + it('shows the Stage view button as selected', () => { + expect(findStageViewButton().classes('selected')).toBe(true); + }); + + it('shows the Job dependencies view button not selected', () => { + expect(findLayerViewButton().exists()).toBe(true); + expect(findLayerViewButton().classes('selected')).toBe(false); }); it('does not show the Job dependencies (links) toggle', () => { @@ -70,8 +75,13 @@ describe('the graph view selector component', () => { }); }); - it('shows the Job dependencies view label as active in the selector', () => { - expect(findLayersViewLabel().classes()).toContain('active'); + it('shows the Job dependencies view as selected', () => { + expect(findLayerViewButton().classes('selected')).toBe(true); + }); + + it('shows the Stage button as not selected', () => { + expect(findStageViewButton().exists()).toBe(true); + expect(findStageViewButton().classes('selected')).toBe(false); }); it('shows the Job dependencies (links) toggle', () => { @@ -94,7 +104,7 @@ describe('the graph view selector component', () => { expect(wrapper.emitted().updateViewType).toBeUndefined(); expect(findSwitcherLoader().exists()).toBe(false); - await findStageViewLabel().trigger('click'); + await findStageViewButton().trigger('click'); /* Loading happens before the event is emitted or timers are run. Then we run the timer because the event is emitted in setInterval @@ -123,6 +133,14 @@ describe('the graph view selector component', () => { expect(wrapper.emitted().updateShowLinksState).toHaveLength(1); expect(wrapper.emitted().updateShowLinksState).toEqual([[true]]); }); + + it('does not emit an event if the click occurs on the currently selected view button', async () => { + expect(wrapper.emitted().updateShowLinksState).toBeUndefined(); + + await findLayerViewButton().trigger('click'); + + expect(wrapper.emitted().updateShowLinksState).toBeUndefined(); + }); }); describe('hover tip callout', () => { diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js index 3812483766d..dcbbde7bf36 100644 --- a/spec/frontend/pipelines/graph/mock_data.js +++ b/spec/frontend/pipelines/graph/mock_data.js @@ -4,6 +4,7 @@ export const mockPipelineResponse = { data: { project: { __typename: 'Project', + id: '1', pipeline: { __typename: 'Pipeline', id: 163, @@ -21,9 +22,11 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiStage', + id: '2', name: 'build', status: { __typename: 'DetailedStatus', + id: '3', action: null, }, groups: { @@ -31,10 +34,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiGroup', + id: '4', name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl', size: 1, status: { __typename: 'DetailedStatus', + id: '5', label: 'passed', group: 'success', icon: 'status_success', @@ -44,10 +49,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '6', name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '7', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -55,6 +62,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '8', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1482/retry', @@ -72,9 +80,11 @@ export const mockPipelineResponse = { { __typename: 'CiGroup', name: 'build_b', + id: '9', size: 1, status: { __typename: 'DetailedStatus', + id: '10', label: 'passed', group: 'success', icon: 'status_success', @@ -84,10 +94,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '11', name: 'build_b', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '12', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -95,6 +107,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '13', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1515/retry', @@ -111,10 +124,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiGroup', + id: '14', name: 'build_c', size: 1, status: { __typename: 'DetailedStatus', + id: '15', label: 'passed', group: 'success', icon: 'status_success', @@ -124,10 +139,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '16', name: 'build_c', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '17', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -135,6 +152,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '18', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1484/retry', @@ -151,10 +169,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiGroup', + id: '19', name: 'build_d', size: 3, status: { __typename: 'DetailedStatus', + id: '20', label: 'passed', group: 'success', icon: 'status_success', @@ -164,10 +184,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '21', name: 'build_d 1/3', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '22', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -175,6 +197,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '23', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1485/retry', @@ -188,10 +211,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiJob', + id: '24', name: 'build_d 2/3', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '25', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -199,6 +224,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '26', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1486/retry', @@ -212,10 +238,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiJob', + id: '27', name: 'build_d 3/3', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '28', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -223,6 +251,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '29', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1487/retry', @@ -242,9 +271,11 @@ export const mockPipelineResponse = { }, { __typename: 'CiStage', + id: '30', name: 'test', status: { __typename: 'DetailedStatus', + id: '31', action: null, }, groups: { @@ -252,10 +283,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiGroup', + id: '32', name: 'test_a', size: 1, status: { __typename: 'DetailedStatus', + id: '33', label: 'passed', group: 'success', icon: 'status_success', @@ -265,10 +298,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '34', name: 'test_a', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '35', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -276,6 +311,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '36', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1514/retry', @@ -287,14 +323,17 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiBuildNeed', + id: '37', name: 'build_c', }, { __typename: 'CiBuildNeed', + id: '38', name: 'build_b', }, { __typename: 'CiBuildNeed', + id: '39', name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl', }, @@ -306,10 +345,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiGroup', + id: '40', name: 'test_b', size: 2, status: { __typename: 'DetailedStatus', + id: '41', label: 'passed', group: 'success', icon: 'status_success', @@ -319,10 +360,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '42', name: 'test_b 1/2', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '43', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -330,6 +373,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '44', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1489/retry', @@ -341,22 +385,27 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiBuildNeed', + id: '45', name: 'build_d 3/3', }, { __typename: 'CiBuildNeed', + id: '46', name: 'build_d 2/3', }, { __typename: 'CiBuildNeed', + id: '47', name: 'build_d 1/3', }, { __typename: 'CiBuildNeed', + id: '48', name: 'build_b', }, { __typename: 'CiBuildNeed', + id: '49', name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl', }, @@ -365,10 +414,12 @@ export const mockPipelineResponse = { }, { __typename: 'CiJob', + id: '67', name: 'test_b 2/2', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '50', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -376,6 +427,7 @@ export const mockPipelineResponse = { group: 'success', action: { __typename: 'StatusAction', + id: '51', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/abcd-dag/-/jobs/1490/retry', @@ -387,22 +439,27 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiBuildNeed', + id: '52', name: 'build_d 3/3', }, { __typename: 'CiBuildNeed', + id: '53', name: 'build_d 2/3', }, { __typename: 'CiBuildNeed', + id: '54', name: 'build_d 1/3', }, { __typename: 'CiBuildNeed', + id: '55', name: 'build_b', }, { __typename: 'CiBuildNeed', + id: '56', name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl', }, @@ -415,9 +472,11 @@ export const mockPipelineResponse = { { __typename: 'CiGroup', name: 'test_c', + id: '57', size: 1, status: { __typename: 'DetailedStatus', + id: '58', label: null, group: 'success', icon: 'status_success', @@ -427,10 +486,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '59', name: 'test_c', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '60', icon: 'status_success', tooltip: null, hasDetails: true, @@ -448,9 +509,11 @@ export const mockPipelineResponse = { }, { __typename: 'CiGroup', + id: '61', name: 'test_d', size: 1, status: { + id: '62', __typename: 'DetailedStatus', label: null, group: 'success', @@ -461,10 +524,12 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiJob', + id: '53', name: 'test_d', scheduledAt: null, status: { __typename: 'DetailedStatus', + id: '64', icon: 'status_success', tooltip: null, hasDetails: true, @@ -477,6 +542,7 @@ export const mockPipelineResponse = { nodes: [ { __typename: 'CiBuildNeed', + id: '65', name: 'build_b', }, ], @@ -502,6 +568,7 @@ export const downstream = { iid: '31', path: '/root/elemenohpee/-/pipelines/175', status: { + id: '70', group: 'success', label: 'passed', icon: 'status_success', @@ -509,6 +576,7 @@ export const downstream = { }, sourceJob: { name: 'test_c', + id: '71', __typename: 'CiJob', }, project: { @@ -525,12 +593,14 @@ export const downstream = { iid: '27', path: '/root/abcd-dag/-/pipelines/181', status: { + id: '72', group: 'success', label: 'passed', icon: 'status_success', __typename: 'DetailedStatus', }, sourceJob: { + id: '73', name: 'test_d', __typename: 'CiJob', }, @@ -551,6 +621,7 @@ export const upstream = { iid: '24', path: '/root/abcd-dag/-/pipelines/161', status: { + id: '74', group: 'success', label: 'passed', icon: 'status_success', @@ -571,6 +642,7 @@ export const wrappedPipelineReturn = { data: { project: { __typename: 'Project', + id: '75', pipeline: { __typename: 'Pipeline', id: 'gid://gitlab/Ci::Pipeline/175', @@ -592,12 +664,14 @@ export const wrappedPipelineReturn = { __typename: 'Pipeline', status: { __typename: 'DetailedStatus', + id: '77', group: 'success', label: 'passed', icon: 'status_success', }, sourceJob: { name: 'test_c', + id: '78', __typename: 'CiJob', }, project: { @@ -613,8 +687,10 @@ export const wrappedPipelineReturn = { { name: 'build', __typename: 'CiStage', + id: '79', status: { action: null, + id: '80', __typename: 'DetailedStatus', }, groups: { @@ -622,8 +698,10 @@ export const wrappedPipelineReturn = { nodes: [ { __typename: 'CiGroup', + id: '81', status: { __typename: 'DetailedStatus', + id: '82', label: 'passed', group: 'success', icon: 'status_success', @@ -635,6 +713,7 @@ export const wrappedPipelineReturn = { nodes: [ { __typename: 'CiJob', + id: '83', name: 'build_n', scheduledAt: null, needs: { @@ -643,6 +722,7 @@ export const wrappedPipelineReturn = { }, status: { __typename: 'DetailedStatus', + id: '84', icon: 'status_success', tooltip: 'passed', hasDetails: true, @@ -650,6 +730,7 @@ export const wrappedPipelineReturn = { group: 'success', action: { __typename: 'StatusAction', + id: '85', buttonTitle: 'Retry this job', icon: 'retry', path: '/root/elemenohpee/-/jobs/1662/retry', diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js index fdc78d48901..b9d20eb7ca5 100644 --- a/spec/frontend/pipelines/mock_data.js +++ b/spec/frontend/pipelines/mock_data.js @@ -14,6 +14,7 @@ export const mockPipelineHeader = { }, createdAt: threeWeeksAgo.toISOString(), user: { + id: 'user-1', name: 'Foo', username: 'foobar', email: 'foo@bar.com', @@ -27,6 +28,7 @@ export const mockFailedPipelineHeader = { retryable: true, cancelable: false, detailedStatus: { + id: 'status-1', group: 'failed', icon: 'status_failed', label: 'failed', @@ -43,6 +45,7 @@ export const mockFailedPipelineNoPermissions = { }, createdAt: threeWeeksAgo.toISOString(), user: { + id: 'user-1', name: 'Foo', username: 'foobar', email: 'foo@bar.com', @@ -52,6 +55,7 @@ export const mockFailedPipelineNoPermissions = { retryable: true, cancelable: false, detailedStatus: { + id: 'status-1', group: 'running', icon: 'status_running', label: 'running', @@ -66,6 +70,7 @@ export const mockRunningPipelineHeader = { retryable: false, cancelable: true, detailedStatus: { + id: 'status-1', group: 'running', icon: 'status_running', label: 'running', @@ -82,6 +87,7 @@ export const mockRunningPipelineNoPermissions = { }, createdAt: threeWeeksAgo.toISOString(), user: { + id: 'user-1', name: 'Foo', username: 'foobar', email: 'foo@bar.com', @@ -91,6 +97,7 @@ export const mockRunningPipelineNoPermissions = { retryable: false, cancelable: true, detailedStatus: { + id: 'status-1', group: 'running', icon: 'status_running', label: 'running', @@ -105,6 +112,7 @@ export const mockCancelledPipelineHeader = { retryable: true, cancelable: false, detailedStatus: { + id: 'status-1', group: 'cancelled', icon: 'status_cancelled', label: 'cancelled', @@ -119,6 +127,7 @@ export const mockSuccessfulPipelineHeader = { retryable: false, cancelable: false, detailedStatus: { + id: 'status-1', group: 'success', icon: 'status_success', label: 'success', @@ -130,13 +139,16 @@ export const mockSuccessfulPipelineHeader = { export const mockRunningPipelineHeaderData = { data: { project: { + id: '1', pipeline: { ...mockRunningPipelineHeader, iid: '28', user: { + id: 'user-1', name: 'Foo', username: 'foobar', webPath: '/foo', + webUrl: '/foo', email: 'foo@bar.com', avatarUrl: 'link', status: null, @@ -493,3 +505,132 @@ export const mockSearch = [ export const mockBranchesAfterMap = ['branch-1', 'branch-10', 'branch-11']; export const mockTagsAfterMap = ['tag-3', 'tag-2', 'tag-1', 'main-tag']; + +export const mockPipelineJobsQueryResponse = { + data: { + project: { + id: 'gid://gitlab/Project/20', + __typename: 'Project', + pipeline: { + id: 'gid://gitlab/Ci::Pipeline/224', + __typename: 'Pipeline', + jobs: { + __typename: 'CiJobConnection', + pageInfo: { + endCursor: 'eyJpZCI6Ijg0NyJ9', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'eyJpZCI6IjYyMCJ9', + __typename: 'PageInfo', + }, + nodes: [ + { + artifacts: { + nodes: [ + { + downloadPath: '/root/ci-project/-/jobs/620/artifacts/download?file_type=trace', + fileType: 'TRACE', + __typename: 'CiJobArtifact', + }, + ], + __typename: 'CiJobArtifactConnection', + }, + allowFailure: false, + status: 'SUCCESS', + scheduledAt: null, + manualJob: false, + triggered: null, + createdByTag: false, + detailedStatus: { + id: 'success-620-620', + detailsPath: '/root/ci-project/-/jobs/620', + group: 'success', + icon: 'status_success', + label: 'passed', + text: 'passed', + tooltip: 'passed (retried)', + action: null, + __typename: 'DetailedStatus', + }, + id: 'gid://gitlab/Ci::Build/620', + refName: 'main', + refPath: '/root/ci-project/-/commits/main', + tags: [], + shortSha: '5acce24b', + commitPath: '/root/ci-project/-/commit/5acce24b3737d4f0d649ad0a26ae1903a2b35f5e', + stage: { id: 'gid://gitlab/Ci::Stage/148', name: 'test', __typename: 'CiStage' }, + name: 'coverage_job', + duration: 4, + finishedAt: '2021-12-06T14:13:49Z', + coverage: 82.71, + retryable: false, + playable: false, + cancelable: false, + active: false, + stuck: false, + userPermissions: { + readBuild: true, + readJobArtifacts: true, + updateBuild: true, + __typename: 'JobPermissions', + }, + __typename: 'CiJob', + }, + { + artifacts: { + nodes: [ + { + downloadPath: '/root/ci-project/-/jobs/619/artifacts/download?file_type=trace', + fileType: 'TRACE', + __typename: 'CiJobArtifact', + }, + ], + __typename: 'CiJobArtifactConnection', + }, + allowFailure: false, + status: 'SUCCESS', + scheduledAt: null, + manualJob: false, + triggered: null, + createdByTag: false, + detailedStatus: { + id: 'success-619-619', + detailsPath: '/root/ci-project/-/jobs/619', + group: 'success', + icon: 'status_success', + label: 'passed', + text: 'passed', + tooltip: 'passed (retried)', + action: null, + __typename: 'DetailedStatus', + }, + id: 'gid://gitlab/Ci::Build/619', + refName: 'main', + refPath: '/root/ci-project/-/commits/main', + tags: [], + shortSha: '5acce24b', + commitPath: '/root/ci-project/-/commit/5acce24b3737d4f0d649ad0a26ae1903a2b35f5e', + stage: { id: 'gid://gitlab/Ci::Stage/148', name: 'test', __typename: 'CiStage' }, + name: 'test_job_two', + duration: 4, + finishedAt: '2021-12-06T14:13:44Z', + coverage: null, + retryable: false, + playable: false, + cancelable: false, + active: false, + stuck: false, + userPermissions: { + readBuild: true, + readJobArtifacts: true, + updateBuild: true, + __typename: 'JobPermissions', + }, + __typename: 'CiJob', + }, + ], + }, + }, + }, + }, +}; |