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-04-21 02:50:22 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-21 02:50:22 +0300
commit9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch)
tree70467ae3692a0e35e5ea56bcb803eb512a10bedb /spec/frontend/projects
parent4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff)
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'spec/frontend/projects')
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js6
-rw-r--r--spec/frontend/projects/commit/components/commit_comments_button_spec.js42
-rw-r--r--spec/frontend/projects/commit/components/commit_options_dropdown_spec.js123
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js11
-rw-r--r--spec/frontend/projects/commit/components/form_trigger_spec.js44
-rw-r--r--spec/frontend/projects/commit/mock_data.js2
-rw-r--r--spec/frontend/projects/commit/store/mutations_spec.js6
-rw-r--r--spec/frontend/projects/commit_box/info/load_branches_spec.js41
-rw-r--r--spec/frontend/projects/compare/components/app_legacy_spec.js55
-rw-r--r--spec/frontend/projects/compare/components/repo_dropdown_spec.js22
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js25
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js41
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js52
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js31
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap6
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js57
16 files changed, 440 insertions, 124 deletions
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
index 7686c28c7fc..ab84c3768d0 100644
--- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -15,7 +15,7 @@ describe('BranchesDropdown', () => {
const createComponent = (term, state = { isFetching: false }) => {
store = new Vuex.Store({
getters: {
- joinedBranches: () => ['_master_', '_branch_1_', '_branch_2_'],
+ joinedBranches: () => ['_main_', '_branch_1_', '_branch_2_'],
},
actions: {
fetchBranches: spyFetchBranches,
@@ -94,13 +94,13 @@ describe('BranchesDropdown', () => {
it('renders all branches when search term is empty', () => {
expect(findAllDropdownItems()).toHaveLength(3);
- expect(findDropdownItemByIndex(0).text()).toBe('_master_');
+ expect(findDropdownItemByIndex(0).text()).toBe('_main_');
expect(findDropdownItemByIndex(1).text()).toBe('_branch_1_');
expect(findDropdownItemByIndex(2).text()).toBe('_branch_2_');
});
it('should not be selected on the inactive branch', () => {
- expect(wrapper.vm.isSelected('_master_')).toBe(false);
+ expect(wrapper.vm.isSelected('_main_')).toBe(false);
});
});
diff --git a/spec/frontend/projects/commit/components/commit_comments_button_spec.js b/spec/frontend/projects/commit/components/commit_comments_button_spec.js
new file mode 100644
index 00000000000..873270c5be1
--- /dev/null
+++ b/spec/frontend/projects/commit/components/commit_comments_button_spec.js
@@ -0,0 +1,42 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitCommentsButton from '~/projects/commit/components/commit_comments_button.vue';
+
+describe('CommitCommentsButton', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitCommentsButton, {
+ propsData: {
+ commentsCount: 1,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const tooltip = () => wrapper.findByTestId('comment-button-wrapper');
+
+ describe('Comment Button', () => {
+ it('has proper tooltip and button attributes for 1 comment', () => {
+ createComponent();
+
+ expect(tooltip().attributes('title')).toBe('1 comment on this commit');
+ expect(tooltip().text()).toBe('1');
+ });
+
+ it('has proper tooltip and button attributes for multiple comments', () => {
+ createComponent({ commentsCount: 2 });
+
+ expect(tooltip().attributes('title')).toBe('2 comments on this commit');
+ expect(tooltip().text()).toBe('2');
+ });
+
+ it('does not show when there are no comments', () => {
+ createComponent({ commentsCount: 0 });
+
+ expect(tooltip().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js
new file mode 100644
index 00000000000..70491405986
--- /dev/null
+++ b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js
@@ -0,0 +1,123 @@
+import { GlDropdownDivider, GlDropdownSectionHeader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitOptionsDropdown from '~/projects/commit/components/commit_options_dropdown.vue';
+import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
+import eventHub from '~/projects/commit/event_hub';
+
+describe('BranchesDropdown', () => {
+ let wrapper;
+ const provide = {
+ newProjectTagPath: '_new_project_tag_path_',
+ emailPatchesPath: '_email_patches_path_',
+ plainDiffPath: '_plain_diff_path_',
+ };
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitOptionsDropdown, {
+ provide,
+ propsData: {
+ canRevert: true,
+ canCherryPick: true,
+ canTag: true,
+ canEmailPatches: true,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findRevertLink = () => wrapper.findByTestId('revert-link');
+ const findCherryPickLink = () => wrapper.findByTestId('cherry-pick-link');
+ const findTagItem = () => wrapper.findByTestId('tag-link');
+ const findEmailPatchesItem = () => wrapper.findByTestId('email-patches-link');
+ const findPlainDiffItem = () => wrapper.findByTestId('plain-diff-link');
+ const findDivider = () => wrapper.findComponent(GlDropdownDivider);
+ const findSectionHeader = () => wrapper.findComponent(GlDropdownSectionHeader);
+
+ describe('Everything enabled', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('has expected dropdown button text', () => {
+ expect(wrapper.attributes('text')).toBe('Options');
+ });
+
+ it('has expected items', () => {
+ expect(
+ [
+ findRevertLink().exists(),
+ findCherryPickLink().exists(),
+ findTagItem().exists(),
+ findDivider().exists(),
+ findSectionHeader().exists(),
+ findEmailPatchesItem().exists(),
+ findPlainDiffItem().exists(),
+ ].every((exists) => exists),
+ ).toBe(true);
+ });
+
+ it('has expected href links', () => {
+ expect(findTagItem().attributes('href')).toBe(provide.newProjectTagPath);
+ expect(findEmailPatchesItem().attributes('href')).toBe(provide.emailPatchesPath);
+ expect(findPlainDiffItem().attributes('href')).toBe(provide.plainDiffPath);
+ });
+ });
+
+ describe('Different dropdown item permutations', () => {
+ it('does not have a revert option', () => {
+ createComponent({ canRevert: false });
+
+ expect(findRevertLink().exists()).toBe(false);
+ });
+
+ it('does not have a cherry-pick option', () => {
+ createComponent({ canCherryPick: false });
+
+ expect(findCherryPickLink().exists()).toBe(false);
+ });
+
+ it('does not have a tag option', () => {
+ createComponent({ canTag: false });
+
+ expect(findTagItem().exists()).toBe(false);
+ });
+
+ it('does not have a email patches options', () => {
+ createComponent({ canEmailPatches: false });
+
+ expect(findEmailPatchesItem().exists()).toBe(false);
+ });
+
+ it('only has the download items', () => {
+ createComponent({ canRevert: false, canCherryPick: false, canTag: false });
+
+ expect(findDivider().exists()).toBe(false);
+ expect(findEmailPatchesItem().exists()).toBe(true);
+ expect(findPlainDiffItem().exists()).toBe(true);
+ });
+ });
+
+ describe('Modal triggering', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(eventHub, '$emit');
+ createComponent();
+ });
+
+ it('emits openModal for revert', () => {
+ findRevertLink().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith(OPEN_REVERT_MODAL);
+ });
+
+ it('emits openModal for cherry-pick', () => {
+ findCherryPickLink().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith(OPEN_CHERRY_PICK_MODAL);
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 708644cb7ee..9688cb47799 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -17,15 +17,14 @@ describe('CommitFormModal', () => {
let store;
let axiosMock;
- const createComponent = (method, state = {}, provide = {}) => {
+ const createComponent = (method, state = {}, provide = {}, propsData = {}) => {
store = createStore({ ...mockData.mockModal, ...state });
wrapper = extendedWrapper(
method(CommitFormModal, {
provide: {
...provide,
- glFeatures: { pickIntoProject: true },
},
- propsData: { ...mockData.modalPropsData },
+ propsData: { ...mockData.modalPropsData, ...propsData },
store,
attrs: {
static: true,
@@ -160,6 +159,12 @@ describe('CommitFormModal', () => {
});
it('Changes the target_project_id input value', async () => {
+ createComponent(
+ shallowMount,
+ {},
+ { glFeatures: { pickIntoProject: true } },
+ { isCherryPick: true },
+ );
findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/projects/commit/components/form_trigger_spec.js b/spec/frontend/projects/commit/components/form_trigger_spec.js
deleted file mode 100644
index 4503493c0a6..00000000000
--- a/spec/frontend/projects/commit/components/form_trigger_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import FormTrigger from '~/projects/commit/components/form_trigger.vue';
-import eventHub from '~/projects/commit/event_hub';
-
-const displayText = '_display_text_';
-
-const createComponent = () => {
- return shallowMount(FormTrigger, {
- provide: { displayText },
- propsData: { openModal: '_open_modal_' },
- });
-};
-
-describe('FormTrigger', () => {
- let wrapper;
- let spy;
-
- beforeEach(() => {
- spy = jest.spyOn(eventHub, '$emit');
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findLink = () => wrapper.find(GlLink);
-
- describe('displayText', () => {
- it('includes the correct displayText for the link', () => {
- expect(findLink().text()).toBe(displayText);
- });
- });
-
- describe('clicking the link', () => {
- it('emits openModal', () => {
- findLink().vm.$emit('click');
-
- expect(spy).toHaveBeenCalledWith('_open_modal_');
- });
- });
-});
diff --git a/spec/frontend/projects/commit/mock_data.js b/spec/frontend/projects/commit/mock_data.js
index e4dcb24c4c0..34e9c400af4 100644
--- a/spec/frontend/projects/commit/mock_data.js
+++ b/spec/frontend/projects/commit/mock_data.js
@@ -23,6 +23,6 @@ export default {
modalId: '_modal_id_',
openModal: '_open_modal_',
},
- mockBranches: ['_branch_1', '_abc_', '_master_'],
+ mockBranches: ['_branch_1', '_abc_', '_main_'],
mockProjects: ['_project_1', '_abc_', '_project_'],
};
diff --git a/spec/frontend/projects/commit/store/mutations_spec.js b/spec/frontend/projects/commit/store/mutations_spec.js
index 8989e769772..60abf0fddad 100644
--- a/spec/frontend/projects/commit/store/mutations_spec.js
+++ b/spec/frontend/projects/commit/store/mutations_spec.js
@@ -27,7 +27,7 @@ describe('Commit form modal mutations', () => {
describe('CLEAR_MODAL', () => {
it('should clear modal state ', () => {
- stateCopy = { branch: '_master_', defaultBranch: '_default_branch_' };
+ stateCopy = { branch: '_main_', defaultBranch: '_default_branch_' };
mutations[types.CLEAR_MODAL](stateCopy);
@@ -47,7 +47,7 @@ describe('Commit form modal mutations', () => {
describe('SET_BRANCH', () => {
it('should set branch', () => {
- stateCopy = { branch: '_master_' };
+ stateCopy = { branch: '_main_' };
mutations[types.SET_BRANCH](stateCopy, '_changed_branch_');
@@ -57,7 +57,7 @@ describe('Commit form modal mutations', () => {
describe('SET_SELECTED_BRANCH', () => {
it('should set selectedBranch', () => {
- stateCopy = { selectedBranch: '_master_' };
+ stateCopy = { selectedBranch: '_main_' };
mutations[types.SET_SELECTED_BRANCH](stateCopy, '_changed_branch_');
diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js
index 8100200cbdd..9456e6ef5f5 100644
--- a/spec/frontend/projects/commit_box/info/load_branches_spec.js
+++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js
@@ -1,66 +1,73 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { setHTMLFixture } from 'helpers/fixtures';
import waitForPromises from 'helpers/wait_for_promises';
import { loadBranches } from '~/projects/commit_box/info/load_branches';
const mockCommitPath = '/commit/abcd/branches';
const mockBranchesRes =
- '<a href="/-/commits/master">master</a><span><a href="/-/commits/my-branch">my-branch</a></span>';
+ '<a href="/-/commits/main">main</a><span><a href="/-/commits/my-branch">my-branch</a></span>';
describe('~/projects/commit_box/info/load_branches', () => {
let mock;
- let el;
+
+ const getElInnerHtml = () => document.querySelector('.js-commit-box-info').innerHTML;
beforeEach(() => {
+ setHTMLFixture(`
+ <div class="js-commit-box-info" data-commit-path="${mockCommitPath}">
+ <div class="commit-info branches">
+ <span class="spinner"/>
+ </div>
+ </div>`);
+
mock = new MockAdapter(axios);
mock.onGet(mockCommitPath).reply(200, mockBranchesRes);
-
- el = document.createElement('div');
- el.dataset.commitPath = mockCommitPath;
- el.innerHTML = '<div class="commit-info branches"><span class="spinner"/></div>';
});
it('loads and renders branches info', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(`<div class="commit-info branches">${mockBranchesRes}</div>`);
+ expect(getElInnerHtml()).toMatchInterpolatedText(
+ `<div class="commit-info branches">${mockBranchesRes}</div>`,
+ );
});
it('does not load when no container is provided', async () => {
- loadBranches(null);
+ loadBranches('.js-another-class');
await waitForPromises();
expect(mock.history.get).toHaveLength(0);
});
- describe('when braches request returns unsafe content', () => {
+ describe('when branches request returns unsafe content', () => {
beforeEach(() => {
mock
.onGet(mockCommitPath)
- .reply(200, '<a onload="alert(\'xss!\');" href="/-/commits/master">master</a>');
+ .reply(200, '<a onload="alert(\'xss!\');" href="/-/commits/main">main</a>');
});
it('displays sanitized html', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(
- '<div class="commit-info branches"><a href="/-/commits/master">master</a></div>',
+ expect(getElInnerHtml()).toMatchInterpolatedText(
+ '<div class="commit-info branches"><a href="/-/commits/main">main</a></div>',
);
});
});
- describe('when braches request fails', () => {
+ describe('when branches request fails', () => {
beforeEach(() => {
mock.onGet(mockCommitPath).reply(500, 'Error!');
});
it('attempts to load and renders an error', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(
+ expect(getElInnerHtml()).toMatchInterpolatedText(
'<div class="commit-info branches">Failed to load branches. Please try again.</div>',
);
});
diff --git a/spec/frontend/projects/compare/components/app_legacy_spec.js b/spec/frontend/projects/compare/components/app_legacy_spec.js
index 4c7f0d5cccc..93e96c8b9f7 100644
--- a/spec/frontend/projects/compare/components/app_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/app_legacy_spec.js
@@ -8,7 +8,7 @@ jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
const projectCompareIndexPath = 'some/path';
const refsProjectPath = 'some/refs/path';
const paramsFrom = 'master';
-const paramsTo = 'master';
+const paramsTo = 'some-other-branch';
describe('CompareApp component', () => {
let wrapper;
@@ -36,6 +36,9 @@ describe('CompareApp component', () => {
createComponent();
});
+ const findSourceDropdown = () => wrapper.find('[data-testid="sourceRevisionDropdown"]');
+ const findTargetDropdown = () => wrapper.find('[data-testid="targetRevisionDropdown"]');
+
it('renders component with prop', () => {
expect(wrapper.props()).toEqual(
expect.objectContaining({
@@ -62,12 +65,31 @@ describe('CompareApp component', () => {
expect(wrapper.find('[data-testid="ellipsis"]').exists()).toBe(true);
});
- it('render Source and Target BranchDropdown components', () => {
- const branchDropdowns = wrapper.findAll(RevisionDropdown);
+ describe('Source and Target BranchDropdown components', () => {
+ const findAllBranchDropdowns = () => wrapper.findAll(RevisionDropdown);
+
+ it('renders the components with the correct props', () => {
+ expect(findAllBranchDropdowns().length).toBe(2);
+ expect(findSourceDropdown().props('revisionText')).toBe('Source');
+ expect(findTargetDropdown().props('revisionText')).toBe('Target');
+ });
+
+ it('sets the revision when the "selectRevision" event is emitted', async () => {
+ findSourceDropdown().vm.$emit('selectRevision', {
+ direction: 'to',
+ revision: 'some-source-revision',
+ });
+
+ findTargetDropdown().vm.$emit('selectRevision', {
+ direction: 'from',
+ revision: 'some-target-revision',
+ });
+
+ await wrapper.vm.$nextTick();
- expect(branchDropdowns.length).toBe(2);
- expect(branchDropdowns.at(0).props('revisionText')).toBe('Source');
- expect(branchDropdowns.at(1).props('revisionText')).toBe('Target');
+ expect(findTargetDropdown().props('paramsBranch')).toBe('some-target-revision');
+ expect(findSourceDropdown().props('paramsBranch')).toBe('some-source-revision');
+ });
});
describe('compare button', () => {
@@ -87,6 +109,27 @@ describe('CompareApp component', () => {
});
});
+ describe('swap revisions button', () => {
+ const findSwapRevisionsButton = () => wrapper.find('[data-testid="swapRevisionsButton"]');
+
+ it('renders the swap revisions button', () => {
+ expect(findSwapRevisionsButton().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ expect(findSwapRevisionsButton().text()).toBe('Swap revisions');
+ });
+
+ it('swaps revisions when clicked', async () => {
+ findSwapRevisionsButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTargetDropdown().props('paramsBranch')).toBe(paramsTo);
+ expect(findSourceDropdown().props('paramsBranch')).toBe(paramsFrom);
+ });
+ });
+
describe('merge request buttons', () => {
const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
index af76632515c..df8fea8fd32 100644
--- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RepoDropdown from '~/projects/compare/components/repo_dropdown.vue';
@@ -69,12 +69,12 @@ describe('RepoDropdown component', () => {
createComponent({ paramsName: 'from' });
});
- it('set hidden input of the first project', () => {
- expect(findHiddenInput().attributes('value')).toBe(projectFromId);
+ it('set hidden input of the selected project', () => {
+ expect(findHiddenInput().attributes('value')).toBe(projectToId);
});
- it('displays the first project name initially in the dropdown', () => {
- expect(findGlDropdown().props('text')).toBe(projectFromName);
+ it('displays matching project name of the source revision initially in the dropdown', () => {
+ expect(findGlDropdown().props('text')).toBe(projectToName);
});
it('updates the hiddin input value when onClick method is triggered', async () => {
@@ -84,15 +84,13 @@ describe('RepoDropdown component', () => {
expect(findHiddenInput().attributes('value')).toBe(repoId);
});
- it('emits initial `changeTargetProject` event with target project', () => {
- expect(wrapper.emitted('changeTargetProject')).toEqual([[projectFromName]]);
- });
-
it('emits `changeTargetProject` event when another target project is selected', async () => {
- const newTargetProject = 'new-from-name';
- wrapper.vm.$emit('changeTargetProject', newTargetProject);
+ const index = 1;
+ const { projectsFrom } = defaultProvide;
+ findGlDropdown().findAll(GlDropdownItem).at(index).vm.$emit('click');
await wrapper.vm.$nextTick();
- expect(wrapper.emitted('changeTargetProject')[1]).toEqual([newTargetProject]);
+
+ expect(wrapper.emitted('changeTargetProject')[0][0]).toEqual(projectsFrom[index].name);
});
});
});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
index 270c89e674c..ca208395e82 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@@ -29,6 +29,7 @@ describe('RevisionDropdown component', () => {
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
+ createComponent();
});
afterEach(() => {
@@ -39,7 +40,6 @@ describe('RevisionDropdown component', () => {
const findGlDropdown = () => wrapper.find(GlDropdown);
it('sets hidden input', () => {
- createComponent();
expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe(
defaultProps.paramsBranch,
);
@@ -68,8 +68,6 @@ describe('RevisionDropdown component', () => {
Tags: undefined,
});
- createComponent();
-
await axios.waitForAll();
expect(wrapper.vm.branches).toEqual([]);
@@ -79,15 +77,12 @@ describe('RevisionDropdown component', () => {
it('shows flash message on error', async () => {
axiosMock.onGet('some/invalid/path').replyOnce(404);
- createComponent();
-
await wrapper.vm.fetchBranchesAndTags();
expect(createFlash).toHaveBeenCalled();
});
describe('GlDropdown component', () => {
it('renders props', () => {
- createComponent();
expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps));
});
@@ -99,8 +94,22 @@ describe('RevisionDropdown component', () => {
});
it('display params branch text', () => {
- createComponent();
expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch);
});
+
+ it('emits a "selectRevision" event when a revision is selected', async () => {
+ const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
+
+ wrapper.setData({ branches: ['some-branch'] });
+
+ await wrapper.vm.$nextTick();
+
+ findFirstGlDropdownItem().vm.$emit('click');
+
+ expect(wrapper.emitted()).toEqual({
+ selectRevision: [[{ direction: 'from', revision: 'some-branch' }]],
+ });
+ });
});
});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
index 69d3167c99c..aab9607ceae 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@@ -23,6 +23,10 @@ describe('RevisionDropdown component', () => {
...defaultProps,
...props,
},
+ stubs: {
+ GlDropdown,
+ GlSearchBoxByType,
+ },
});
};
@@ -36,6 +40,7 @@ describe('RevisionDropdown component', () => {
});
const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
it('sets hidden input', () => {
createComponent();
@@ -85,6 +90,40 @@ describe('RevisionDropdown component', () => {
expect(axios.get).toHaveBeenLastCalledWith(newRefsProjectPath);
});
+ describe('search', () => {
+ it('shows flash message on error', async () => {
+ axiosMock.onGet('some/invalid/path').replyOnce(404);
+
+ createComponent();
+
+ await wrapper.vm.searchBranchesAndTags();
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('makes request with search param', async () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: {
+ Branches: [],
+ Tags: [],
+ },
+ });
+
+ const mockSearchTerm = 'foobar';
+ createComponent();
+ findSearchBox().vm.$emit('input', mockSearchTerm);
+ await axios.waitForAll();
+
+ expect(axios.get).toHaveBeenCalledWith(
+ defaultProps.refsProjectPath,
+ expect.objectContaining({
+ params: {
+ search: mockSearchTerm,
+ },
+ }),
+ );
+ });
+ });
+
describe('GlDropdown component', () => {
it('renders props', () => {
createComponent();
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
index b4ae50341d4..204e7a7c394 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlBreadcrumb } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { assignGitlabExperiment } from 'helpers/experimentation_helper';
import App from '~/projects/experiment_new_project_creation/components/app.vue';
import LegacyContainer from '~/projects/experiment_new_project_creation/components/legacy_container.vue';
import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
@@ -17,6 +18,57 @@ describe('Experimental new project creation app', () => {
wrapper = null;
});
+ const findWelcomePage = () => wrapper.findComponent(WelcomePage);
+ const findPanel = (panelName) =>
+ findWelcomePage()
+ .props()
+ .panels.find((p) => p.name === panelName);
+ const findPanelHeader = () => wrapper.find('h4');
+
+ describe('new_repo experiment', () => {
+ describe('when in the candidate variant', () => {
+ assignGitlabExperiment('new_repo', 'candidate');
+
+ it('has "repository" in the panel title', () => {
+ createComponent();
+
+ expect(findPanel('blank_project').title).toBe('Create blank project/repository');
+ });
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project/repository"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project/repository');
+ });
+ });
+ });
+
+ describe('when in the control variant', () => {
+ assignGitlabExperiment('new_repo', 'control');
+
+ it('has "project" in the panel title', () => {
+ createComponent();
+
+ expect(findPanel('blank_project').title).toBe('Create blank project');
+ });
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project');
+ });
+ });
+ });
+ });
+
describe('with empty hash', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
index f26d1a6d2a3..9fd1230806e 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
@@ -1,8 +1,13 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { mockTracking } from 'helpers/tracking_helper';
+import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
+import { getExperimentData } from '~/experimentation/utils';
import NewProjectPushTipPopover from '~/projects/experiment_new_project_creation/components/new_project_push_tip_popover.vue';
import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
+jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
+
describe('Welcome page', () => {
let wrapper;
let trackingSpy;
@@ -14,6 +19,7 @@ describe('Welcome page', () => {
beforeEach(() => {
trackingSpy = mockTracking('_category_', document, jest.spyOn);
trackingSpy.mockImplementation(() => {});
+ getExperimentData.mockReturnValue(undefined);
});
afterEach(() => {
@@ -22,14 +28,35 @@ describe('Welcome page', () => {
wrapper = null;
});
- it('tracks link clicks', () => {
+ it('tracks link clicks', async () => {
createComponent({ panels: [{ name: 'test', href: '#' }] });
- wrapper.find('a').trigger('click');
+ const link = wrapper.find('a');
+ link.trigger('click');
+ await nextTick();
return wrapper.vm.$nextTick().then(() => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
});
});
+ it('adds new_repo experiment data if in experiment', async () => {
+ const mockExperimentData = 'data';
+ getExperimentData.mockReturnValue(mockExperimentData);
+
+ createComponent({ panels: [{ name: 'test', href: '#' }] });
+ const link = wrapper.find('a');
+ link.trigger('click');
+ await nextTick();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
+ label: 'test',
+ context: {
+ data: mockExperimentData,
+ schema: TRACKING_CONTEXT_SCHEMA,
+ },
+ });
+ });
+ });
+
it('renders new project push tip popover', () => {
createComponent({ panels: [{ name: 'test', href: '#' }] });
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
index fc51825f15b..c37f6415898 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
@@ -21,7 +21,11 @@ exports[`CiCdAnalyticsAreaChart matches the snapshot 1`] = `
option="[object Object]"
thresholds=""
width="0"
- />
+ >
+ <template />
+
+ <template />
+ </glareachart-stub>
</div>
</div>
`;
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index e8aace14db4..0cf05d4ac37 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -10,6 +10,7 @@ import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_char
jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
+const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -21,10 +22,11 @@ describe('ProjectsPipelinesChartsApp', () => {
{},
{
provide: {
- shouldRenderDeploymentFrequencyCharts: false,
+ shouldRenderDoraCharts: true,
},
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
+ LeadTimeCharts: LeadTimeChartsStub,
},
},
mountOptions,
@@ -32,37 +34,42 @@ describe('ProjectsPipelinesChartsApp', () => {
);
}
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
const findGlTabs = () => wrapper.find(GlTabs);
- const findAllGlTab = () => wrapper.findAll(GlTab);
- const findGlTabAt = (i) => findAllGlTab().at(i);
+ const findAllGlTabs = () => wrapper.findAll(GlTab);
+ const findGlTabAtIndex = (index) => findAllGlTabs().at(index);
+ const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts);
- it('renders the pipeline charts', () => {
- expect(findPipelineCharts().exists()).toBe(true);
- });
-
- describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
+ describe('when all charts are available', () => {
beforeEach(() => {
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
});
- it('renders the deployment frequency charts in a tab', () => {
+ it('renders tabs', () => {
expect(findGlTabs().exists()).toBe(true);
- expect(findGlTabAt(0).attributes('title')).toBe('Pipelines');
- expect(findGlTabAt(1).attributes('title')).toBe('Deployments');
+
+ expect(findGlTabAtIndex(0).attributes('title')).toBe('Pipelines');
+ expect(findGlTabAtIndex(1).attributes('title')).toBe('Deployments');
+ expect(findGlTabAtIndex(2).attributes('title')).toBe('Lead Time');
+ });
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
+ });
+
+ it('renders the deployment frequency charts', () => {
expect(findDeploymentFrequencyCharts().exists()).toBe(true);
});
+ it('renders the lead time charts', () => {
+ expect(findLeadTimeCharts().exists()).toBe(true);
+ });
+
it('sets the tab and url when a tab is clicked', async () => {
let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
@@ -108,6 +115,7 @@ describe('ProjectsPipelinesChartsApp', () => {
describe('when provided with a query param', () => {
it.each`
chart | tab
+ ${'lead-time'} | ${'2'}
${'deployments'} | ${'1'}
${'pipelines'} | ${'0'}
${'fake'} | ${'0'}
@@ -118,7 +126,7 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(name).toBe('chart');
return chart ? [chart] : [];
});
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
expect(findGlTabs().attributes('value')).toBe(tab);
});
@@ -138,7 +146,7 @@ describe('ProjectsPipelinesChartsApp', () => {
return [];
});
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
expect(findGlTabs().attributes('value')).toBe('0');
@@ -155,14 +163,17 @@ describe('ProjectsPipelinesChartsApp', () => {
});
});
- describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
+ describe('when the dora charts are not available', () => {
beforeEach(() => {
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: false } });
+ createComponent({ provide: { shouldRenderDoraCharts: false } });
});
- it('does not render the deployment frequency charts in a tab', () => {
+ it('does not render tabs', () => {
expect(findGlTabs().exists()).toBe(false);
- expect(findDeploymentFrequencyCharts().exists()).toBe(false);
+ });
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
});
});
});