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>2023-03-21 15:08:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-21 15:08:46 +0300
commit7f521d27811b472c43203ed3d1bde4460a617f89 (patch)
tree47f1a10b776991e86c6db002bc6e03e83acc356a /spec/frontend
parent83e3316a189d3b709b23af30647b5f9ea5377bac (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js13
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js48
-rw-r--r--spec/frontend/diffs/components/diff_line_note_form_spec.js17
-rw-r--r--spec/frontend/lib/utils/error_message_spec.js102
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js3
-rw-r--r--spec/frontend/notes/components/note_body_spec.js8
-rw-r--r--spec/frontend/notes/components/note_form_spec.js108
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js26
-rw-r--r--spec/frontend/super_sidebar/components/context_switcher_spec.js14
-rw-r--r--spec/frontend/super_sidebar/components/search_results_spec.js16
-rw-r--r--spec/frontend/super_sidebar/mock_data.js1
-rw-r--r--spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js4
-rw-r--r--spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js19
13 files changed, 131 insertions, 248 deletions
diff --git a/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js b/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
index 694c16a85c4..66f1ca2b32a 100644
--- a/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
+++ b/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
@@ -19,7 +19,6 @@ describe('ManageTwoFactorForm', () => {
wrapper = mountExtended(ManageTwoFactorForm, {
provide: {
...defaultProvide,
- webauthnEnabled: options?.webauthnEnabled ?? false,
isCurrentPasswordRequired: options?.currentPasswordRequired ?? true,
},
stubs: {
@@ -91,17 +90,7 @@ describe('ManageTwoFactorForm', () => {
describe('when clicked', () => {
itShowsValidationMessageIfCurrentPasswordFieldIsEmpty(findDisableButton);
- itShowsConfirmationModal(i18n.confirm);
-
- describe('when webauthnEnabled', () => {
- beforeEach(() => {
- createComponent({
- webauthnEnabled: true,
- });
- });
-
- itShowsConfirmationModal(i18n.confirmWebAuthn);
- });
+ itShowsConfirmationModal(i18n.confirmWebAuthn);
it('modifies the form action and method when submitted through the button', async () => {
const form = findForm();
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index 2807fe7727f..3eb47fdb97e 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import DesignOverlay from '~/design_management/components/design_overlay.vue';
@@ -16,22 +16,20 @@ describe('Design overlay component', () => {
const mockDimensions = { width: 100, height: 100 };
- const findOverlay = () => wrapper.find('[data-testid="design-overlay"]');
- const findAllNotes = () => wrapper.findAll('[data-testid="note-pin"]');
- const findCommentBadge = () => wrapper.find('[data-testid="comment-badge"]');
+ const findOverlay = () => wrapper.findByTestId('design-overlay');
+ const findAllNotes = () => wrapper.findAllByTestId('note-pin');
+ const findCommentBadge = () => wrapper.findByTestId('comment-badge');
const findBadgeAtIndex = (noteIndex) => findAllNotes().at(noteIndex);
const findFirstBadge = () => findBadgeAtIndex(0);
const findSecondBadge = () => findBadgeAtIndex(1);
- const clickAndDragBadge = async (elem, fromPoint, toPoint) => {
+ const clickAndDragBadge = (elem, fromPoint, toPoint) => {
elem.vm.$emit(
'mousedown',
new MouseEvent('click', { clientX: fromPoint.x, clientY: fromPoint.y }),
);
findOverlay().trigger('mousemove', { clientX: toPoint.x, clientY: toPoint.y });
- await nextTick();
elem.vm.$emit('mouseup', new MouseEvent('click', { clientX: toPoint.x, clientY: toPoint.y }));
- await nextTick();
};
function createComponent(props = {}, data = {}) {
@@ -47,7 +45,7 @@ describe('Design overlay component', () => {
},
});
- wrapper = shallowMount(DesignOverlay, {
+ wrapper = shallowMountExtended(DesignOverlay, {
apolloProvider,
propsData: {
dimensions: mockDimensions,
@@ -80,7 +78,7 @@ describe('Design overlay component', () => {
expect(wrapper.attributes().style).toBe('width: 100px; height: 100px; top: 0px; left: 0px;');
});
- it('should emit `openCommentForm` when clicking on overlay', async () => {
+ it('should emit `openCommentForm` when clicking on overlay', () => {
createComponent();
const newCoordinates = {
x: 10,
@@ -90,7 +88,7 @@ describe('Design overlay component', () => {
wrapper
.find('[data-qa-selector="design_image_button"]')
.trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
- await nextTick();
+
expect(wrapper.emitted('openCommentForm')).toEqual([
[{ x: newCoordinates.x, y: newCoordinates.y }],
]);
@@ -175,25 +173,15 @@ describe('Design overlay component', () => {
});
});
- it('should recalculate badges positions on window resize', async () => {
+ it('should calculate badges positions based on dimensions', () => {
createComponent({
notes,
dimensions: {
- width: 400,
- height: 400,
- },
- });
-
- expect(findFirstBadge().props('position')).toEqual({ left: '40px', top: '60px' });
-
- wrapper.setProps({
- dimensions: {
width: 200,
height: 200,
},
});
- await nextTick();
expect(findFirstBadge().props('position')).toEqual({ left: '20px', top: '30px' });
});
@@ -216,7 +204,6 @@ describe('Design overlay component', () => {
new MouseEvent('click', { clientX: position.x, clientY: position.y }),
);
- await nextTick();
findFirstBadge().vm.$emit(
'mouseup',
new MouseEvent('click', { clientX: position.x, clientY: position.y }),
@@ -290,7 +277,7 @@ describe('Design overlay component', () => {
});
describe('when moving the comment badge', () => {
- it('should update badge style when note-moving action ends', async () => {
+ it('should update badge style when note-moving action ends', () => {
const { position } = notes[0];
createComponent({
currentCommentForm: {
@@ -298,19 +285,15 @@ describe('Design overlay component', () => {
},
});
- const commentBadge = findCommentBadge();
+ expect(findCommentBadge().props('position')).toEqual({ left: '10px', top: '15px' });
+
const toPoint = { x: 20, y: 20 };
- await clickAndDragBadge(commentBadge, { x: position.x, y: position.y }, toPoint);
- commentBadge.vm.$emit('mouseup', new MouseEvent('click'));
- // simulates the currentCommentForm being updated in index.vue component, and
- // propagated back down to this prop
- wrapper.setProps({
+ createComponent({
currentCommentForm: { height: position.height, width: position.width, ...toPoint },
});
- await nextTick();
- expect(commentBadge.props('position')).toEqual({ left: '20px', top: '20px' });
+ expect(findCommentBadge().props('position')).toEqual({ left: '20px', top: '20px' });
});
it('should emit `openCommentForm` event when mouseleave fired on overlay element', async () => {
@@ -330,8 +313,7 @@ describe('Design overlay component', () => {
newCoordinates,
);
- wrapper.trigger('mouseleave');
- await nextTick();
+ findOverlay().vm.$emit('mouseleave');
expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
});
diff --git a/spec/frontend/diffs/components/diff_line_note_form_spec.js b/spec/frontend/diffs/components/diff_line_note_form_spec.js
index bd0e3455872..eb895bd9057 100644
--- a/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
-import Autosave from '~/autosave';
import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
import { createModules } from '~/mr_notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
@@ -11,7 +10,6 @@ import { noteableDataMock } from 'jest/notes/mock_data';
import { getDiffFileMock } from '../mock_data/diff_file';
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
-jest.mock('~/autosave');
describe('DiffLineNoteForm', () => {
let wrapper;
@@ -77,7 +75,6 @@ describe('DiffLineNoteForm', () => {
const findCommentForm = () => wrapper.findComponent(MultilineCommentForm);
beforeEach(() => {
- Autosave.mockClear();
createComponent();
});
@@ -100,19 +97,6 @@ describe('DiffLineNoteForm', () => {
});
});
- it('should init autosave', () => {
- // we're using shallow mount here so there's no element to pass to Autosave
- expect(Autosave).toHaveBeenCalledWith(undefined, [
- 'Note',
- 'Issue',
- 98,
- undefined,
- 'DiffNote',
- undefined,
- '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
- ]);
- });
-
describe('when cancelling form', () => {
afterEach(() => {
confirmAction.mockReset();
@@ -146,7 +130,6 @@ describe('DiffLineNoteForm', () => {
await nextTick();
expect(getSelectedLine().hasForm).toBe(false);
- expect(Autosave.mock.instances[0].reset).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/lib/utils/error_message_spec.js b/spec/frontend/lib/utils/error_message_spec.js
index 17b5168c32f..54c630b8ba0 100644
--- a/spec/frontend/lib/utils/error_message_spec.js
+++ b/spec/frontend/lib/utils/error_message_spec.js
@@ -1,65 +1,43 @@
import { parseErrorMessage, USER_FACING_ERROR_MESSAGE_PREFIX } from '~/lib/utils/error_message';
-const defaultErrorMessage = 'Something caused this error';
-const userFacingErrorMessage = 'User facing error message';
-const nonUserFacingErrorMessage = 'NonUser facing error message';
-const genericErrorMessage = 'Some error message';
-
-describe('error message', () => {
- describe('when given an errormessage object', () => {
- const errorMessageObject = {
- options: {
- cause: defaultErrorMessage,
- },
- filename: 'error.js',
- linenumber: 7,
- };
-
- it('returns the correct values for userfacing errors', () => {
- const userFacingObject = errorMessageObject;
- userFacingObject.message = `${USER_FACING_ERROR_MESSAGE_PREFIX} ${userFacingErrorMessage}`;
-
- expect(parseErrorMessage(userFacingObject)).toEqual({
- message: userFacingErrorMessage,
- userFacing: true,
- });
- });
-
- it('returns the correct values for non userfacing errors', () => {
- const nonUserFacingObject = errorMessageObject;
- nonUserFacingObject.message = nonUserFacingErrorMessage;
-
- expect(parseErrorMessage(nonUserFacingObject)).toEqual({
- message: nonUserFacingErrorMessage,
- userFacing: false,
- });
- });
- });
-
- describe('when given an errormessage string', () => {
- it('returns the correct values for userfacing errors', () => {
- expect(
- parseErrorMessage(`${USER_FACING_ERROR_MESSAGE_PREFIX} ${genericErrorMessage}`),
- ).toEqual({
- message: genericErrorMessage,
- userFacing: true,
- });
- });
-
- it('returns the correct values for non userfacing errors', () => {
- expect(parseErrorMessage(genericErrorMessage)).toEqual({
- message: genericErrorMessage,
- userFacing: false,
- });
- });
- });
-
- describe('when given nothing', () => {
- it('returns an empty error message', () => {
- expect(parseErrorMessage()).toEqual({
- message: '',
- userFacing: false,
- });
- });
- });
+const defaultErrorMessage = 'Default error message';
+const errorMessage = 'Returned error message';
+
+const generateErrorWithMessage = (message) => {
+ return {
+ message,
+ };
+};
+
+describe('parseErrorMessage', () => {
+ it.each`
+ error | expectedResult
+ ${`${USER_FACING_ERROR_MESSAGE_PREFIX} ${errorMessage}`} | ${errorMessage}
+ ${`${errorMessage} ${USER_FACING_ERROR_MESSAGE_PREFIX}`} | ${defaultErrorMessage}
+ ${errorMessage} | ${defaultErrorMessage}
+ ${undefined} | ${defaultErrorMessage}
+ ${''} | ${defaultErrorMessage}
+ `(
+ 'properly parses "$error" error object and returns "$expectedResult"',
+ ({ error, expectedResult }) => {
+ const errorObject = generateErrorWithMessage(error);
+ expect(parseErrorMessage(errorObject, defaultErrorMessage)).toEqual(expectedResult);
+ },
+ );
+
+ it.each`
+ error | defaultMessage | expectedResult
+ ${undefined} | ${defaultErrorMessage} | ${defaultErrorMessage}
+ ${''} | ${defaultErrorMessage} | ${defaultErrorMessage}
+ ${{}} | ${defaultErrorMessage} | ${defaultErrorMessage}
+ ${generateErrorWithMessage(errorMessage)} | ${undefined} | ${''}
+ ${generateErrorWithMessage(`${USER_FACING_ERROR_MESSAGE_PREFIX} ${errorMessage}`)} | ${undefined} | ${errorMessage}
+ ${generateErrorWithMessage(errorMessage)} | ${''} | ${''}
+ ${generateErrorWithMessage(`${USER_FACING_ERROR_MESSAGE_PREFIX} ${errorMessage}`)} | ${''} | ${errorMessage}
+ `(
+ 'properly handles the edge case of error="$error" and defaultMessage="$defaultMessage"',
+ ({ error, defaultMessage, expectedResult }) => {
+ expect(parseErrorMessage(error, defaultMessage)).toEqual(expectedResult);
+ },
+ );
});
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index 062cd098640..891b5c751fb 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -5,6 +5,7 @@ import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import { createAlert } from '~/alert';
@@ -27,6 +28,8 @@ jest.mock('~/alert');
Vue.use(Vuex);
describe('issue_comment_form component', () => {
+ useLocalStorageSpy();
+
let store;
let wrapper;
let axiosMock;
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index b4f185004bb..c4f8e50b969 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -7,10 +7,7 @@ import NoteAwardsList from '~/notes/components/note_awards_list.vue';
import NoteForm from '~/notes/components/note_form.vue';
import createStore from '~/notes/stores';
import notes from '~/notes/stores/modules/index';
-import Autosave from '~/autosave';
-
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
-
import { noteableDataMock, notesDataMock, note } from '../mock_data';
jest.mock('~/autosave');
@@ -82,11 +79,6 @@ describe('issue_note_body component', () => {
expect(wrapper.findComponent(NoteForm).props('saveButtonTitle')).toBe(buttonText);
});
- it('adds autosave', () => {
- // passing undefined instead of an element because of shallowMount
- expect(Autosave).toHaveBeenCalledWith(undefined, ['Note', note.noteable_type, note.id]);
- });
-
describe('isInternalNote', () => {
beforeEach(() => {
wrapper.setProps({ isInternalNote: true });
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index 59362e18098..12c3b154fc7 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -2,7 +2,6 @@ import { GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
-import { getDraft, updateDraft } from '~/lib/utils/autosave';
import NoteForm from '~/notes/components/note_form.vue';
import createStore from '~/notes/stores';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
@@ -12,30 +11,25 @@ import { noteableDataMock, notesDataMock, discussionMock, note } from '../mock_d
jest.mock('~/lib/utils/autosave');
describe('issue_note_form component', () => {
- const dummyAutosaveKey = 'some-autosave-key';
- const dummyDraft = 'dummy draft content';
-
let store;
let wrapper;
let props;
+ let features;
const createComponentWrapper = () => {
return mount(NoteForm, {
store,
propsData: props,
+ provide: {
+ glFeatures: features || {},
+ },
});
};
const findCancelButton = () => wrapper.find('[data-testid="cancel"]');
beforeEach(() => {
- getDraft.mockImplementation((key) => {
- if (key === dummyAutosaveKey) {
- return dummyDraft;
- }
-
- return null;
- });
+ features = {};
store = createStore();
store.dispatch('setNoteableData', noteableDataMock);
@@ -68,6 +62,20 @@ describe('issue_note_form component', () => {
});
});
+ it('hides content editor switcher if feature flag content_editor_on_issues is off', () => {
+ features = { contentEditorOnIssues: false };
+ wrapper = createComponentWrapper();
+
+ expect(wrapper.text()).not.toContain('Rich text');
+ });
+
+ it('shows content editor switcher if feature flag content_editor_on_issues is on', () => {
+ features = { contentEditorOnIssues: true };
+ wrapper = createComponentWrapper();
+
+ expect(wrapper.text()).toContain('Rich text');
+ });
+
describe('conflicts editing', () => {
beforeEach(() => {
wrapper = createComponentWrapper();
@@ -117,13 +125,15 @@ describe('issue_note_form component', () => {
${true} | ${'Write an internal note or drag your files hereā€¦'}
`(
'should set correct textarea placeholder text when discussion confidentiality is $internal',
- ({ internal, placeholder }) => {
+ async ({ internal, placeholder }) => {
props.note = {
...note,
internal,
};
wrapper = createComponentWrapper();
+ await nextTick();
+
expect(wrapper.find('textarea').attributes('placeholder')).toBe(placeholder);
},
);
@@ -204,7 +214,7 @@ describe('issue_note_form component', () => {
});
await nextTick();
- const textareaEl = wrapper.vm.$refs.textarea;
+ const textareaEl = wrapper.vm.$refs.markdownEditor.$el.querySelector('textarea');
const cancelButton = findCancelButton();
textareaEl.classList.add(AT_WHO_ACTIVE_CLASS);
cancelButton.vm.$emit('click');
@@ -229,78 +239,6 @@ describe('issue_note_form component', () => {
});
});
- describe('with autosaveKey', () => {
- describe('with draft', () => {
- beforeEach(() => {
- Object.assign(props, {
- noteBody: '',
- autosaveKey: dummyAutosaveKey,
- });
- wrapper = createComponentWrapper();
-
- return nextTick();
- });
-
- it('displays the draft in textarea', () => {
- const textarea = wrapper.find('textarea');
-
- expect(textarea.element.value).toBe(dummyDraft);
- });
- });
-
- describe('without draft', () => {
- beforeEach(() => {
- Object.assign(props, {
- noteBody: '',
- autosaveKey: 'some key without draft',
- });
- wrapper = createComponentWrapper();
-
- return nextTick();
- });
-
- it('leaves the textarea empty', () => {
- const textarea = wrapper.find('textarea');
-
- expect(textarea.element.value).toBe('');
- });
- });
-
- it('updates the draft if textarea content changes', () => {
- Object.assign(props, {
- noteBody: '',
- autosaveKey: dummyAutosaveKey,
- });
- wrapper = createComponentWrapper();
- const textarea = wrapper.find('textarea');
- const dummyContent = 'some new content';
-
- textarea.setValue(dummyContent);
-
- expect(updateDraft).toHaveBeenCalledWith(dummyAutosaveKey, dummyContent);
- });
-
- it('does not save draft when ctrl+enter is pressed', () => {
- const options = {
- noteBody: '',
- autosaveKey: dummyAutosaveKey,
- };
-
- props = { ...props, ...options };
- wrapper = createComponentWrapper();
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ isSubmittingWithKeydown: true });
-
- const textarea = wrapper.find('textarea');
- textarea.setValue('some content');
- textarea.trigger('keydown.enter', { metaKey: true });
-
- expect(updateDraft).not.toHaveBeenCalled();
- });
- });
-
describe('with batch comments', () => {
beforeEach(() => {
store.registerModule('batchComments', batchComments());
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 0ca350f9ed7..ae5316eb12f 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -26,8 +26,6 @@ import {
REPORT_TYPE_LICENSE_COMPLIANCE,
REPORT_TYPE_SAST,
} from '~/vue_shared/security_reports/constants';
-import { USER_FACING_ERROR_MESSAGE_PREFIX } from '~/lib/utils/error_message';
-import { manageViaMRErrorMessage } from '../constants';
const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
@@ -202,21 +200,20 @@ describe('App component', () => {
});
});
- describe('when user facing error occurs', () => {
+ describe('when error occurs', () => {
+ const errorMessage = 'There was a manage via MR error';
+
it('should show Alert with error Message', async () => {
expect(findManageViaMRErrorAlert().exists()).toBe(false);
- // Prefixed with USER_FACING_ERROR_MESSAGE_PREFIX as used in lib/gitlab/utils/error_message.rb to indicate a user facing error
- findFeatureCards()
- .at(1)
- .vm.$emit('error', `${USER_FACING_ERROR_MESSAGE_PREFIX} ${manageViaMRErrorMessage}`);
+ findFeatureCards().at(1).vm.$emit('error', errorMessage);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
- expect(findManageViaMRErrorAlert().text()).toEqual(manageViaMRErrorMessage);
+ expect(findManageViaMRErrorAlert().text()).toBe(errorMessage);
});
it('should hide Alert when it is dismissed', async () => {
- findFeatureCards().at(1).vm.$emit('error', manageViaMRErrorMessage);
+ findFeatureCards().at(1).vm.$emit('error', errorMessage);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
@@ -226,17 +223,6 @@ describe('App component', () => {
expect(findManageViaMRErrorAlert().exists()).toBe(false);
});
});
-
- describe('when non-user facing error occurs', () => {
- it('should show Alert with generic error Message', async () => {
- expect(findManageViaMRErrorAlert().exists()).toBe(false);
- findFeatureCards().at(1).vm.$emit('error', manageViaMRErrorMessage);
-
- await nextTick();
- expect(findManageViaMRErrorAlert().exists()).toBe(true);
- expect(findManageViaMRErrorAlert().text()).toEqual(i18n.genericErrorText);
- });
- });
});
describe('Auto DevOps hint alert', () => {
diff --git a/spec/frontend/super_sidebar/components/context_switcher_spec.js b/spec/frontend/super_sidebar/components/context_switcher_spec.js
index 538e87cf843..92df8129799 100644
--- a/spec/frontend/super_sidebar/components/context_switcher_spec.js
+++ b/spec/frontend/super_sidebar/components/context_switcher_spec.js
@@ -5,6 +5,7 @@ import * as Sentry from '@sentry/browser';
import { s__ } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ContextSwitcher from '~/super_sidebar/components/context_switcher.vue';
+import NavItem from '~/super_sidebar/components/nav_item.vue';
import ProjectsList from '~/super_sidebar/components/projects_list.vue';
import GroupsList from '~/super_sidebar/components/groups_list.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -23,6 +24,7 @@ jest.mock('~/super_sidebar/utils', () => ({
trackContextAccess: jest.fn(),
}));
+const persistentLinks = [{ title: 'Explore', link: '/explore', icon: 'compass' }];
const username = 'root';
const projectsPath = 'projectsPath';
const groupsPath = 'groupsPath';
@@ -33,6 +35,7 @@ describe('ContextSwitcher component', () => {
let wrapper;
let mockApollo;
+ const findNavItems = () => wrapper.findAllComponents(NavItem);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findProjectsList = () => wrapper.findComponent(ProjectsList);
const findGroupsList = () => wrapper.findComponent(GroupsList);
@@ -60,6 +63,7 @@ describe('ContextSwitcher component', () => {
wrapper = shallowMountExtended(ContextSwitcher, {
apolloProvider: mockApollo,
propsData: {
+ persistentLinks,
username,
projectsPath,
groupsPath,
@@ -84,6 +88,12 @@ describe('ContextSwitcher component', () => {
createWrapper();
});
+ it('renders the persistent links', () => {
+ const navItems = findNavItems();
+ expect(navItems.length).toBe(persistentLinks.length);
+ expect(navItems.at(0).props('item')).toBe(persistentLinks[0]);
+ });
+
it('passes the placeholder to the search box', () => {
expect(findSearchBox().props('placeholder')).toBe(
s__('Navigation|Search for projects or groups'),
@@ -138,6 +148,10 @@ describe('ContextSwitcher component', () => {
return triggerSearchQuery();
});
+ it('hides persistent links', () => {
+ expect(findNavItems().length).toBe(0);
+ });
+
it('triggers the search query on search', () => {
expect(searchUserProjectsAndGroupsHandlerSuccess).toHaveBeenCalled();
});
diff --git a/spec/frontend/super_sidebar/components/search_results_spec.js b/spec/frontend/super_sidebar/components/search_results_spec.js
index dd48935c138..daec5c2a9b4 100644
--- a/spec/frontend/super_sidebar/components/search_results_spec.js
+++ b/spec/frontend/super_sidebar/components/search_results_spec.js
@@ -1,7 +1,9 @@
+import { GlCollapse } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { s__ } from '~/locale';
import SearchResults from '~/super_sidebar/components/search_results.vue';
import ItemsList from '~/super_sidebar/components/items_list.vue';
+import { stubComponent } from 'helpers/stub_component';
const title = s__('Navigation|PROJECTS');
const noResultsText = s__('Navigation|No project matches found');
@@ -9,7 +11,8 @@ const noResultsText = s__('Navigation|No project matches found');
describe('SearchResults component', () => {
let wrapper;
- const findListTitle = () => wrapper.findByTestId('list-title');
+ const findSearchResultsToggle = () => wrapper.findByTestId('search-results-toggle');
+ const findCollapsibleSection = () => wrapper.findComponent(GlCollapse);
const findItemsList = () => wrapper.findComponent(ItemsList);
const findEmptyText = () => wrapper.findByTestId('empty-text');
@@ -20,6 +23,11 @@ describe('SearchResults component', () => {
noResultsText,
...props,
},
+ stubs: {
+ GlCollapse: stubComponent(GlCollapse, {
+ props: ['visible'],
+ }),
+ },
});
};
@@ -29,7 +37,11 @@ describe('SearchResults component', () => {
});
it("renders the list's title", () => {
- expect(findListTitle().text()).toBe(title);
+ expect(findSearchResultsToggle().text()).toBe(title);
+ });
+
+ it('is expanded', () => {
+ expect(findCollapsibleSection().props('visible')).toBe(true);
});
it('renders the empty text', () => {
diff --git a/spec/frontend/super_sidebar/mock_data.js b/spec/frontend/super_sidebar/mock_data.js
index b540f85d9fe..8c70693465f 100644
--- a/spec/frontend/super_sidebar/mock_data.js
+++ b/spec/frontend/super_sidebar/mock_data.js
@@ -86,6 +86,7 @@ export const sidebarData = {
gitlab_version_check: { severity: 'success' },
gitlab_com_and_canary: false,
canary_toggle_com_url: 'https://next.gitlab.com',
+ context_switcher_links: [],
};
export const userMenuMockStatus = {
diff --git a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
index 681ff6c8dd3..7bda37bcaa8 100644
--- a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
@@ -275,7 +275,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
await findTextarea().setValue(newValue);
- expect(wrapper.emitted('input')).toEqual([[newValue]]);
+ expect(wrapper.emitted('input')).toEqual([[value], [newValue]]);
});
it('autosaves the markdown value to local storage', async () => {
@@ -370,7 +370,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
await findContentEditor().vm.$emit('change', { markdown: newValue });
- expect(wrapper.emitted('input')).toEqual([[newValue]]);
+ expect(wrapper.emitted('input')).toEqual([[value], [newValue]]);
});
it('autosaves the content editor value to local storage', async () => {
diff --git a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
index 6345393951c..646b37d334b 100644
--- a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
@@ -8,7 +8,9 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { humanize } from '~/lib/utils/text_utility';
import { redirectTo } from '~/lib/utils/url_utility';
-import ManageViaMr from '~/vue_shared/security_configuration/components/manage_via_mr.vue';
+import ManageViaMr, {
+ i18n,
+} from '~/vue_shared/security_configuration/components/manage_via_mr.vue';
import { REPORT_TYPE_SAST } from '~/vue_shared/security_reports/constants';
import { buildConfigureSecurityFeatureMockFactory } from './apollo_mocks';
@@ -77,10 +79,11 @@ describe('ManageViaMr component', () => {
buildConfigureSecurityFeatureMock({
successPath: '',
});
- const errorHandler = async () =>
- buildConfigureSecurityFeatureMock({
- errors: ['foo'],
+ const errorHandler = async (message = 'foo') => {
+ return buildConfigureSecurityFeatureMock({
+ errors: [message],
});
+ };
const pendingHandler = () => new Promise(() => {});
describe('when feature is configured', () => {
@@ -147,9 +150,11 @@ describe('ManageViaMr component', () => {
});
describe.each`
- handler | message
- ${noSuccessPathHandler} | ${`${featureName} merge request creation mutation failed`}
- ${errorHandler} | ${'foo'}
+ handler | message
+ ${noSuccessPathHandler} | ${`${featureName} merge request creation mutation failed`}
+ ${errorHandler.bind(null, 'UF: message')} | ${'message'}
+ ${errorHandler.bind(null, 'message')} | ${i18n.genericErrorText}
+ ${errorHandler} | ${i18n.genericErrorText}
`('given an error response', ({ handler, message }) => {
beforeEach(() => {
const apolloProvider = createMockApolloProvider(mutation, handler);