Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 16:16:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 16:16:36 +0300
commit311b0269b4eb9839fa63f80c8d7a58f32b8138a0 (patch)
tree07e7870bca8aed6d61fdcc810731c50d2c40af47 /spec/frontend/pipeline_editor/components
parent27909cef6c4170ed9205afa7426b8d3de47cbb0c (diff)
Add latest changes from gitlab-org/gitlab@14-5-stable-eev14.5.0-rc42
Diffstat (limited to 'spec/frontend/pipeline_editor/components')
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js19
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js16
-rw-r--r--spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js37
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js38
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js39
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js72
-rw-r--r--spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js132
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js29
9 files changed, 341 insertions, 43 deletions
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
index 8040c9d701c..23219042008 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -5,6 +5,9 @@ import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import { mockCommitMessage, mockDefaultBranch } from '../../mock_data';
+const scrollIntoViewMock = jest.fn();
+HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
describe('Pipeline Editor | Commit Form', () => {
let wrapper;
@@ -113,4 +116,20 @@ describe('Pipeline Editor | Commit Form', () => {
expect(findSubmitBtn().attributes('disabled')).toBe('disabled');
});
});
+
+ describe('when scrollToCommitForm becomes true', () => {
+ beforeEach(async () => {
+ createComponent();
+ wrapper.setProps({ scrollToCommitForm: true });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('scrolls into view', () => {
+ expect(scrollIntoViewMock).toHaveBeenCalledWith({ behavior: 'smooth' });
+ });
+
+ it('emits "scrolled-to-commit-form"', () => {
+ expect(wrapper.emitted()['scrolled-to-commit-form']).toBeTruthy();
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
index 2f934898ef1..efc345d8877 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -52,6 +52,7 @@ describe('Pipeline Editor | Commit section', () => {
const defaultProps = {
ciFileContent: mockCiYml,
commitSha: mockCommitSha,
+ isNewCiConfigFile: false,
};
const createComponent = ({ props = {}, options = {}, provide = {} } = {}) => {
@@ -72,7 +73,6 @@ describe('Pipeline Editor | Commit section', () => {
data() {
return {
currentBranch: mockDefaultBranch,
- isNewCiConfigFile: Boolean(options?.isNewCiConfigfile),
};
},
mocks: {
@@ -115,7 +115,7 @@ describe('Pipeline Editor | Commit section', () => {
describe('when the user commits a new file', () => {
beforeEach(async () => {
- createComponent({ options: { isNewCiConfigfile: true } });
+ createComponent({ props: { isNewCiConfigFile: true } });
await submitCommit();
});
@@ -277,4 +277,16 @@ describe('Pipeline Editor | Commit section', () => {
expect(wrapper.emitted('resetContent')).toHaveLength(1);
});
});
+
+ it('sets listeners on commit form', () => {
+ const handler = jest.fn();
+ createComponent({ options: { listeners: { event: handler } } });
+ findCommitForm().vm.$emit('event');
+ expect(handler).toHaveBeenCalled();
+ });
+
+ it('passes down scroll-to-commit-form prop to commit form', () => {
+ createComponent({ props: { 'scroll-to-commit-form': true } });
+ expect(findCommitForm().props('scrollToCommitForm')).toBe(true);
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js b/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
index 1b68cd3dc43..4df7768b035 100644
--- a/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
+++ b/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { stubExperiments } from 'helpers/experimentation_helper';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import FirstPipelineCard from '~/pipeline_editor/components/drawer/cards/first_pipeline_card.vue';
import GettingStartedCard from '~/pipeline_editor/components/drawer/cards/getting_started_card.vue';
@@ -33,19 +34,41 @@ describe('Pipeline editor drawer', () => {
const clickToggleBtn = async () => findToggleBtn().vm.$emit('click');
+ const originalObjects = [];
+
+ beforeEach(() => {
+ originalObjects.push(window.gon, window.gl);
+ stubExperiments({ pipeline_editor_walkthrough: 'control' });
+ });
+
afterEach(() => {
wrapper.destroy();
localStorage.clear();
+ [window.gon, window.gl] = originalObjects;
});
- it('it sets the drawer to be opened by default', async () => {
- createComponent();
-
- expect(findDrawerContent().exists()).toBe(false);
-
- await nextTick();
+ describe('default expanded state', () => {
+ describe('when experiment control', () => {
+ it('sets the drawer to be opened by default', async () => {
+ createComponent();
+ expect(findDrawerContent().exists()).toBe(false);
+ await nextTick();
+ expect(findDrawerContent().exists()).toBe(true);
+ });
+ });
- expect(findDrawerContent().exists()).toBe(true);
+ describe('when experiment candidate', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+ });
+
+ it('sets the drawer to be closed by default', async () => {
+ createComponent();
+ expect(findDrawerContent().exists()).toBe(false);
+ await nextTick();
+ expect(findDrawerContent().exists()).toBe(false);
+ });
+ });
});
describe('when the drawer is collapsed', () => {
diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
index b5881790b0b..6532c4e289d 100644
--- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -36,8 +36,9 @@ describe('Pipeline editor branch switcher', () => {
let mockLastCommitBranchQuery;
const createComponent = (
- { currentBranch, isQueryLoading, mountFn, options } = {
+ { currentBranch, isQueryLoading, mountFn, options, props } = {
currentBranch: mockDefaultBranch,
+ hasUnsavedChanges: false,
isQueryLoading: false,
mountFn: shallowMount,
options: {},
@@ -45,6 +46,7 @@ describe('Pipeline editor branch switcher', () => {
) => {
wrapper = mountFn(BranchSwitcher, {
propsData: {
+ ...props,
paginationLimit: mockBranchPaginationLimit,
},
provide: {
@@ -70,7 +72,7 @@ describe('Pipeline editor branch switcher', () => {
});
};
- const createComponentWithApollo = (mountFn = shallowMount) => {
+ const createComponentWithApollo = ({ mountFn = shallowMount, props = {} } = {}) => {
const handlers = [[getAvailableBranchesQuery, mockAvailableBranchQuery]];
const resolvers = {
Query: {
@@ -86,6 +88,7 @@ describe('Pipeline editor branch switcher', () => {
createComponent({
mountFn,
+ props,
options: {
localVue,
apolloProvider: mockApollo,
@@ -138,8 +141,8 @@ describe('Pipeline editor branch switcher', () => {
createComponentWithApollo();
});
- it('does not render dropdown', () => {
- expect(findDropdown().exists()).toBe(false);
+ it('disables the dropdown', () => {
+ expect(findDropdown().props('disabled')).toBe(true);
});
});
@@ -149,7 +152,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -186,7 +189,7 @@ describe('Pipeline editor branch switcher', () => {
});
it('does not render dropdown', () => {
- expect(findDropdown().exists()).toBe(false);
+ expect(findDropdown().props('disabled')).toBe(true);
});
it('shows an error message', () => {
@@ -201,7 +204,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -247,6 +250,23 @@ describe('Pipeline editor branch switcher', () => {
expect(wrapper.emitted('refetchContent')).toBeUndefined();
});
+
+ describe('with unsaved changes', () => {
+ beforeEach(async () => {
+ createComponentWithApollo({ mountFn: mount, props: { hasUnsavedChanges: true } });
+ await waitForPromises();
+ });
+
+ it('emits `select-branch` event and does not switch branch', async () => {
+ expect(wrapper.emitted('select-branch')).toBeUndefined();
+
+ const branch = findDropdownItems().at(1);
+ await branch.vm.$emit('click');
+
+ expect(wrapper.emitted('select-branch')).toEqual([[branch.text()]]);
+ expect(wrapper.emitted('refetchContent')).toBeUndefined();
+ });
+ });
});
describe('when searching', () => {
@@ -255,7 +275,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -429,7 +449,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
await createNewBranch();
});
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 44656b2b67d..29ab52bde8f 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -16,7 +16,7 @@ describe('Pipeline Status', () => {
let mockApollo;
let mockPipelineQuery;
- const createComponentWithApollo = (glFeatures = {}) => {
+ const createComponentWithApollo = () => {
const handlers = [[getPipelineQuery, mockPipelineQuery]];
mockApollo = createMockApollo(handlers);
@@ -27,7 +27,6 @@ describe('Pipeline Status', () => {
commitSha: mockCommitSha,
},
provide: {
- glFeatures,
projectFullPath: mockProjectFullPath,
},
stubs: { GlLink, GlSprintf },
@@ -40,6 +39,8 @@ describe('Pipeline Status', () => {
const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]');
const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]');
const findPipelineErrorMsg = () => wrapper.find('[data-testid="pipeline-error-msg"]');
+ const findPipelineNotTriggeredErrorMsg = () =>
+ wrapper.find('[data-testid="pipeline-not-triggered-error-msg"]');
const findPipelineLoadingMsg = () => wrapper.find('[data-testid="pipeline-loading-msg"]');
const findPipelineViewBtn = () => wrapper.find('[data-testid="pipeline-view-btn"]');
const findStatusIcon = () => wrapper.find('[data-testid="pipeline-status-icon"]');
@@ -95,17 +96,18 @@ describe('Pipeline Status', () => {
it('renders pipeline data', () => {
const {
id,
+ commit: { title },
detailedStatus: { detailsPath },
} = mockProjectPipeline().pipeline;
expect(findStatusIcon().exists()).toBe(true);
expect(findPipelineId().text()).toBe(`#${id.match(/\d+/g)[0]}`);
- expect(findPipelineCommit().text()).toBe(mockCommitSha);
+ expect(findPipelineCommit().text()).toBe(`${mockCommitSha}: ${title}`);
expect(findPipelineViewBtn().attributes('href')).toBe(detailsPath);
});
- it('does not render the pipeline mini graph', () => {
- expect(findPipelineEditorMiniGraph().exists()).toBe(false);
+ it('renders the pipeline mini graph', () => {
+ expect(findPipelineEditorMiniGraph().exists()).toBe(true);
});
});
@@ -117,7 +119,8 @@ describe('Pipeline Status', () => {
await waitForPromises();
});
- it('renders error', () => {
+ it('renders api error', () => {
+ expect(findPipelineNotTriggeredErrorMsg().exists()).toBe(false);
expect(findIcon().attributes('name')).toBe('warning-solid');
expect(findPipelineErrorMsg().text()).toBe(i18n.fetchError);
});
@@ -129,20 +132,22 @@ describe('Pipeline Status', () => {
expect(findPipelineViewBtn().exists()).toBe(false);
});
});
- });
- describe('when feature flag for pipeline mini graph is enabled', () => {
- beforeEach(() => {
- mockPipelineQuery.mockResolvedValue({
- data: { project: mockProjectPipeline() },
- });
+ describe('when pipeline is null', () => {
+ beforeEach(() => {
+ mockPipelineQuery.mockResolvedValue({
+ data: { project: { pipeline: null } },
+ });
- createComponentWithApollo({ pipelineEditorMiniGraph: true });
- waitForPromises();
- });
+ createComponentWithApollo();
+ waitForPromises();
+ });
- it('renders the pipeline mini graph', () => {
- expect(findPipelineEditorMiniGraph().exists()).toBe(true);
+ it('renders pipeline not triggered error', () => {
+ expect(findPipelineErrorMsg().exists()).toBe(false);
+ expect(findIcon().attributes('name')).toBe('information-o');
+ expect(findPipelineNotTriggeredErrorMsg().text()).toBe(i18n.pipelineNotTriggeredMsg);
+ });
});
});
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
index 3d7c3c839da..6b9f576917f 100644
--- a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
@@ -1,22 +1,54 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
-import { mockProjectPipeline } from '../../mock_data';
+import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
+import { PIPELINE_FAILURE } from '~/pipeline_editor/constants';
+import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
describe('Pipeline Status', () => {
let wrapper;
+ let mockApollo;
+ let mockLinkedPipelinesQuery;
- const createComponent = ({ hasStages = true } = {}) => {
+ const createComponent = ({ hasStages = true, options } = {}) => {
wrapper = shallowMount(PipelineEditorMiniGraph, {
+ provide: {
+ dataMethod: 'graphql',
+ projectFullPath: mockProjectFullPath,
+ },
propsData: {
pipeline: mockProjectPipeline({ hasStages }).pipeline,
},
+ ...options,
+ });
+ };
+
+ const createComponentWithApollo = (hasStages = true) => {
+ const handlers = [[getLinkedPipelinesQuery, mockLinkedPipelinesQuery]];
+ mockApollo = createMockApollo(handlers);
+
+ createComponent({
+ hasStages,
+ options: {
+ localVue,
+ apolloProvider: mockApollo,
+ },
});
};
const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ beforeEach(() => {
+ mockLinkedPipelinesQuery = jest.fn();
+ });
+
afterEach(() => {
+ mockLinkedPipelinesQuery.mockReset();
wrapper.destroy();
});
@@ -39,4 +71,38 @@ describe('Pipeline Status', () => {
expect(findPipelineMiniGraph().exists()).toBe(false);
});
});
+
+ describe('when querying upstream and downstream pipelines', () => {
+ describe('when query succeeds', () => {
+ beforeEach(() => {
+ mockLinkedPipelinesQuery.mockResolvedValue(mockLinkedPipelines());
+ createComponentWithApollo();
+ });
+
+ it('should call the query with the correct variables', () => {
+ expect(mockLinkedPipelinesQuery).toHaveBeenCalledTimes(1);
+ expect(mockLinkedPipelinesQuery).toHaveBeenCalledWith({
+ fullPath: mockProjectFullPath,
+ iid: mockProjectPipeline().pipeline.iid,
+ });
+ });
+ });
+
+ describe('when query fails', () => {
+ beforeEach(() => {
+ mockLinkedPipelinesQuery.mockRejectedValue(new Error());
+ createComponentWithApollo();
+ });
+
+ it('should emit an error event when query fails', async () => {
+ expect(wrapper.emitted('showError')).toHaveLength(1);
+ expect(wrapper.emitted('showError')[0]).toEqual([
+ {
+ type: PIPELINE_FAILURE,
+ reasons: [wrapper.vm.$options.i18n.linkedPipelinesFetchError],
+ },
+ ]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
index 5cf8d47bc23..f6154f50bc0 100644
--- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
+++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -1,19 +1,27 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import setWindowLocation from 'helpers/set_window_location_helper';
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
+import WalkthroughPopover from '~/pipeline_editor/components/walkthrough_popover.vue';
import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
+import { stubExperiments } from 'helpers/experimentation_helper';
import {
+ CREATE_TAB,
EDITOR_APP_STATUS_EMPTY,
- EDITOR_APP_STATUS_ERROR,
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_INVALID,
EDITOR_APP_STATUS_VALID,
+ MERGED_TAB,
+ TAB_QUERY_PARAM,
+ TABS_INDEX,
} from '~/pipeline_editor/constants';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-import { mockLintResponse, mockCiYml } from '../mock_data';
+import { mockLintResponse, mockLintResponseWithoutMerged, mockCiYml } from '../mock_data';
+
+Vue.config.ignoredElements = ['gl-emoji'];
describe('Pipeline editor tabs component', () => {
let wrapper;
@@ -22,6 +30,7 @@ describe('Pipeline editor tabs component', () => {
};
const createComponent = ({
+ listeners = {},
props = {},
provide = {},
appStatus = EDITOR_APP_STATUS_VALID,
@@ -31,6 +40,7 @@ describe('Pipeline editor tabs component', () => {
propsData: {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
+ isNewCiConfigFile: true,
...props,
},
data() {
@@ -43,6 +53,7 @@ describe('Pipeline editor tabs component', () => {
TextEditor: MockTextEditor,
EditorTab,
},
+ listeners,
});
};
@@ -53,10 +64,12 @@ describe('Pipeline editor tabs component', () => {
const findAlert = () => wrapper.findComponent(GlAlert);
const findCiLint = () => wrapper.findComponent(CiLint);
+ const findGlTabs = () => wrapper.findComponent(GlTabs);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPipelineGraph = () => wrapper.findComponent(PipelineGraph);
const findTextEditor = () => wrapper.findComponent(MockTextEditor);
const findMergedPreview = () => wrapper.findComponent(CiConfigMergedPreview);
+ const findWalkthroughPopover = () => wrapper.findComponent(WalkthroughPopover);
afterEach(() => {
wrapper.destroy();
@@ -137,7 +150,7 @@ describe('Pipeline editor tabs component', () => {
describe('when there is a fetch error', () => {
beforeEach(() => {
- createComponent({ appStatus: EDITOR_APP_STATUS_ERROR });
+ createComponent({ props: { ciConfigData: mockLintResponseWithoutMerged } });
});
it('show an error message', () => {
@@ -181,4 +194,113 @@ describe('Pipeline editor tabs component', () => {
},
);
});
+
+ 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}`,
+ });
+ });
+
+ it('is the tab specified in query param and transform it into an index value', async () => {
+ setWindowLocation(`${gitlabUrl}?${TAB_QUERY_PARAM}=${MERGED_TAB}`);
+ createComponent();
+
+ // If the query param has changed to an index, it means we have synced the
+ // query with.
+ expect(window.location).toMatchObject({
+ ...matchObject,
+ search: `?${TAB_QUERY_PARAM}=${TABS_INDEX[MERGED_TAB]}`,
+ });
+ });
+ });
+
+ describe('glTabs', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('passes the `sync-active-tab-with-query-params` prop', () => {
+ expect(findGlTabs().props('syncActiveTabWithQueryParams')).toBe(true);
+ });
+ });
+
+ describe('pipeline_editor_walkthrough experiment', () => {
+ describe('when in control path', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'control' });
+ });
+
+ it('does not show walkthrough popover', async () => {
+ createComponent({ mountFn: mount });
+ await nextTick();
+ expect(findWalkthroughPopover().exists()).toBe(false);
+ });
+ });
+
+ describe('when in candidate path', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+ });
+
+ describe('when isNewCiConfigFile prop is true (default)', () => {
+ beforeEach(async () => {
+ createComponent({
+ mountFn: mount,
+ });
+ await nextTick();
+ });
+
+ it('shows walkthrough popover', async () => {
+ expect(findWalkthroughPopover().exists()).toBe(true);
+ });
+ });
+
+ describe('when isNewCiConfigFile prop is false', () => {
+ it('does not show walkthrough popover', async () => {
+ createComponent({ props: { isNewCiConfigFile: false }, mountFn: mount });
+ await nextTick();
+ expect(findWalkthroughPopover().exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ it('sets listeners on walkthrough popover', async () => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+
+ const handler = jest.fn();
+
+ createComponent({
+ mountFn: mount,
+ listeners: {
+ event: handler,
+ },
+ });
+ await nextTick();
+
+ findWalkthroughPopover().vm.$emit('event');
+
+ expect(handler).toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
index 9f910ed4f9c..a55176ccd79 100644
--- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
@@ -11,6 +11,7 @@ import {
DEFAULT_FAILURE,
DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN,
+ PIPELINE_FAILURE,
} from '~/pipeline_editor/constants';
beforeEach(() => {
@@ -65,6 +66,7 @@ describe('Pipeline Editor messages', () => {
failureType | message | expectedFailureType
${COMMIT_FAILURE} | ${'failed commit'} | ${COMMIT_FAILURE}
${LOAD_FAILURE_UNKNOWN} | ${'loading failure'} | ${LOAD_FAILURE_UNKNOWN}
+ ${PIPELINE_FAILURE} | ${'pipeline failure'} | ${PIPELINE_FAILURE}
${'random'} | ${'error without a specified type'} | ${DEFAULT_FAILURE}
`('shows a message for $message', ({ failureType, expectedFailureType }) => {
createComponent({ failureType, showFailure: true });
diff --git a/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js b/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js
new file mode 100644
index 00000000000..a9ce89ff521
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js
@@ -0,0 +1,29 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import WalkthroughPopover from '~/pipeline_editor/components/walkthrough_popover.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+Vue.config.ignoredElements = ['gl-emoji'];
+
+describe('WalkthroughPopover component', () => {
+ let wrapper;
+
+ const createComponent = (mountFn = shallowMount) => {
+ return extendedWrapper(mountFn(WalkthroughPopover));
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('CTA button clicked', () => {
+ beforeEach(async () => {
+ wrapper = createComponent(mount);
+ await wrapper.findByTestId('ctaBtn').trigger('click');
+ });
+
+ it('emits "walkthrough-popover-cta-clicked" event', async () => {
+ expect(wrapper.emitted()['walkthrough-popover-cta-clicked']).toBeTruthy();
+ });
+ });
+});