diff options
Diffstat (limited to 'spec/frontend/pipelines/graph/graph_component_wrapper_spec.js')
-rw-r--r-- | spec/frontend/pipelines/graph/graph_component_wrapper_spec.js | 154 |
1 files changed, 146 insertions, 8 deletions
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js index 8c469966be4..4914a9a1ced 100644 --- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js +++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js @@ -15,8 +15,10 @@ import PipelineGraph from '~/pipelines/components/graph/graph_component.vue'; import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue'; import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue'; import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue'; +import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue'; import * as parsingUtils from '~/pipelines/components/parsing_utils'; -import { mockPipelineResponse } from './mock_data'; +import getUserCallouts from '~/pipelines/graphql/queries/get_user_callouts.query.graphql'; +import { mapCallouts, mockCalloutsResponse, mockPipelineResponse } from './mock_data'; const defaultProvide = { graphqlResourceEtag: 'frog/amphibirama/etag/', @@ -30,13 +32,16 @@ describe('Pipeline graph wrapper', () => { useLocalStorageSpy(); let wrapper; - const getAlert = () => wrapper.find(GlAlert); - const getLoadingIcon = () => wrapper.find(GlLoadingIcon); + const getAlert = () => wrapper.findComponent(GlAlert); + const getDependenciesToggle = () => wrapper.find('[data-testid="show-links-toggle"]'); + const getLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const getLinksLayer = () => wrapper.findComponent(LinksLayer); const getGraph = () => wrapper.find(PipelineGraph); const getStageColumnTitle = () => wrapper.find('[data-testid="stage-column-title"]'); const getAllStageColumnGroupsInColumn = () => wrapper.find(StageColumnComponent).findAll('[data-testid="stage-column-group"]'); const getViewSelector = () => wrapper.find(GraphViewSelector); + const getViewSelectorTrip = () => getViewSelector().findComponent(GlAlert); const createComponent = ({ apolloProvider, @@ -59,14 +64,22 @@ describe('Pipeline graph wrapper', () => { }; const createComponentWithApollo = ({ + calloutsList = [], + data = {}, getPipelineDetailsHandler = jest.fn().mockResolvedValue(mockPipelineResponse), mountFn = shallowMount, provide = {}, } = {}) => { - const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]]; + const callouts = mapCallouts(calloutsList); + const getUserCalloutsHandler = jest.fn().mockResolvedValue(mockCalloutsResponse(callouts)); + + const requestHandlers = [ + [getPipelineDetails, getPipelineDetailsHandler], + [getUserCallouts, getUserCalloutsHandler], + ]; const apolloProvider = createMockApollo(requestHandlers); - createComponent({ apolloProvider, provide, mountFn }); + createComponent({ apolloProvider, data, provide, mountFn }); }; afterEach(() => { @@ -74,6 +87,15 @@ describe('Pipeline graph wrapper', () => { wrapper = null; }); + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.runOnlyPendingTimers(); + jest.useRealTimers(); + }); + describe('when data is loading', () => { it('displays the loading icon', () => { createComponentWithApollo(); @@ -282,6 +304,87 @@ describe('Pipeline graph wrapper', () => { }); }); + describe('when pipelineGraphLayersView feature flag is on and layers view is selected', () => { + beforeEach(async () => { + createComponentWithApollo({ + provide: { + glFeatures: { + pipelineGraphLayersView: true, + }, + }, + data: { + currentViewType: LAYER_VIEW, + }, + mountFn: mount, + }); + + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + }); + + it('sets showLinks to true', async () => { + /* This spec uses .props for performance reasons. */ + expect(getLinksLayer().exists()).toBe(true); + expect(getLinksLayer().props('showLinks')).toBe(false); + expect(getViewSelector().props('type')).toBe(LAYER_VIEW); + await getDependenciesToggle().trigger('click'); + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true); + }); + }); + + describe('when pipelineGraphLayersView feature flag is on, layers view is selected, and links are active', () => { + beforeEach(async () => { + createComponentWithApollo({ + provide: { + glFeatures: { + pipelineGraphLayersView: true, + }, + }, + data: { + currentViewType: LAYER_VIEW, + showLinks: true, + }, + mountFn: mount, + }); + + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + }); + + it('shows the hover tip in the view selector', async () => { + await getViewSelector().setData({ showLinksActive: true }); + expect(getViewSelectorTrip().exists()).toBe(true); + }); + }); + + describe('when hover tip would otherwise show, but it has been previously dismissed', () => { + beforeEach(async () => { + createComponentWithApollo({ + provide: { + glFeatures: { + pipelineGraphLayersView: true, + }, + }, + data: { + currentViewType: LAYER_VIEW, + showLinks: true, + }, + mountFn: mount, + calloutsList: ['pipeline_needs_hover_tip'.toUpperCase()], + }); + + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + }); + + it('does not show the hover tip', async () => { + await getViewSelector().setData({ showLinksActive: true }); + expect(getViewSelectorTrip().exists()).toBe(false); + }); + }); + describe('when feature flag is on and local storage is set', () => { beforeEach(async () => { localStorage.setItem(VIEW_TYPE_KEY, LAYER_VIEW); @@ -299,10 +402,45 @@ describe('Pipeline graph wrapper', () => { await wrapper.vm.$nextTick(); }); + afterEach(() => { + localStorage.clear(); + }); + it('reads the view type from localStorage when available', () => { - expect(wrapper.find('[data-testid="pipeline-view-selector"] code').text()).toContain( - 'needs:', - ); + const viewSelectorNeedsSegment = wrapper + .findAll('[data-testid="pipeline-view-selector"] > label') + .at(1); + expect(viewSelectorNeedsSegment.classes()).toContain('active'); + }); + }); + + describe('when feature flag is on and local storage is set, but the graph does not use needs', () => { + beforeEach(async () => { + const nonNeedsResponse = { ...mockPipelineResponse }; + nonNeedsResponse.data.project.pipeline.usesNeeds = false; + + localStorage.setItem(VIEW_TYPE_KEY, LAYER_VIEW); + + createComponentWithApollo({ + provide: { + glFeatures: { + pipelineGraphLayersView: true, + }, + }, + mountFn: mount, + getPipelineDetailsHandler: jest.fn().mockResolvedValue(nonNeedsResponse), + }); + + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + }); + + afterEach(() => { + localStorage.clear(); + }); + + it('still passes stage type to graph', () => { + expect(getGraph().props('viewType')).toBe(STAGE_VIEW); }); }); |