debian-mirror-gitlab/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

343 lines
10 KiB
JavaScript
Raw Normal View History

2022-08-27 11:52:29 +05:30
// TODO
2022-08-13 15:12:31 +05:30
import { GlAlert, GlBadge, GlLoadingIcon, GlTabs } from '@gitlab/ui';
2022-08-27 11:52:29 +05:30
import { mount, shallowMount } from '@vue/test-utils';
2022-08-13 15:12:31 +05:30
import VueApollo from 'vue-apollo';
2021-12-11 22:18:48 +05:30
import Vue, { nextTick } from 'vue';
2022-08-13 15:12:31 +05:30
import createMockApollo from 'helpers/mock_apollo_helper';
2021-12-11 22:18:48 +05:30
import setWindowLocation from 'helpers/set_window_location_helper';
2021-03-11 19:13:27 +05:30
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
2022-07-23 23:45:48 +05:30
import CiValidate from '~/pipeline_editor/components/validate/ci_validate.vue';
import WalkthroughPopover from '~/pipeline_editor/components/popovers/walkthrough_popover.vue';
2021-03-11 19:13:27 +05:30
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
2021-04-29 21:17:54 +05:30
import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
import {
2021-12-11 22:18:48 +05:30
CREATE_TAB,
2021-04-29 21:17:54 +05:30
EDITOR_APP_STATUS_EMPTY,
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_INVALID,
EDITOR_APP_STATUS_VALID,
2021-12-11 22:18:48 +05:30
TAB_QUERY_PARAM,
2022-08-13 15:12:31 +05:30
VALIDATE_TAB,
VALIDATE_TAB_BADGE_DISMISSED_KEY,
2021-04-29 21:17:54 +05:30
} from '~/pipeline_editor/constants';
2021-03-11 19:13:27 +05:30
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
2022-08-13 15:12:31 +05:30
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
import {
mockBlobContentQueryResponse,
mockCiLintPath,
mockCiYml,
mockLintResponse,
mockLintResponseWithoutMerged,
} from '../mock_data';
2022-08-27 11:52:29 +05:30
Vue.use(VueApollo);
2021-12-11 22:18:48 +05:30
Vue.config.ignoredElements = ['gl-emoji'];
2021-03-11 19:13:27 +05:30
describe('Pipeline editor tabs component', () => {
let wrapper;
const MockTextEditor = {
template: '<div />',
};
2021-04-29 21:17:54 +05:30
const createComponent = ({
2021-12-11 22:18:48 +05:30
listeners = {},
2021-04-29 21:17:54 +05:30
props = {},
provide = {},
appStatus = EDITOR_APP_STATUS_VALID,
mountFn = shallowMount,
2022-08-13 15:12:31 +05:30
options = {},
2021-04-29 21:17:54 +05:30
} = {}) => {
2021-03-11 19:13:27 +05:30
wrapper = mountFn(PipelineEditorTabs, {
propsData: {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
2022-08-13 15:12:31 +05:30
currentTab: CREATE_TAB,
2021-12-11 22:18:48 +05:30
isNewCiConfigFile: true,
2022-06-21 17:19:12 +05:30
showDrawer: false,
2021-03-11 19:13:27 +05:30
...props,
},
2021-04-29 21:17:54 +05:30
data() {
return {
appStatus,
};
},
2022-08-13 15:12:31 +05:30
provide: {
2022-08-27 11:52:29 +05:30
ciConfigPath: '/path/to/ci-config',
2022-08-13 15:12:31 +05:30
ciLintPath: mockCiLintPath,
2022-08-27 11:52:29 +05:30
currentBranch: 'main',
projectFullPath: '/path/to/project',
simulatePipelineHelpPagePath: 'path/to/help/page',
validateTabIllustrationPath: 'path/to/svg',
2022-08-13 15:12:31 +05:30
...provide,
},
2021-03-11 19:13:27 +05:30
stubs: {
TextEditor: MockTextEditor,
2021-04-29 21:17:54 +05:30
EditorTab,
2021-03-11 19:13:27 +05:30
},
2021-12-11 22:18:48 +05:30
listeners,
2022-08-13 15:12:31 +05:30
...options,
});
};
let mockBlobContentData;
let mockApollo;
const createComponentWithApollo = ({ props, provide = {}, mountFn = shallowMount } = {}) => {
const handlers = [[getBlobContent, mockBlobContentData]];
mockApollo = createMockApollo(handlers);
createComponent({
props,
provide,
mountFn,
options: {
apolloProvider: mockApollo,
},
2021-03-11 19:13:27 +05:30
});
};
const findEditorTab = () => wrapper.find('[data-testid="editor-tab"]');
const findMergedTab = () => wrapper.find('[data-testid="merged-tab"]');
2022-07-23 23:45:48 +05:30
const findValidateTab = () => wrapper.find('[data-testid="validate-tab"]');
2021-03-11 19:13:27 +05:30
const findVisualizationTab = () => wrapper.find('[data-testid="visualization-tab"]');
const findAlert = () => wrapper.findComponent(GlAlert);
2022-08-13 15:12:31 +05:30
const findBadge = () => wrapper.findComponent(GlBadge);
2022-07-23 23:45:48 +05:30
const findCiValidate = () => wrapper.findComponent(CiValidate);
2021-12-11 22:18:48 +05:30
const findGlTabs = () => wrapper.findComponent(GlTabs);
2021-03-11 19:13:27 +05:30
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPipelineGraph = () => wrapper.findComponent(PipelineGraph);
const findTextEditor = () => wrapper.findComponent(MockTextEditor);
const findMergedPreview = () => wrapper.findComponent(CiConfigMergedPreview);
2021-12-11 22:18:48 +05:30
const findWalkthroughPopover = () => wrapper.findComponent(WalkthroughPopover);
2021-03-11 19:13:27 +05:30
2022-08-13 15:12:31 +05:30
beforeEach(() => {
mockBlobContentData = jest.fn();
});
2021-03-11 19:13:27 +05:30
afterEach(() => {
wrapper.destroy();
});
describe('editor tab', () => {
it('displays editor only after the tab is mounted', async () => {
2022-08-27 11:52:29 +05:30
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
createComponentWithApollo({ mountFn: mount });
2021-03-11 19:13:27 +05:30
expect(findTextEditor().exists()).toBe(false);
await nextTick();
expect(findTextEditor().exists()).toBe(true);
expect(findEditorTab().exists()).toBe(true);
});
});
describe('visualization tab', () => {
2021-06-08 01:23:25 +05:30
describe('while loading', () => {
beforeEach(() => {
createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
2021-03-11 19:13:27 +05:30
});
2021-06-08 01:23:25 +05:30
it('displays a loading icon if the lint query is loading', () => {
expect(findLoadingIcon().exists()).toBe(true);
expect(findPipelineGraph().exists()).toBe(false);
});
});
describe('after loading', () => {
2021-03-11 19:13:27 +05:30
beforeEach(() => {
2021-06-08 01:23:25 +05:30
createComponent();
2021-03-11 19:13:27 +05:30
});
2021-06-08 01:23:25 +05:30
it('display the tab and visualization', () => {
expect(findVisualizationTab().exists()).toBe(true);
expect(findPipelineGraph().exists()).toBe(true);
2021-03-11 19:13:27 +05:30
});
});
});
2022-07-23 23:45:48 +05:30
describe('validate tab', () => {
2022-08-27 11:52:29 +05:30
describe('after loading', () => {
beforeEach(() => {
createComponent();
2022-07-23 23:45:48 +05:30
});
2022-08-27 11:52:29 +05:30
it('displays the tab and the validate component', () => {
expect(findValidateTab().exists()).toBe(true);
expect(findCiValidate().exists()).toBe(true);
2022-07-23 23:45:48 +05:30
});
});
2022-08-27 11:52:29 +05:30
describe('NEW badge', () => {
describe('default', () => {
beforeEach(() => {
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
createComponentWithApollo({
mountFn: mount,
props: {
currentTab: VALIDATE_TAB,
2022-07-23 23:45:48 +05:30
},
2022-08-27 11:52:29 +05:30
});
2022-07-23 23:45:48 +05:30
});
2022-08-27 11:52:29 +05:30
it('renders badge by default', () => {
expect(findBadge().exists()).toBe(true);
expect(findBadge().text()).toBe(wrapper.vm.$options.i18n.new);
});
2022-07-23 23:45:48 +05:30
2022-08-27 11:52:29 +05:30
it('hides badge when moving away from the validate tab', async () => {
expect(findBadge().exists()).toBe(true);
2021-03-11 19:13:27 +05:30
2022-08-27 11:52:29 +05:30
await findEditorTab().vm.$emit('click');
2021-03-11 19:13:27 +05:30
2022-08-27 11:52:29 +05:30
expect(findBadge().exists()).toBe(false);
});
2021-03-11 19:13:27 +05:30
});
2022-08-27 11:52:29 +05:30
describe('if badge has been dismissed before', () => {
beforeEach(() => {
localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true');
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
createComponentWithApollo({ mountFn: mount });
2022-07-23 23:45:48 +05:30
});
2022-08-27 11:52:29 +05:30
it('does not render badge if it has been dismissed before', () => {
expect(findBadge().exists()).toBe(false);
});
2022-07-23 23:45:48 +05:30
});
});
});
2022-08-27 11:52:29 +05:30
2021-03-11 19:13:27 +05:30
describe('merged tab', () => {
2021-06-08 01:23:25 +05:30
describe('while loading', () => {
beforeEach(() => {
createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
2021-03-11 19:13:27 +05:30
});
2021-06-08 01:23:25 +05:30
it('displays a loading icon if the lint query is loading', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
2021-03-11 19:13:27 +05:30
2021-06-08 01:23:25 +05:30
describe('when there is a fetch error', () => {
beforeEach(() => {
2021-12-11 22:18:48 +05:30
createComponent({ props: { ciConfigData: mockLintResponseWithoutMerged } });
2021-03-11 19:13:27 +05:30
});
2021-06-08 01:23:25 +05:30
it('show an error message', () => {
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts.loadMergedYaml);
});
2021-03-11 19:13:27 +05:30
2021-06-08 01:23:25 +05:30
it('does not render the `merged_preview` component', () => {
expect(findMergedPreview().exists()).toBe(false);
2021-03-11 19:13:27 +05:30
});
});
2021-06-08 01:23:25 +05:30
describe('after loading', () => {
2021-03-11 19:13:27 +05:30
beforeEach(() => {
2021-06-08 01:23:25 +05:30
createComponent();
2021-03-11 19:13:27 +05:30
});
2021-06-08 01:23:25 +05:30
it('display the tab and the merged preview component', () => {
expect(findMergedTab().exists()).toBe(true);
expect(findMergedPreview().exists()).toBe(true);
2021-03-11 19:13:27 +05:30
});
});
});
2021-04-29 21:17:54 +05:30
describe('show tab content based on status', () => {
it.each`
2022-08-27 11:52:29 +05:30
appStatus | editor | viz | validate | merged
2021-04-29 21:17:54 +05:30
${undefined} | ${true} | ${true} | ${true} | ${true}
2022-08-27 11:52:29 +05:30
${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${true} | ${false}
2023-01-13 00:05:48 +05:30
${EDITOR_APP_STATUS_INVALID} | ${true} | ${false} | ${true} | ${true}
2021-04-29 21:17:54 +05:30
${EDITOR_APP_STATUS_VALID} | ${true} | ${true} | ${true} | ${true}
`(
2022-10-11 01:57:18 +05:30
'when status is $appStatus, we show - editor:$editor | viz:$viz | validate:$validate | merged:$merged',
2022-08-27 11:52:29 +05:30
({ appStatus, editor, viz, validate, merged }) => {
2021-04-29 21:17:54 +05:30
createComponent({ appStatus });
expect(findTextEditor().exists()).toBe(editor);
expect(findPipelineGraph().exists()).toBe(viz);
2022-08-27 11:52:29 +05:30
expect(findValidateTab().exists()).toBe(validate);
2021-04-29 21:17:54 +05:30
expect(findMergedPreview().exists()).toBe(merged);
},
);
});
2021-12-11 22:18:48 +05:30
describe('default tab based on url query param', () => {
const gitlabUrl = 'https://gitlab.test/ci/editor/';
const matchObject = {
hostname: 'gitlab.test',
pathname: '/ci/editor/',
search: '',
};
it(`is ${CREATE_TAB} if the query param ${TAB_QUERY_PARAM} is not present`, () => {
setWindowLocation(gitlabUrl);
createComponent();
expect(window.location).toMatchObject(matchObject);
});
it(`is ${CREATE_TAB} tab if the query param ${TAB_QUERY_PARAM} is invalid`, () => {
const queryValue = 'FOO';
setWindowLocation(`${gitlabUrl}?${TAB_QUERY_PARAM}=${queryValue}`);
createComponent();
// If the query param remains unchanged, then we have ignored it.
expect(window.location).toMatchObject({
...matchObject,
search: `?${TAB_QUERY_PARAM}=${queryValue}`,
});
});
});
describe('glTabs', () => {
beforeEach(() => {
createComponent();
});
it('passes the `sync-active-tab-with-query-params` prop', () => {
expect(findGlTabs().props('syncActiveTabWithQueryParams')).toBe(true);
});
});
2022-05-07 20:08:51 +05:30
describe('pipeline editor walkthrough', () => {
describe('when isNewCiConfigFile prop is true (default)', () => {
2022-08-27 11:52:29 +05:30
beforeEach(() => {
createComponent();
2021-12-11 22:18:48 +05:30
});
2022-05-07 20:08:51 +05:30
it('shows walkthrough popover', async () => {
expect(findWalkthroughPopover().exists()).toBe(true);
2021-12-11 22:18:48 +05:30
});
2022-05-07 20:08:51 +05:30
});
2021-12-11 22:18:48 +05:30
2022-05-07 20:08:51 +05:30
describe('when isNewCiConfigFile prop is false', () => {
it('does not show walkthrough popover', async () => {
2022-08-27 11:52:29 +05:30
createComponent({ props: { isNewCiConfigFile: false } });
2022-05-07 20:08:51 +05:30
expect(findWalkthroughPopover().exists()).toBe(false);
2021-12-11 22:18:48 +05:30
});
});
});
it('sets listeners on walkthrough popover', async () => {
const handler = jest.fn();
createComponent({
listeners: {
event: handler,
},
});
await nextTick();
findWalkthroughPopover().vm.$emit('event');
expect(handler).toHaveBeenCalled();
});
2021-03-11 19:13:27 +05:30
});