diff options
Diffstat (limited to 'spec/frontend/pipeline_editor/components/header')
3 files changed, 83 insertions, 81 deletions
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js index ef8ca574e59..27652bb268b 100644 --- a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js @@ -13,7 +13,7 @@ describe('Pipeline editor header', () => { }, }; - const createComponent = ({ provide = {} } = {}) => { + const createComponent = ({ provide = {}, props = {} } = {}) => { wrapper = shallowMount(PipelineEditorHeader, { provide: { ...mockProvide, @@ -23,6 +23,8 @@ describe('Pipeline editor header', () => { ciConfigData: mockLintResponse, ciFileContent: mockCiYml, isCiConfigDataLoading: false, + isNewCiConfigFile: false, + ...props, }, }); }; @@ -36,15 +38,21 @@ describe('Pipeline editor header', () => { }); describe('template', () => { - beforeEach(() => { - createComponent(); + it('hides the pipeline status for new projects without a CI file', () => { + createComponent({ props: { isNewCiConfigFile: true } }); + + expect(findPipelineStatus().exists()).toBe(false); }); - it('renders the pipeline status', () => { + it('renders the pipeline status when CI file exists', () => { + createComponent({ props: { isNewCiConfigFile: false } }); + expect(findPipelineStatus().exists()).toBe(true); }); it('renders the validation segment', () => { + createComponent(); + expect(findValidationSegment().exists()).toBe(true); }); }); diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js index de6e112866b..b6d49d0d0f8 100644 --- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js @@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue'; +import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data'; @@ -19,32 +20,9 @@ describe('Pipeline Status', () => { let mockApollo; let mockPipelineQuery; - const createComponent = ({ hasPipeline = true, isQueryLoading = false }) => { - const pipeline = hasPipeline - ? { loading: isQueryLoading, ...mockProjectPipeline.pipeline } - : { loading: isQueryLoading }; - - wrapper = shallowMount(PipelineStatus, { - provide: mockProvide, - stubs: { GlLink, GlSprintf }, - data: () => (hasPipeline ? { pipeline } : {}), - mocks: { - $apollo: { - queries: { - pipeline, - }, - }, - }, - }); - }; - const createComponentWithApollo = () => { - const resolvers = { - Query: { - project: mockPipelineQuery, - }, - }; - mockApollo = createMockApollo([], resolvers); + const handlers = [[getPipelineQuery, mockPipelineQuery]]; + mockApollo = createMockApollo(handlers); wrapper = shallowMount(PipelineStatus, { localVue, @@ -78,16 +56,17 @@ describe('Pipeline Status', () => { wrapper = null; }); - describe('while querying', () => { - it('renders loading icon', () => { - createComponent({ isQueryLoading: true, hasPipeline: false }); + describe('loading icon', () => { + it('renders while query is being fetched', () => { + createComponentWithApollo(); expect(findLoadingIcon().exists()).toBe(true); expect(findPipelineLoadingMsg().text()).toBe(i18n.fetchLoading); }); - it('does not render loading icon if pipeline data is already set', () => { - createComponent({ isQueryLoading: true }); + it('does not render if query is no longer loading', async () => { + createComponentWithApollo(); + await waitForPromises(); expect(findLoadingIcon().exists()).toBe(false); }); @@ -96,7 +75,9 @@ describe('Pipeline Status', () => { describe('when querying data', () => { describe('when data is set', () => { beforeEach(async () => { - mockPipelineQuery.mockResolvedValue(mockProjectPipeline); + mockPipelineQuery.mockResolvedValue({ + data: { project: mockProjectPipeline }, + }); createComponentWithApollo(); await waitForPromises(); @@ -104,14 +85,10 @@ describe('Pipeline Status', () => { it('query is called with correct variables', async () => { expect(mockPipelineQuery).toHaveBeenCalledTimes(1); - expect(mockPipelineQuery).toHaveBeenCalledWith( - expect.anything(), - { - fullPath: mockProjectFullPath, - }, - expect.anything(), - expect.anything(), - ); + expect(mockPipelineQuery).toHaveBeenCalledWith({ + fullPath: mockProjectFullPath, + sha: mockCommitSha, + }); }); it('does not render error', () => { diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js index 274c2d1b8da..fd8a100bb2c 100644 --- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js +++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js @@ -6,13 +6,19 @@ import { sprintf } from '~/locale'; import ValidationSegment, { i18n, } from '~/pipeline_editor/components/header/validation_segment.vue'; -import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants'; +import { + CI_CONFIG_STATUS_INVALID, + EDITOR_APP_STATUS_EMPTY, + EDITOR_APP_STATUS_INVALID, + EDITOR_APP_STATUS_LOADING, + EDITOR_APP_STATUS_VALID, +} from '~/pipeline_editor/constants'; import { mockYmlHelpPagePath, mergeUnwrappedCiConfig, mockCiYml } from '../../mock_data'; describe('Validation segment component', () => { let wrapper; - const createComponent = (props = {}) => { + const createComponent = ({ props = {}, appStatus }) => { wrapper = extendedWrapper( shallowMount(ValidationSegment, { provide: { @@ -21,9 +27,14 @@ describe('Validation segment component', () => { propsData: { ciConfig: mergeUnwrappedCiConfig(), ciFileContent: mockCiYml, - loading: false, ...props, }, + // Simulate graphQL client query result + data() { + return { + appStatus, + }; + }, }), ); }; @@ -34,18 +45,17 @@ describe('Validation segment component', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); it('shows the loading state', () => { - createComponent({ loading: true }); + createComponent({ appStatus: EDITOR_APP_STATUS_LOADING }); expect(wrapper.text()).toBe(i18n.loading); }); describe('when config is empty', () => { beforeEach(() => { - createComponent({ ciFileContent: '' }); + createComponent({ appStatus: EDITOR_APP_STATUS_EMPTY }); }); it('has check icon', () => { @@ -59,7 +69,7 @@ describe('Validation segment component', () => { describe('when config is valid', () => { beforeEach(() => { - createComponent({}); + createComponent({ appStatus: EDITOR_APP_STATUS_VALID }); }); it('has check icon', () => { @@ -79,12 +89,9 @@ describe('Validation segment component', () => { describe('when config is invalid', () => { beforeEach(() => { createComponent({ - ciConfig: mergeUnwrappedCiConfig({ - status: CI_CONFIG_STATUS_INVALID, - }), + appStatus: EDITOR_APP_STATUS_INVALID, }); }); - it('has warning icon', () => { expect(findIcon().props('name')).toBe('warning-solid'); }); @@ -93,43 +100,53 @@ describe('Validation segment component', () => { expect(findValidationMsg().text()).toBe(i18n.invalid); }); - it('shows an invalid state with an error', () => { + it('shows the learn more link', () => { + expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath); + expect(findLearnMoreLink().text()).toBe('Learn more'); + }); + + describe('with multiple errors', () => { const firstError = 'First Error'; const secondError = 'Second Error'; - createComponent({ - ciConfig: mergeUnwrappedCiConfig({ - status: CI_CONFIG_STATUS_INVALID, - errors: [firstError, secondError], - }), + beforeEach(() => { + createComponent({ + props: { + ciConfig: mergeUnwrappedCiConfig({ + status: CI_CONFIG_STATUS_INVALID, + errors: [firstError, secondError], + }), + }, + }); + }); + it('shows an invalid state with an error', () => { + // Test the error is shown _and_ the string matches + expect(findValidationMsg().text()).toContain(firstError); + expect(findValidationMsg().text()).toBe( + sprintf(i18n.invalidWithReason, { reason: firstError }), + ); }); - - // Test the error is shown _and_ the string matches - expect(findValidationMsg().text()).toContain(firstError); - expect(findValidationMsg().text()).toBe( - sprintf(i18n.invalidWithReason, { reason: firstError }), - ); }); - it('shows an invalid state with an error while preventing XSS', () => { + describe('with XSS inside the error', () => { const evilError = '<script>evil();</script>'; - createComponent({ - ciConfig: mergeUnwrappedCiConfig({ - status: CI_CONFIG_STATUS_INVALID, - errors: [evilError], - }), + beforeEach(() => { + createComponent({ + props: { + ciConfig: mergeUnwrappedCiConfig({ + status: CI_CONFIG_STATUS_INVALID, + errors: [evilError], + }), + }, + }); }); + it('shows an invalid state with an error while preventing XSS', () => { + const { innerHTML } = findValidationMsg().element; - const { innerHTML } = findValidationMsg().element; - - expect(innerHTML).not.toContain(evilError); - expect(innerHTML).toContain(escape(evilError)); - }); - - it('shows the learn more link', () => { - expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath); - expect(findLearnMoreLink().text()).toBe('Learn more'); + expect(innerHTML).not.toContain(evilError); + expect(innerHTML).toContain(escape(evilError)); + }); }); }); }); |