summaryrefslogtreecommitdiff
path: root/spec/frontend/notes
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
committerRobert Speicher <rspeicher@gmail.com>2021-01-20 13:34:23 -0600
commit6438df3a1e0fb944485cebf07976160184697d72 (patch)
tree00b09bfd170e77ae9391b1a2f5a93ef6839f2597 /spec/frontend/notes
parent42bcd54d971da7ef2854b896a7b34f4ef8601067 (diff)
downloadgitlab-ce-6438df3a1e0fb944485cebf07976160184697d72.tar.gz
Add latest changes from gitlab-org/gitlab@13-8-stable-eev13.8.0-rc42
Diffstat (limited to 'spec/frontend/notes')
-rw-r--r--spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap21
-rw-r--r--spec/frontend/notes/components/comment_field_layout_spec.js137
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js15
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js10
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js33
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_filter_note_spec.js10
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js26
-rw-r--r--spec/frontend/notes/components/discussion_jump_to_next_button_spec.js43
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js5
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js2
-rw-r--r--spec/frontend/notes/components/email_participants_warning_spec.js70
-rw-r--r--spec/frontend/notes/components/multiline_comment_form_spec.js89
-rw-r--r--spec/frontend/notes/components/multiline_comment_utils_spec.js4
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js28
-rw-r--r--spec/frontend/notes/components/note_attachment_spec.js2
-rw-r--r--spec/frontend/notes/components/note_awards_list_spec.js8
-rw-r--r--spec/frontend/notes/components/note_body_spec.js2
-rw-r--r--spec/frontend/notes/components/note_form_spec.js86
-rw-r--r--spec/frontend/notes/components/note_header_spec.js4
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js80
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js4
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js44
-rw-r--r--spec/frontend/notes/components/toggle_replies_widget_spec.js2
-rw-r--r--spec/frontend/notes/helpers.js2
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js2
-rw-r--r--spec/frontend/notes/old_notes_spec.js74
-rw-r--r--spec/frontend/notes/stores/actions_spec.js130
-rw-r--r--spec/frontend/notes/stores/getters_spec.js25
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js8
30 files changed, 534 insertions, 434 deletions
diff --git a/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap b/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
deleted file mode 100644
index 13af29821d8..00000000000
--- a/spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
+++ /dev/null
@@ -1,21 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
-<div
- class="btn-group"
- role="group"
->
- <button
- class="btn btn-default discussion-next-btn"
- data-track-event="click_button"
- data-track-label="mr_next_unresolved_thread"
- data-track-property="click_next_unresolved_thread"
- title="Jump to next unresolved thread"
- >
- <gl-icon-stub
- name="comment-next"
- size="16"
- />
- </button>
-</div>
-`;
diff --git a/spec/frontend/notes/components/comment_field_layout_spec.js b/spec/frontend/notes/components/comment_field_layout_spec.js
new file mode 100644
index 00000000000..4d9b4ea8c6f
--- /dev/null
+++ b/spec/frontend/notes/components/comment_field_layout_spec.js
@@ -0,0 +1,137 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommentFieldLayout from '~/notes/components/comment_field_layout.vue';
+import EmailParticipantsWarning from '~/notes/components/email_participants_warning.vue';
+import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
+
+describe('Comment Field Layout Component', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const LOCKED_DISCUSSION_DOCS_PATH = 'docs/locked/path';
+ const CONFIDENTIAL_ISSUES_DOCS_PATH = 'docs/confidential/path';
+
+ const noteableDataMock = {
+ confidential: false,
+ discussion_locked: false,
+ locked_discussion_docs_path: LOCKED_DISCUSSION_DOCS_PATH,
+ confidential_issues_docs_path: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ };
+
+ const findIssuableNoteWarning = () => wrapper.find(NoteableWarning);
+ const findEmailParticipantsWarning = () => wrapper.find(EmailParticipantsWarning);
+ const findErrorAlert = () => wrapper.findByTestId('comment-field-alert-container');
+
+ const createWrapper = (props = {}, slots = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommentFieldLayout, {
+ propsData: {
+ noteableData: noteableDataMock,
+ ...props,
+ },
+ slots,
+ }),
+ );
+ };
+
+ describe('.error-alert', () => {
+ it('does not exist by default', () => {
+ createWrapper();
+
+ expect(findErrorAlert().exists()).toBe(false);
+ });
+
+ it('exists when withAlertContainer is true', () => {
+ createWrapper({ withAlertContainer: true });
+
+ expect(findErrorAlert().isVisible()).toBe(true);
+ });
+ });
+
+ describe('issue is not confidential and not locked', () => {
+ it('does not show IssuableNoteWarning', () => {
+ createWrapper();
+
+ expect(findIssuableNoteWarning().exists()).toBe(false);
+ });
+ });
+
+ describe('issue is confidential', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: { ...noteableDataMock, confidential: true },
+ });
+ });
+
+ it('shows IssuableNoteWarning', () => {
+ expect(findIssuableNoteWarning().isVisible()).toBe(true);
+ });
+
+ it('sets IssuableNoteWarning props', () => {
+ expect(findIssuableNoteWarning().props()).toMatchObject({
+ isLocked: false,
+ isConfidential: true,
+ lockedNoteableDocsPath: LOCKED_DISCUSSION_DOCS_PATH,
+ confidentialNoteableDocsPath: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ });
+ });
+ });
+
+ describe('issue is locked', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: { ...noteableDataMock, discussion_locked: true },
+ });
+ });
+
+ it('shows IssuableNoteWarning', () => {
+ expect(findIssuableNoteWarning().isVisible()).toBe(true);
+ });
+
+ it('sets IssuableNoteWarning props', () => {
+ expect(findIssuableNoteWarning().props()).toMatchObject({
+ isConfidential: false,
+ isLocked: true,
+ lockedNoteableDocsPath: LOCKED_DISCUSSION_DOCS_PATH,
+ confidentialNoteableDocsPath: CONFIDENTIAL_ISSUES_DOCS_PATH,
+ });
+ });
+ });
+
+ describe('issue has no email participants', () => {
+ it('does not show EmailParticipantsWarning', () => {
+ createWrapper();
+
+ expect(findEmailParticipantsWarning().exists()).toBe(false);
+ });
+ });
+
+ describe('issue has email participants', () => {
+ beforeEach(() => {
+ createWrapper({
+ noteableData: {
+ ...noteableDataMock,
+ issue_email_participants: [
+ { email: 'someone@gitlab.com' },
+ { email: 'another@gitlab.com' },
+ ],
+ },
+ });
+ });
+
+ it('shows EmailParticipantsWarning', () => {
+ expect(findEmailParticipantsWarning().isVisible()).toBe(true);
+ });
+
+ it('sets EmailParticipantsWarning props', () => {
+ expect(findEmailParticipantsWarning().props('emails')).toEqual([
+ 'someone@gitlab.com',
+ 'another@gitlab.com',
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index fca1beca999..002c4f206cb 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -181,7 +181,7 @@ describe('issue_comment_form component', () => {
describe('edit mode', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ mountFunction: mount });
});
it('should enter edit mode when arrow up is pressed', () => {
@@ -200,7 +200,7 @@ describe('issue_comment_form component', () => {
describe('event enter', () => {
beforeEach(() => {
- mountComponent();
+ mountComponent({ mountFunction: mount });
});
it('should save note when cmd+enter is pressed', () => {
@@ -368,17 +368,6 @@ describe('issue_comment_form component', () => {
});
});
});
-
- describe('issue is confidential', () => {
- it('shows information warning', () => {
- mountComponent({
- noteableData: { ...noteableDataMock, confidential: true },
- mountFunction: mount,
- });
-
- expect(wrapper.find('[data-testid="confidential-warning"]').exists()).toBe(true);
- });
- });
});
describe('user is not logged in', () => {
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index 9162bee2078..3940439a32b 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -45,7 +45,7 @@ describe('diff_discussion_header component', () => {
const truncatedCommitId = commitId.substr(0, 8);
let commitElement;
- beforeEach(done => {
+ beforeEach((done) => {
store.state.diffs = {
projectPath: 'something',
};
@@ -72,7 +72,7 @@ describe('diff_discussion_header component', () => {
});
describe('for diff threads without a commit id', () => {
- it('should show started a thread on the diff text', done => {
+ it('should show started a thread on the diff text', (done) => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
@@ -85,7 +85,7 @@ describe('diff_discussion_header component', () => {
});
});
- it('should show thread on older version text', done => {
+ it('should show thread on older version text', (done) => {
Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
@@ -109,7 +109,7 @@ describe('diff_discussion_header component', () => {
});
describe('for diff thread with a commit id', () => {
- it('should display started thread on commit header', done => {
+ it('should display started thread on commit header', (done) => {
wrapper.vm.discussion.for_commit = false;
wrapper.vm.$nextTick(() => {
@@ -121,7 +121,7 @@ describe('diff_discussion_header component', () => {
});
});
- it('should display outdated change on commit header', done => {
+ it('should display outdated change on commit header', (done) => {
wrapper.vm.discussion.for_commit = false;
wrapper.vm.discussion.active = false;
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index b26eb00bfdc..48e569720e9 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -4,7 +4,6 @@ import DiscussionActions from '~/notes/components/discussion_actions.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
-import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
import createStore from '~/notes/stores';
// NOTE: clone mock_data so that it is not accidentally mutated
@@ -21,7 +20,7 @@ const createUnallowedNote = () =>
describe('DiscussionActions', () => {
let wrapper;
- const createComponentFactory = (shallow = true) => (props, options) => {
+ const createComponentFactory = (shallow = true) => (props) => {
const store = createStore();
const mountFn = shallow ? shallowMount : mount;
@@ -35,11 +34,6 @@ describe('DiscussionActions', () => {
shouldShowJumpToNextDiscussion: true,
...props,
},
- provide: {
- glFeatures: {
- hideJumpToNextUnresolvedInThreads: options?.hideJumpToNextUnresolvedInThreads,
- },
- },
});
};
@@ -55,7 +49,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true);
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true);
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(true);
});
it('only renders reply placholder if disccusion is not resolvable', () => {
@@ -66,7 +59,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false);
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
});
it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => {
@@ -75,12 +67,6 @@ describe('DiscussionActions', () => {
expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
});
- it('does not render jump to next discussion button if shouldShowJumpToNextDiscussion is false', () => {
- createComponent({ shouldShowJumpToNextDiscussion: false });
-
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
- });
-
describe.each`
desc | notes | shouldRender
${'with no notes'} | ${[]} | ${true}
@@ -101,13 +87,6 @@ describe('DiscussionActions', () => {
});
});
- it('does not render jump to next discussion button if feature flag is enabled', () => {
- const createComponent = createComponentFactory();
- createComponent({}, { hideJumpToNextUnresolvedInThreads: true });
-
- expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
- });
-
describe('events handling', () => {
const createComponent = createComponentFactory(false);
@@ -117,19 +96,13 @@ describe('DiscussionActions', () => {
it('emits showReplyForm event when clicking on reply placeholder', () => {
jest.spyOn(wrapper.vm, '$emit');
- wrapper
- .find(ReplyPlaceholder)
- .find('button')
- .trigger('click');
+ wrapper.find(ReplyPlaceholder).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
});
it('emits resolve event when clicking on resolve button', () => {
jest.spyOn(wrapper.vm, '$emit');
- wrapper
- .find(ResolveDiscussionButton)
- .find('button')
- .trigger('click');
+ wrapper.find(ResolveDiscussionButton).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index d82590c7e9e..ebf7d52f38b 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -95,7 +95,7 @@ describe('DiscussionCounter component', () => {
describe('toggle all threads button', () => {
let toggleAllButton;
- const updateStoreWithExpanded = expanded => {
+ const updateStoreWithExpanded = (expanded) => {
const discussion = { ...discussionMock, expanded };
store.commit(types.SET_INITIAL_DISCUSSIONS, [discussion]);
store.dispatch('updateResolvableDiscussionsCounts');
diff --git a/spec/frontend/notes/components/discussion_filter_note_spec.js b/spec/frontend/notes/components/discussion_filter_note_spec.js
index d35f8f7c28d..9ae3f08df77 100644
--- a/spec/frontend/notes/components/discussion_filter_note_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_note_spec.js
@@ -31,20 +31,14 @@ describe('DiscussionFilterNote component', () => {
it('emits `dropdownSelect` event with 0 parameter on clicking Show all activity button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper
- .findAll(GlButton)
- .at(0)
- .vm.$emit('click');
+ wrapper.findAll(GlButton).at(0).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 0);
});
it('emits `dropdownSelect` event with 1 parameter on clicking Show comments only button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper
- .findAll(GlButton)
- .at(1)
- .vm.$emit('click');
+ wrapper.findAll(GlButton).at(1).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
});
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index 9f3655c53b9..aeba8e8056c 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import createEventHub from '~/helpers/event_hub_factory';
import axios from '~/lib/utils/axios_utils';
@@ -25,7 +25,8 @@ describe('DiscussionFilter component', () => {
const filterDiscussion = jest.fn();
- const findFilter = filterType => wrapper.find(`.dropdown-item[data-filter-type="${filterType}"]`);
+ const findFilter = (filterType) =>
+ wrapper.find(`.dropdown-item[data-filter-type="${filterType}"]`);
const mountComponent = () => {
const discussions = [
@@ -82,12 +83,9 @@ describe('DiscussionFilter component', () => {
});
it('renders the default selected item', () => {
- expect(
- wrapper
- .find('#discussion-filter-dropdown .dropdown-item')
- .text()
- .trim(),
- ).toBe(discussionFiltersMock[0].title);
+ expect(wrapper.find('#discussion-filter-dropdown .dropdown-item').text().trim()).toBe(
+ discussionFiltersMock[0].title,
+ );
});
it('updates to the selected item', () => {
@@ -148,7 +146,7 @@ describe('DiscussionFilter component', () => {
window.mrTabs = undefined;
});
- it('only renders when discussion tab is active', done => {
+ it('only renders when discussion tab is active', (done) => {
eventHub.$emit('MergeRequestTabChange', 'commit');
wrapper.vm.$nextTick(() => {
@@ -163,7 +161,7 @@ describe('DiscussionFilter component', () => {
window.location.hash = '';
});
- it('updates the filter when the URL links to a note', done => {
+ it('updates the filter when the URL links to a note', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
wrapper.vm.handleLocationHash();
@@ -174,7 +172,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('does not update the filter when the current filter is "Show all activity"', done => {
+ it('does not update the filter when the current filter is "Show all activity"', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.handleLocationHash();
@@ -184,7 +182,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('only updates filter when the URL links to a note', done => {
+ it('only updates filter when the URL links to a note', (done) => {
window.location.hash = `testing123`;
wrapper.vm.handleLocationHash();
@@ -194,7 +192,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('fetches discussions when there is a hash', done => {
+ it('fetches discussions when there is a hash', (done) => {
window.location.hash = `note_${discussionMock.notes[0].id}`;
wrapper.vm.currentValue = discussionFiltersMock[2].value;
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
@@ -206,7 +204,7 @@ describe('DiscussionFilter component', () => {
});
});
- it('does not fetch discussions when there is no hash', done => {
+ it('does not fetch discussions when there is no hash', (done) => {
window.location.hash = '';
jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
wrapper.vm.handleLocationHash();
diff --git a/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js b/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
deleted file mode 100644
index 183966cf435..00000000000
--- a/spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
-import { mockTracking } from '../../helpers/tracking_helper';
-
-describe('JumpToNextDiscussionButton', () => {
- const fromDiscussionId = 'abc123';
- let wrapper;
- let trackingSpy;
- let jumpFn;
-
- beforeEach(() => {
- jumpFn = jest.fn();
- wrapper = shallowMount(JumpToNextDiscussionButton, {
- propsData: { fromDiscussionId },
- });
- wrapper.setMethods({ jumpToNextRelativeDiscussion: jumpFn });
-
- trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('matches the snapshot', () => {
- expect(wrapper.vm.$el).toMatchSnapshot();
- });
-
- it('calls jumpToNextRelativeDiscussion when clicked', () => {
- wrapper.find({ ref: 'button' }).trigger('click');
-
- expect(jumpFn).toHaveBeenCalledWith(fromDiscussionId);
- });
-
- it('sends the correct tracking event when clicked', () => {
- wrapper.find({ ref: 'button' }).trigger('click');
-
- expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
- label: 'mr_next_unresolved_thread',
- property: 'click_next_unresolved_thread',
- });
- });
-});
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 8cc98f978c2..e803dcb7b4a 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -122,12 +122,11 @@ describe('DiscussionNotes', () => {
describe('events', () => {
describe('with groupped notes and replies expanded', () => {
- const findNoteAtIndex = index => {
+ const findNoteAtIndex = (index) => {
const noteComponents = [NoteableNote, SystemNote, PlaceholderNote, PlaceholderSystemNote];
- const allowedNames = noteComponents.map(c => c.name);
return wrapper
.findAll('.notes *')
- .filter(w => allowedNames.includes(w.name()))
+ .filter((w) => noteComponents.some((Component) => w.is(Component)))
.at(index);
};
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index 41701e54dfa..5105e1013d3 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -7,7 +7,7 @@ const buttonTitle = 'Resolve discussion';
describe('resolveDiscussionButton', () => {
let wrapper;
- const factory = options => {
+ const factory = (options) => {
wrapper = shallowMount(resolveDiscussionButton, {
...options,
});
diff --git a/spec/frontend/notes/components/email_participants_warning_spec.js b/spec/frontend/notes/components/email_participants_warning_spec.js
new file mode 100644
index 00000000000..ab1a6b152a4
--- /dev/null
+++ b/spec/frontend/notes/components/email_participants_warning_spec.js
@@ -0,0 +1,70 @@
+import { mount } from '@vue/test-utils';
+import EmailParticipantsWarning from '~/notes/components/email_participants_warning.vue';
+
+describe('Email Participants Warning Component', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findMoreButton = () => wrapper.find('button');
+
+ const createWrapper = (emails) => {
+ wrapper = mount(EmailParticipantsWarning, {
+ propsData: { emails },
+ });
+ };
+
+ describe('with 3 or less emails', () => {
+ beforeEach(() => {
+ createWrapper(['a@gitlab.com', 'b@gitlab.com', 'c@gitlab.com']);
+ });
+
+ it('more button does not exist', () => {
+ expect(findMoreButton().exists()).toBe(false);
+ });
+
+ it('all emails are displayed', () => {
+ expect(wrapper.text()).toBe(
+ 'a@gitlab.com, b@gitlab.com, and c@gitlab.com will be notified of your comment.',
+ );
+ });
+ });
+
+ describe('with more than 3 emails', () => {
+ beforeEach(() => {
+ createWrapper(['a@gitlab.com', 'b@gitlab.com', 'c@gitlab.com', 'd@gitlab.com']);
+ });
+
+ it('only displays first 3 emails', () => {
+ expect(wrapper.text()).toContain('a@gitlab.com, b@gitlab.com, c@gitlab.com');
+ expect(wrapper.text()).not.toContain('d@gitlab.com');
+ });
+
+ it('more button does exist', () => {
+ expect(findMoreButton().exists()).toBe(true);
+ });
+
+ it('more button displays the correct wordage', () => {
+ expect(findMoreButton().text()).toBe('and 1 more');
+ });
+
+ describe('when more button clicked', () => {
+ beforeEach(() => {
+ findMoreButton().trigger('click');
+ });
+
+ it('more button no longer exists', () => {
+ expect(findMoreButton().exists()).toBe(false);
+ });
+
+ it('all emails are displayed', () => {
+ expect(wrapper.text()).toBe(
+ 'a@gitlab.com, b@gitlab.com, c@gitlab.com, and d@gitlab.com will be notified of your comment.',
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/multiline_comment_form_spec.js b/spec/frontend/notes/components/multiline_comment_form_spec.js
new file mode 100644
index 00000000000..081fd6e10ef
--- /dev/null
+++ b/spec/frontend/notes/components/multiline_comment_form_spec.js
@@ -0,0 +1,89 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mount } from '@vue/test-utils';
+import { GlFormSelect } from '@gitlab/ui';
+import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue';
+import notesModule from '~/notes/stores/modules';
+
+describe('MultilineCommentForm', () => {
+ Vue.use(Vuex);
+ const setSelectedCommentPosition = jest.fn();
+ const testLine = {
+ line_code: 'test',
+ type: 'test',
+ old_line: 'test',
+ new_line: 'test',
+ };
+
+ const createWrapper = (props = {}, state) => {
+ setSelectedCommentPosition.mockReset();
+
+ const store = new Vuex.Store({
+ modules: { notes: notesModule() },
+ actions: { setSelectedCommentPosition },
+ });
+ if (state) store.replaceState({ ...store.state, ...state });
+
+ const propsData = {
+ line: { ...testLine },
+ commentLineOptions: [{ text: '1' }],
+ ...props,
+ };
+ return mount(MultilineCommentForm, { propsData, store });
+ };
+
+ describe('created', () => {
+ it('sets commentLineStart to line', () => {
+ const line = { ...testLine };
+ const wrapper = createWrapper({ line });
+
+ expect(wrapper.vm.commentLineStart).toEqual(line);
+ expect(setSelectedCommentPosition).toHaveBeenCalled();
+ });
+
+ it('sets commentLineStart to lineRange', () => {
+ const lineRange = {
+ start: { ...testLine },
+ };
+ const wrapper = createWrapper({ lineRange });
+
+ expect(wrapper.vm.commentLineStart).toEqual(lineRange.start);
+ expect(setSelectedCommentPosition).toHaveBeenCalled();
+ });
+
+ it('sets commentLineStart to selectedCommentPosition', () => {
+ const notes = {
+ selectedCommentPosition: {
+ start: { ...testLine },
+ },
+ };
+ const wrapper = createWrapper({}, { notes });
+
+ expect(wrapper.vm.commentLineStart).toEqual(wrapper.vm.selectedCommentPosition.start);
+ expect(setSelectedCommentPosition).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('destroyed', () => {
+ it('calls setSelectedCommentPosition', () => {
+ const wrapper = createWrapper();
+ wrapper.destroy();
+
+ // Once during created, once during destroyed
+ expect(setSelectedCommentPosition).toHaveBeenCalledTimes(2);
+ });
+ });
+
+ it('handles changing the start line', () => {
+ const line = { ...testLine };
+ const wrapper = createWrapper({ line });
+ const glSelect = wrapper.findComponent(GlFormSelect);
+
+ glSelect.vm.$emit('change', { ...testLine });
+
+ expect(wrapper.vm.commentLineStart).toEqual(line);
+ expect(wrapper.emitted('input')).toBeTruthy();
+ // Once during created, once during updateCommentLineStart
+ expect(setSelectedCommentPosition).toHaveBeenCalledTimes(2);
+ });
+});
diff --git a/spec/frontend/notes/components/multiline_comment_utils_spec.js b/spec/frontend/notes/components/multiline_comment_utils_spec.js
index 99b33e7cd5f..05faff02a6c 100644
--- a/spec/frontend/notes/components/multiline_comment_utils_spec.js
+++ b/spec/frontend/notes/components/multiline_comment_utils_spec.js
@@ -7,7 +7,7 @@ import {
describe('Multiline comment utilities', () => {
describe('get start & end line numbers', () => {
- const lineRanges = ['old', 'new', null].map(type => ({
+ const lineRanges = ['old', 'new', null].map((type) => ({
start: { new_line: 1, old_line: 1, type },
end: { new_line: 2, old_line: 2, type },
}));
@@ -35,7 +35,7 @@ describe('Multiline comment utilities', () => {
});
});
const inlineDiffLines = [{ line_code: '1' }, { line_code: '2' }, { line_code: '3' }];
- const parallelDiffLines = inlineDiffLines.map(line => ({
+ const parallelDiffLines = inlineDiffLines.map((line) => ({
left: { ...line },
right: { ...line },
}));
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index f01c6c6b84e..3cfc1445cb8 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -65,23 +65,11 @@ describe('noteActions', () => {
});
it('should render noteable author badge', () => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(0)
- .text()
- .trim(),
- ).toEqual('Author');
+ expect(wrapper.findAll('.note-role').at(0).text().trim()).toEqual('Author');
});
it('should render access level badge', () => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(1)
- .text()
- .trim(),
- ).toEqual(props.accessLevel);
+ expect(wrapper.findAll('.note-role').at(1).text().trim()).toEqual(props.accessLevel);
});
it('should render contributor badge', () => {
@@ -91,13 +79,7 @@ describe('noteActions', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(
- wrapper
- .findAll('.note-role')
- .at(1)
- .text()
- .trim(),
- ).toBe('Contributor');
+ expect(wrapper.findAll('.note-role').at(1).text().trim()).toBe('Contributor');
});
});
@@ -119,7 +101,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(true);
});
- it('should not show copy link action when `noteUrl` prop is empty', done => {
+ it('should not show copy link action when `noteUrl` prop is empty', (done) => {
wrapper.setProps({
...props,
author: {
@@ -145,7 +127,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-note-delete').exists()).toBe(true);
});
- it('closes tooltip when dropdown opens', done => {
+ it('closes tooltip when dropdown opens', (done) => {
wrapper.find('.more-actions-toggle').trigger('click');
const rootWrapper = createWrapper(wrapper.vm.$root);
diff --git a/spec/frontend/notes/components/note_attachment_spec.js b/spec/frontend/notes/components/note_attachment_spec.js
index 9d1051676e1..d47c2beaaf8 100644
--- a/spec/frontend/notes/components/note_attachment_spec.js
+++ b/spec/frontend/notes/components/note_attachment_spec.js
@@ -7,7 +7,7 @@ describe('Issue note attachment', () => {
const findImage = () => wrapper.find({ ref: 'attachmentImage' });
const findUrl = () => wrapper.find({ ref: 'attachmentUrl' });
- const createComponent = attachment => {
+ const createComponent = (attachment) => {
wrapper = shallowMount(NoteAttachment, {
propsData: {
attachment,
diff --git a/spec/frontend/notes/components/note_awards_list_spec.js b/spec/frontend/notes/components/note_awards_list_spec.js
index 5ab183e5452..13a817902e6 100644
--- a/spec/frontend/notes/components/note_awards_list_spec.js
+++ b/spec/frontend/notes/components/note_awards_list_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'jest/helpers/test_constants';
+import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores';
import awardsNote from '~/notes/components/note_awards_list.vue';
@@ -106,7 +106,7 @@ describe('note_awards_list component', () => {
awardsMock = [...new Array(1)].map(createAwardEmoji);
mountComponent();
- awardsMock.forEach(award => {
+ awardsMock.forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
@@ -115,7 +115,7 @@ describe('note_awards_list component', () => {
awardsMock = [...new Array(2)].map(createAwardEmoji);
mountComponent();
- awardsMock.forEach(award => {
+ awardsMock.forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
@@ -125,7 +125,7 @@ describe('note_awards_list component', () => {
mountComponent();
// Testing only the first 10 awards since 11 onward will not be displayed.
- awardsMock.slice(0, 10).forEach(award => {
+ awardsMock.slice(0, 10).forEach((award) => {
expect(findTooltip()).toContain(award.user.name);
});
});
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index efad0785afe..3c11c266f90 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -38,7 +38,7 @@ describe('issue_note_body component', () => {
});
describe('isEditing', () => {
- beforeEach(done => {
+ beforeEach((done) => {
vm.isEditing = true;
Vue.nextTick(done);
});
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index cc434d6c952..e64a75bede9 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import createStore from '~/notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
@@ -18,17 +19,14 @@ describe('issue_note_form component', () => {
let props;
const createComponentWrapper = () => {
- const localVue = createLocalVue();
- return shallowMount(localVue.extend(NoteForm), {
+ return mount(NoteForm, {
store,
propsData: props,
- // see https://gitlab.com/gitlab-org/gitlab-foss/issues/56317 for the following
- localVue,
});
};
beforeEach(() => {
- getDraft.mockImplementation(key => {
+ getDraft.mockImplementation((key) => {
if (key === dummyAutosaveKey) {
return dummyDraft;
}
@@ -60,15 +58,14 @@ describe('issue_note_form component', () => {
expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
});
- it('return note hash as `#` when `noteId` is empty', () => {
+ it('return note hash as `#` when `noteId` is empty', async () => {
wrapper.setProps({
...props,
noteId: '',
});
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.noteHash).toBe('#');
- });
+ expect(wrapper.vm.noteHash).toBe('#');
});
});
@@ -77,7 +74,7 @@ describe('issue_note_form component', () => {
wrapper = createComponentWrapper();
});
- it('should show conflict message if note changes outside the component', () => {
+ it('should show conflict message if note changes outside the component', async () => {
wrapper.setProps({
...props,
isEditing: true,
@@ -87,17 +84,12 @@ describe('issue_note_form component', () => {
const message =
'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.';
- return wrapper.vm.$nextTick().then(() => {
- const conflictWarning = wrapper.find('.js-conflict-edit-warning');
+ await nextTick();
- expect(conflictWarning.exists()).toBe(true);
- expect(
- conflictWarning
- .text()
- .replace(/\s+/g, ' ')
- .trim(),
- ).toBe(message);
- });
+ const conflictWarning = wrapper.find('.js-conflict-edit-warning');
+
+ expect(conflictWarning.exists()).toBe(true);
+ expect(conflictWarning.text().replace(/\s+/g, ' ').trim()).toBe(message);
});
});
@@ -161,36 +153,33 @@ describe('issue_note_form component', () => {
});
describe('actions', () => {
- it('should be possible to cancel', () => {
- const cancelHandler = jest.fn();
+ it('should be possible to cancel', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
- wrapper.setMethods({ cancelHandler });
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- const cancelButton = wrapper.find('[data-testid="cancel"]');
- cancelButton.trigger('click');
+ const cancelButton = wrapper.find('[data-testid="cancel"]');
+ cancelButton.trigger('click');
+ await nextTick();
- expect(cancelHandler).toHaveBeenCalledWith(true);
- });
+ expect(wrapper.emitted().cancelForm).toHaveLength(1);
});
- it('should be possible to update the note', () => {
+ it('should be possible to update the note', async () => {
wrapper.setProps({
...props,
isEditing: true,
});
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- const textarea = wrapper.find('textarea');
- textarea.setValue('Foo');
- const saveButton = wrapper.find('.js-vue-issue-save');
- saveButton.trigger('click');
+ const textarea = wrapper.find('textarea');
+ textarea.setValue('Foo');
+ const saveButton = wrapper.find('.js-vue-issue-save');
+ saveButton.trigger('click');
- expect(wrapper.vm.isSubmitting).toBe(true);
- });
+ expect(wrapper.vm.isSubmitting).toBe(true);
});
});
});
@@ -204,7 +193,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('displays the draft in textarea', () => {
@@ -222,7 +211,7 @@ describe('issue_note_form component', () => {
});
wrapper = createComponentWrapper();
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('leaves the textarea empty', () => {
@@ -278,15 +267,14 @@ describe('issue_note_form component', () => {
});
});
- it('should be possible to cancel', () => {
+ it('should be possible to cancel', async () => {
jest.spyOn(wrapper.vm, 'cancelHandler');
- return wrapper.vm.$nextTick().then(() => {
- const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
- cancelButton.trigger('click');
+ await nextTick();
+ const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
+ cancelButton.trigger('click');
- expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
- });
+ expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
});
it('shows resolve checkbox', () => {
@@ -299,7 +287,7 @@ describe('issue_note_form component', () => {
discussion: {
...discussionMock,
notes: [
- ...discussionMock.notes.map(n => ({
+ ...discussionMock.notes.map((n) => ({
...n,
resolvable: true,
current_user: { ...n.current_user, can_resolve_discussion: false },
@@ -309,7 +297,7 @@ describe('issue_note_form component', () => {
},
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
});
@@ -317,7 +305,7 @@ describe('issue_note_form component', () => {
it('hides actions for commits', () => {
wrapper.setProps({ discussion: { for_commit: true } });
- return wrapper.vm.$nextTick(() => {
+ return nextTick(() => {
expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
});
});
@@ -331,7 +319,7 @@ describe('issue_note_form component', () => {
textarea.setValue('Foo');
textarea.trigger('keydown.enter', { metaKey: true });
- return wrapper.vm.$nextTick(() => {
+ return nextTick(() => {
expect(wrapper.vm.handleAddToReview).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index 1c6d0bafda8..132e3d8aa7e 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -41,7 +41,7 @@ describe('NoteHeader component', () => {
},
};
- const createComponent = props => {
+ const createComponent = (props) => {
wrapper = shallowMount(NoteHeader, {
localVue,
store: new Vuex.Store({
@@ -252,7 +252,7 @@ describe('NoteHeader component', () => {
});
describe('when author username link is hovered', () => {
- it('toggles hover specific CSS classes on author name link', done => {
+ it('toggles hover specific CSS classes on author name link', (done) => {
createComponent({ author });
const authorUsernameLink = wrapper.find({ ref: 'authorUsernameLink' });
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 1c6603899d3..b87c6cd7f2b 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -1,8 +1,10 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { trimText } from 'helpers/text_helper';
import createStore from '~/notes/stores';
-import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import NoteForm from '~/notes/components/note_form.vue';
@@ -17,8 +19,6 @@ import {
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
-const localVue = createLocalVue();
-
describe('noteable_discussion component', () => {
let store;
let wrapper;
@@ -32,10 +32,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
@@ -47,63 +46,58 @@ describe('noteable_discussion component', () => {
expect(wrapper.find('.discussion-header').exists()).toBe(false);
});
- it('should render thread header', () => {
+ it('should render thread header', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
discussion.expanded = false;
wrapper.setProps({ discussion });
+ await nextTick();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.discussion-header').exists()).toBe(true);
- });
+ expect(wrapper.find('.discussion-header').exists()).toBe(true);
});
describe('actions', () => {
- it('should toggle reply form', () => {
- const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ it('should toggle reply form', async () => {
+ await nextTick();
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.isReplying).toEqual(false);
+ expect(wrapper.vm.isReplying).toEqual(false);
- replyPlaceholder.vm.$emit('onClick');
- })
- .then(() => wrapper.vm.$nextTick())
- .then(() => {
- expect(wrapper.vm.isReplying).toEqual(true);
+ const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ replyPlaceholder.vm.$emit('onClick');
+ await nextTick();
- const noteForm = wrapper.find(NoteForm);
+ expect(wrapper.vm.isReplying).toEqual(true);
- expect(noteForm.exists()).toBe(true);
+ const noteForm = wrapper.find(NoteForm);
- const noteFormProps = noteForm.props();
+ expect(noteForm.exists()).toBe(true);
- expect(noteFormProps.discussion).toBe(discussionMock);
- expect(noteFormProps.isEditing).toBe(false);
- expect(noteFormProps.line).toBe(null);
- expect(noteFormProps.saveButtonTitle).toBe('Comment');
- expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
- });
+ const noteFormProps = noteForm.props();
+
+ expect(noteFormProps.discussion).toBe(discussionMock);
+ expect(noteFormProps.isEditing).toBe(false);
+ expect(noteFormProps.line).toBe(null);
+ expect(noteFormProps.saveButtonTitle).toBe('Comment');
+ expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
});
it('should expand discussion', async () => {
- const expandDiscussion = jest.fn();
- const discussion = { ...discussionMock };
- discussion.expanded = false;
+ const discussion = { ...discussionMock, expanded: false };
wrapper.setProps({ discussion });
- wrapper.setMethods({ expandDiscussion });
+ store.dispatch = jest.fn();
- await wrapper.vm.$nextTick();
+ await nextTick();
- wrapper.vm.showReplyForm();
+ wrapper.find(DiscussionNotes).vm.$emit('startReplying');
- await wrapper.vm.$nextTick();
+ await nextTick();
- expect(expandDiscussion).toHaveBeenCalledWith({ discussionId: discussion.id });
+ expect(store.dispatch).toHaveBeenCalledWith('expandDiscussion', {
+ discussionId: discussion.id,
+ });
});
it('does not render jump to thread button', () => {
@@ -132,7 +126,7 @@ describe('noteable_discussion component', () => {
...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
expanded: true,
};
- discussion.notes = discussion.notes.map(note => ({
+ discussion.notes = discussion.notes.map((note) => ({
...note,
resolved: false,
current_user: {
@@ -143,7 +137,7 @@ describe('noteable_discussion component', () => {
wrapper.setProps({ discussion });
- return wrapper.vm.$nextTick();
+ return nextTick();
});
it('displays a button to resolve with issue', () => {
@@ -169,10 +163,9 @@ describe('noteable_discussion component', () => {
window.gon.current_user_id = userDataMock.id;
store.dispatch('setUserData', userDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
@@ -188,10 +181,9 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', loggedOutnoteableData);
store.dispatch('setNotesData', notesDataMock);
- wrapper = mount(localVue.extend(noteableDiscussion), {
+ wrapper = mount(NoteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- localVue,
});
});
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index a08e86d92d3..6f06665f412 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -208,7 +208,7 @@ describe('issue_note', () => {
expect(noteBodyProps.helpPagePath).toBe('');
});
- it('prevents note preview xss', done => {
+ it('prevents note preview xss', (done) => {
const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`;
const alertSpy = jest.spyOn(window, 'alert');
@@ -230,7 +230,7 @@ describe('issue_note', () => {
});
describe('cancel edit', () => {
- it('restores content of updated note', done => {
+ it('restores content of updated note', (done) => {
const updatedText = 'updated note text';
store.hotUpdate({
actions: {
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index e905a12919e..e495a4738e0 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -36,16 +36,16 @@ describe('note_app', () => {
const getComponentOrder = () => {
return wrapper
.findAll('#notes-list,.js-comment-form')
- .wrappers.map(node => (node.is(CommentForm) ? TYPE_COMMENT_FORM : TYPE_NOTES_LIST));
+ .wrappers.map((node) => (node.is(CommentForm) ? TYPE_COMMENT_FORM : TYPE_NOTES_LIST));
};
/**
* waits for fetchNotes() to complete
*/
const waitForDiscussionsRequest = () =>
- new Promise(resolve => {
+ new Promise((resolve) => {
const { vm } = wrapper.find(NotesApp);
- const unwatch = vm.$watch('isFetching', isFetching => {
+ const unwatch = vm.$watch('isFetching', (isFetching) => {
if (isFetching) {
return;
}
@@ -129,18 +129,15 @@ describe('note_app', () => {
'/gitlab-org/gitlab-foss/issues/26/discussions.json'
][0].notes[0];
- expect(
- wrapper
- .find('.main-notes-list .note-header-author-name')
- .text()
- .trim(),
- ).toEqual(note.author.name);
+ expect(wrapper.find('.main-notes-list .note-header-author-name').text().trim()).toEqual(
+ note.author.name,
+ );
expect(wrapper.find('.main-notes-list .note-text').html()).toContain(note.note_html);
});
it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form').element.tagName).toBe('FORM');
expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
'Write a comment or drag your files here…',
);
@@ -205,7 +202,7 @@ describe('note_app', () => {
});
it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form').element.tagName).toBe('FORM');
expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
'Write a comment or drag your files here…',
);
@@ -272,23 +269,15 @@ describe('note_app', () => {
it('should render markdown docs url', () => {
const { markdownDocsPath } = mockData.notesDataMock;
- expect(
- wrapper
- .find(`a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown');
+ expect(wrapper.find(`a[href="${markdownDocsPath}"]`).text().trim()).toEqual('Markdown');
});
it('should render quick action docs url', () => {
const { quickActionsDocsPath } = mockData.notesDataMock;
- expect(
- wrapper
- .find(`a[href="${quickActionsDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('quick actions');
+ expect(wrapper.find(`a[href="${quickActionsDocsPath}"]`).text().trim()).toEqual(
+ 'quick actions',
+ );
});
});
@@ -304,12 +293,9 @@ describe('note_app', () => {
const { markdownDocsPath } = mockData.notesDataMock;
return Vue.nextTick().then(() => {
- expect(
- wrapper
- .find(`.edit-note a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown is supported');
+ expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
+ 'Markdown is supported',
+ );
});
});
diff --git a/spec/frontend/notes/components/toggle_replies_widget_spec.js b/spec/frontend/notes/components/toggle_replies_widget_spec.js
index b4f68b039cf..409e1bc3951 100644
--- a/spec/frontend/notes/components/toggle_replies_widget_spec.js
+++ b/spec/frontend/notes/components/toggle_replies_widget_spec.js
@@ -3,7 +3,7 @@ import mountComponent from 'helpers/vue_mount_component_helper';
import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import { note } from '../mock_data';
-const deepCloneObject = obj => JSON.parse(JSON.stringify(obj));
+const deepCloneObject = (obj) => JSON.parse(JSON.stringify(obj));
describe('toggle replies widget for notes', () => {
let vm;
diff --git a/spec/frontend/notes/helpers.js b/spec/frontend/notes/helpers.js
index c8168a49a5b..ed34f985e94 100644
--- a/spec/frontend/notes/helpers.js
+++ b/spec/frontend/notes/helpers.js
@@ -1,4 +1,4 @@
-export const resetStore = store => {
+export const resetStore = (store) => {
store.replaceState({
notes: [],
targetNoteHash: null,
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 4114df618e5..9c9a648d213 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -34,7 +34,7 @@ describe('Discussion navigation mixin', () => {
setHTMLFixture(
[...'abcde']
.map(
- id =>
+ (id) =>
`<ul class="notes" data-discussion-id="${id}"></ul>
<div class="discussion" data-discussion-id="${id}"></div>`,
)
diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js
index dee4f93f0ce..00821980e8a 100644
--- a/spec/frontend/notes/old_notes_spec.js
+++ b/spec/frontend/notes/old_notes_spec.js
@@ -82,9 +82,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
it('modifies the Markdown field', () => {
const changeEvent = document.createEvent('HTMLEvents');
changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
+ $('input[type=checkbox]').attr('checked', true)[0].dispatchEvent(changeEvent);
expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
});
@@ -129,7 +127,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
jest.spyOn(notes, 'renderNote');
- $('.js-comment-button').on('click', e => {
+ $('.js-comment-button').on('click', (e) => {
const $form = $(this);
e.preventDefault();
notes.addNote($form, {});
@@ -552,7 +550,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
});
- it('should remove placeholder note when new comment is done posting', done => {
+ it('should remove placeholder note when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -564,7 +562,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
describe('postComment', () => {
- it('disables the submit button', done => {
+ it('disables the submit button', (done) => {
const $submitButton = $form.find('.js-comment-submit-button');
expect($submitButton).not.toBeDisabled();
@@ -587,7 +585,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should show actual note element when new comment is done posting', done => {
+ it('should show actual note element when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -598,7 +596,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should reset Form when new comment is done posting', done => {
+ it('should reset Form when new comment is done posting', (done) => {
mockNotesPost();
$('.js-comment-button').click();
@@ -609,7 +607,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
});
- it('should show flash error message when new comment failed to be posted', done => {
+ it('should show flash error message when new comment failed to be posted', (done) => {
mockNotesPostError();
jest.spyOn(notes, 'addFlash');
@@ -660,7 +658,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should remove quick action placeholder when comment with quick actions is done posting', done => {
+ it('should remove quick action placeholder when comment with quick actions is done posting', (done) => {
jest.spyOn(gl.awardsHandler, 'addAwardToEmojiBar');
$('.js-comment-button').click();
@@ -695,7 +693,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').val(sampleComment);
});
- it('should show message placeholder including lines starting with slash', done => {
+ it('should show message placeholder including lines starting with slash', (done) => {
$('.js-comment-button').click();
expect($notesContainer.find('.note.being-posted').length).toEqual(1); // Placeholder shown
@@ -733,7 +731,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
$form.find('textarea.js-note-text').html(sampleComment);
});
- it('should not render a script tag', done => {
+ it('should not render a script tag', (done) => {
$('.js-comment-button').click();
setImmediate(() => {
@@ -746,12 +744,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
.find(`#note_${note.id}`)
.find('.js-task-list-container');
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual('');
+ expect($updatedNoteEl.find('.note-text').text().trim()).toEqual('');
done();
});
@@ -912,26 +905,15 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual(currentUserFullname);
-
- expect(
- $tempNoteHeader
- .find('.note-headline-light')
- .text()
- .trim(),
- ).toEqual(`@${currentUsername}`);
-
- expect(
- $tempNote
- .find('.note-body .note-text p')
- .text()
- .trim(),
- ).toEqual(sampleComment);
+ expect($tempNoteHeader.find('.d-none.d-sm-inline-block').text().trim()).toEqual(
+ currentUserFullname,
+ );
+
+ expect($tempNoteHeader.find('.note-headline-light').text().trim()).toEqual(
+ `@${currentUsername}`,
+ );
+
+ expect($tempNote.find('.note-body .note-text p').text().trim()).toEqual(sampleComment);
});
it('should return constructed placeholder element for discussion note based on form contents', () => {
@@ -959,12 +941,9 @@ describe.skip('Old Notes (~/notes.js)', () => {
});
const $tempNoteHeader = $tempNote.find('.note-header');
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
+ expect($tempNoteHeader.find('.d-none.d-sm-inline-block').text().trim()).toEqual(
+ 'Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;',
+ );
});
});
@@ -987,12 +966,7 @@ describe.skip('Old Notes (~/notes.js)', () => {
expect($tempNote.attr('id')).toEqual(uniqueId);
expect($tempNote.hasClass('being-posted')).toBeTruthy();
expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- expect(
- $tempNote
- .find('.timeline-content i')
- .text()
- .trim(),
- ).toEqual(sampleCommandDescription);
+ expect($tempNote.find('.timeline-content i').text().trim()).toEqual(sampleCommandDescription);
});
});
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index c9912621785..f0e6a0a68dd 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -1,5 +1,6 @@
import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as actions from '~/notes/stores/actions';
@@ -8,7 +9,6 @@ import * as mutationTypes from '~/notes/stores/mutation_types';
import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub';
-import testAction from '../../helpers/vuex_action_helper';
import { resetStore } from '../helpers';
import {
discussionMock,
@@ -53,7 +53,7 @@ describe('Actions Notes Store', () => {
});
describe('setNotesData', () => {
- it('should set received notes data', done => {
+ it('should set received notes data', (done) => {
testAction(
actions.setNotesData,
notesDataMock,
@@ -66,7 +66,7 @@ describe('Actions Notes Store', () => {
});
describe('setNoteableData', () => {
- it('should set received issue data', done => {
+ it('should set received issue data', (done) => {
testAction(
actions.setNoteableData,
noteableDataMock,
@@ -79,7 +79,7 @@ describe('Actions Notes Store', () => {
});
describe('setUserData', () => {
- it('should set received user data', done => {
+ it('should set received user data', (done) => {
testAction(
actions.setUserData,
userDataMock,
@@ -92,7 +92,7 @@ describe('Actions Notes Store', () => {
});
describe('setLastFetchedAt', () => {
- it('should set received timestamp', done => {
+ it('should set received timestamp', (done) => {
testAction(
actions.setLastFetchedAt,
'timestamp',
@@ -105,7 +105,7 @@ describe('Actions Notes Store', () => {
});
describe('setInitialNotes', () => {
- it('should set initial notes', done => {
+ it('should set initial notes', (done) => {
testAction(
actions.setInitialNotes,
[individualNote],
@@ -118,7 +118,7 @@ describe('Actions Notes Store', () => {
});
describe('setTargetNoteHash', () => {
- it('should set target note hash', done => {
+ it('should set target note hash', (done) => {
testAction(
actions.setTargetNoteHash,
'hash',
@@ -131,7 +131,7 @@ describe('Actions Notes Store', () => {
});
describe('toggleDiscussion', () => {
- it('should toggle discussion', done => {
+ it('should toggle discussion', (done) => {
testAction(
actions.toggleDiscussion,
{ discussionId: discussionMock.id },
@@ -144,7 +144,7 @@ describe('Actions Notes Store', () => {
});
describe('expandDiscussion', () => {
- it('should expand discussion', done => {
+ it('should expand discussion', (done) => {
testAction(
actions.expandDiscussion,
{ discussionId: discussionMock.id },
@@ -157,7 +157,7 @@ describe('Actions Notes Store', () => {
});
describe('collapseDiscussion', () => {
- it('should commit collapse discussion', done => {
+ it('should commit collapse discussion', (done) => {
testAction(
actions.collapseDiscussion,
{ discussionId: discussionMock.id },
@@ -175,7 +175,7 @@ describe('Actions Notes Store', () => {
});
describe('closeMergeRequest', () => {
- it('sets state as closed', done => {
+ it('sets state as closed', (done) => {
store
.dispatch('closeIssuable', { notesData: { closeIssuePath: '' } })
.then(() => {
@@ -188,7 +188,7 @@ describe('Actions Notes Store', () => {
});
describe('reopenMergeRequest', () => {
- it('sets state as reopened', done => {
+ it('sets state as reopened', (done) => {
store
.dispatch('reopenIssuable', { notesData: { reopenIssuePath: '' } })
.then(() => {
@@ -203,7 +203,7 @@ describe('Actions Notes Store', () => {
describe('emitStateChangedEvent', () => {
it('emits an event on the document', () => {
- document.addEventListener('issuable_vue_app:change', event => {
+ document.addEventListener('issuable_vue_app:change', (event) => {
expect(event.detail.data).toEqual({ id: '1', state: 'closed' });
expect(event.detail.isClosed).toEqual(false);
});
@@ -213,7 +213,7 @@ describe('Actions Notes Store', () => {
});
describe('toggleStateButtonLoading', () => {
- it('should set loading as true', done => {
+ it('should set loading as true', (done) => {
testAction(
actions.toggleStateButtonLoading,
true,
@@ -224,7 +224,7 @@ describe('Actions Notes Store', () => {
);
});
- it('should set loading as false', done => {
+ it('should set loading as false', (done) => {
testAction(
actions.toggleStateButtonLoading,
false,
@@ -237,11 +237,11 @@ describe('Actions Notes Store', () => {
});
describe('toggleIssueLocalState', () => {
- it('sets issue state as closed', done => {
+ it('sets issue state as closed', (done) => {
testAction(actions.toggleIssueLocalState, 'closed', {}, [{ type: 'CLOSE_ISSUE' }], [], done);
});
- it('sets issue state as reopened', done => {
+ it('sets issue state as reopened', (done) => {
testAction(
actions.toggleIssueLocalState,
'reopened',
@@ -297,24 +297,21 @@ describe('Actions Notes Store', () => {
});
describe('poll', () => {
- beforeEach(done => {
+ beforeEach((done) => {
axiosMock
.onGet(notesDataMock.notesPath)
.reply(200, { notes: [], last_fetched_at: '123456' }, { 'poll-interval': '1000' });
- store
- .dispatch('setNotesData', notesDataMock)
- .then(done)
- .catch(done.fail);
+ store.dispatch('setNotesData', notesDataMock).then(done).catch(done.fail);
});
- it('calls service with last fetched state', done => {
+ it('calls service with last fetched state', (done) => {
store
.dispatch('poll')
.then(() => {
jest.advanceTimersByTime(2);
})
- .then(() => new Promise(resolve => requestAnimationFrame(resolve)))
+ .then(() => new Promise((resolve) => requestAnimationFrame(resolve)))
.then(() => {
expect(store.state.lastFetchedAt).toBe('123456');
@@ -322,7 +319,7 @@ describe('Actions Notes Store', () => {
})
.then(
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
requestAnimationFrame(resolve);
}),
)
@@ -340,7 +337,7 @@ describe('Actions Notes Store', () => {
});
describe('setNotesFetchedState', () => {
- it('should set notes fetched state', done => {
+ it('should set notes fetched state', (done) => {
testAction(
actions.setNotesFetchedState,
true,
@@ -367,7 +364,7 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
- it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', (done) => {
const note = { path: endpoint, id: 1 };
testAction(
@@ -392,7 +389,7 @@ describe('Actions Notes Store', () => {
);
});
- it('dispatches removeDiscussionsFromDiff on merge request page', done => {
+ it('dispatches removeDiscussionsFromDiff on merge request page', (done) => {
const note = { path: endpoint, id: 1 };
document.body.setAttribute('data-page', 'projects:merge_requests:show');
@@ -438,7 +435,7 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
- it('dispatches removeNote', done => {
+ it('dispatches removeNote', (done) => {
const note = { path: endpoint, id: 1 };
testAction(
@@ -471,7 +468,7 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().reply(200, res);
});
- it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
@@ -507,7 +504,7 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().replyOnce(200, res);
});
- it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', done => {
+ it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', (done) => {
testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
@@ -530,7 +527,7 @@ describe('Actions Notes Store', () => {
});
describe('as note', () => {
- it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', done => {
+ it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: false },
@@ -555,7 +552,7 @@ describe('Actions Notes Store', () => {
});
describe('as discussion', () => {
- it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', done => {
+ it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', (done) => {
testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: true },
@@ -591,7 +588,7 @@ describe('Actions Notes Store', () => {
});
describe('setCommentsDisabled', () => {
- it('should set comments disabled state', done => {
+ it('should set comments disabled state', (done) => {
testAction(
actions.setCommentsDisabled,
true,
@@ -604,7 +601,7 @@ describe('Actions Notes Store', () => {
});
describe('updateResolvableDiscussionsCounts', () => {
- it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', done => {
+ it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', (done) => {
testAction(
actions.updateResolvableDiscussionsCounts,
null,
@@ -617,7 +614,7 @@ describe('Actions Notes Store', () => {
});
describe('convertToDiscussion', () => {
- it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
const noteId = 'dummy-note-id';
testAction(
actions.convertToDiscussion,
@@ -721,7 +718,7 @@ describe('Actions Notes Store', () => {
describe('replyToDiscussion', () => {
const payload = { endpoint: TEST_HOST, data: {} };
- it('updates discussion if response contains disussion', done => {
+ it('updates discussion if response contains disussion', (done) => {
const discussion = { notes: [] };
axiosMock.onAny().reply(200, { discussion });
@@ -741,7 +738,7 @@ describe('Actions Notes Store', () => {
);
});
- it('adds a reply to a discussion', done => {
+ it('adds a reply to a discussion', (done) => {
const res = {};
axiosMock.onAny().reply(200, res);
@@ -759,7 +756,7 @@ describe('Actions Notes Store', () => {
});
describe('removeConvertedDiscussion', () => {
- it('commits CONVERT_TO_DISCUSSION with noteId', done => {
+ it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
const noteId = 'dummy-id';
testAction(
actions.removeConvertedDiscussion,
@@ -784,7 +781,7 @@ describe('Actions Notes Store', () => {
};
});
- it('when unresolved, dispatches action', done => {
+ it('when unresolved, dispatches action', (done) => {
testAction(
actions.resolveDiscussion,
{ discussionId },
@@ -804,8 +801,8 @@ describe('Actions Notes Store', () => {
);
});
- it('when resolved, does nothing', done => {
- getters.isDiscussionResolved = id => id === discussionId;
+ it('when resolved, does nothing', (done) => {
+ getters.isDiscussionResolved = (id) => id === discussionId;
testAction(
actions.resolveDiscussion,
@@ -826,7 +823,7 @@ describe('Actions Notes Store', () => {
const res = { errors: { something: ['went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
- it('throws an error', done => {
+ it('throws an error', (done) => {
actions
.saveNote(
{
@@ -836,7 +833,7 @@ describe('Actions Notes Store', () => {
payload,
)
.then(() => done.fail('Expected error to be thrown!'))
- .catch(err => {
+ .catch((err) => {
expect(err).toBe(error);
expect(Flash).not.toHaveBeenCalled();
})
@@ -849,7 +846,7 @@ describe('Actions Notes Store', () => {
const res = { errors: { base: ['something went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
- it('sets flash alert using errors.base message', done => {
+ it('sets flash alert using errors.base message', (done) => {
actions
.saveNote(
{
@@ -858,7 +855,7 @@ describe('Actions Notes Store', () => {
},
{ ...payload, flashContainer },
)
- .then(resp => {
+ .then((resp) => {
expect(resp.hasFlash).toBe(true);
expect(Flash).toHaveBeenCalledWith(
'Your comment could not be submitted because something went wrong',
@@ -875,7 +872,7 @@ describe('Actions Notes Store', () => {
describe('if response contains no errors', () => {
const res = { valid: true };
- it('returns the response', done => {
+ it('returns the response', (done) => {
actions
.saveNote(
{
@@ -884,7 +881,7 @@ describe('Actions Notes Store', () => {
},
payload,
)
- .then(data => {
+ .then((data) => {
expect(data).toBe(res);
expect(Flash).not.toHaveBeenCalled();
})
@@ -917,11 +914,10 @@ describe('Actions Notes Store', () => {
.catch(done.fail);
};
- it('when service success, commits and resolves discussion', done => {
+ it('when service success, commits and resolves discussion', (done) => {
testSubmitSuggestion(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]);
@@ -934,7 +930,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, flashes error message', done => {
+ it('when service fails, flashes error message', (done) => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
@@ -949,7 +945,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, and no error message available, uses default message', done => {
+ it('when service fails, and no error message available, uses default message', (done) => {
const response = { response: 'foo' };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
@@ -968,7 +964,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when resolve discussion fails, fail gracefully', done => {
+ it('when resolve discussion fails, fail gracefully', (done) => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestion(done, () => {
@@ -999,13 +995,11 @@ describe('Actions Notes Store', () => {
.catch(done.fail);
};
- it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', done => {
+ it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', (done) => {
testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
@@ -1022,7 +1016,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, flashes error message, resets applying batch state', done => {
+ it('when service fails, flashes error message, resets applying batch state', (done) => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
@@ -1040,7 +1034,7 @@ describe('Actions Notes Store', () => {
});
});
- it('when service fails, and no error message available, uses default message', done => {
+ it('when service fails, and no error message available, uses default message', (done) => {
const response = { response: 'foo' };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
@@ -1062,15 +1056,13 @@ describe('Actions Notes Store', () => {
});
});
- it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', done => {
+ it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', (done) => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
- [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
@@ -1084,7 +1076,7 @@ describe('Actions Notes Store', () => {
describe('addSuggestionInfoToBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
- it("adds a suggestion's info to the current batch", done => {
+ it("adds a suggestion's info to the current batch", (done) => {
testAction(
actions.addSuggestionInfoToBatch,
suggestionInfo,
@@ -1099,7 +1091,7 @@ describe('Actions Notes Store', () => {
describe('removeSuggestionInfoFromBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
- it("removes a suggestion's info the current batch", done => {
+ it("removes a suggestion's info the current batch", (done) => {
testAction(
actions.removeSuggestionInfoFromBatch,
suggestionInfo.suggestionId,
@@ -1139,7 +1131,7 @@ describe('Actions Notes Store', () => {
});
describe('setDiscussionSortDirection', () => {
- it('calls the correct mutation with the correct args', done => {
+ it('calls the correct mutation with the correct args', (done) => {
testAction(
actions.setDiscussionSortDirection,
{ direction: notesConstants.DESC, persist: false },
@@ -1157,7 +1149,7 @@ describe('Actions Notes Store', () => {
});
describe('setSelectedCommentPosition', () => {
- it('calls the correct mutation with the correct args', done => {
+ it('calls the correct mutation with the correct args', (done) => {
testAction(
actions.setSelectedCommentPosition,
{},
@@ -1178,7 +1170,7 @@ describe('Actions Notes Store', () => {
};
describe('if response contains no errors', () => {
- it('dispatches requestDeleteDescriptionVersion', done => {
+ it('dispatches requestDeleteDescriptionVersion', (done) => {
axiosMock.onDelete(endpoint).replyOnce(200);
testAction(
actions.softDeleteDescriptionVersion,
@@ -1201,7 +1193,7 @@ describe('Actions Notes Store', () => {
describe('if response contains errors', () => {
const errorMessage = 'Request failed with status code 503';
- it('dispatches receiveDeleteDescriptionVersionError and throws an error', done => {
+ it('dispatches receiveDeleteDescriptionVersionError and throws an error', (done) => {
axiosMock.onDelete(endpoint).replyOnce(503);
testAction(
actions.softDeleteDescriptionVersion,
@@ -1236,7 +1228,7 @@ describe('Actions Notes Store', () => {
});
describe('updateAssignees', () => {
- it('update the assignees state', done => {
+ it('update the assignees state', (done) => {
testAction(
actions.updateAssignees,
[userDataMock.id],
@@ -1351,7 +1343,7 @@ describe('Actions Notes Store', () => {
});
describe('updateDiscussionPosition', () => {
- it('update the assignees state', done => {
+ it('update the assignees state', (done) => {
const updatedPosition = { discussionId: 1, position: { test: true } };
testAction(
actions.updateDiscussionPosition,
diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js
index 1a369caee49..fd04d08b6a5 100644
--- a/spec/frontend/notes/stores/getters_spec.js
+++ b/spec/frontend/notes/stores/getters_spec.js
@@ -72,7 +72,7 @@ describe('Getters Notes Store', () => {
state.isTimelineEnabled = true;
expect(getters.discussions(state).length).toEqual(discussionMock.notes.length);
- getters.discussions(state).forEach(discussion => {
+ getters.discussions(state).forEach((discussion) => {
expect(discussion.individual_note).toBe(true);
expect(discussion.id).toBe(discussion.notes[0].id);
expect(discussion.created_at).toBe(discussion.notes[0].created_at);
@@ -298,17 +298,18 @@ describe('Getters Notes Store', () => {
};
});
- [{ step: 1, id: '123', expected: '123' }, { step: -1, id: '123', expected: '123' }].forEach(
- ({ step, id, expected }) => {
- it(`with step ${step} and match, returns only value`, () => {
- const params = createDiscussionNeighborParams(id, true, step);
-
- expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe(
- expected,
- );
- });
- },
- );
+ [
+ { step: 1, id: '123', expected: '123' },
+ { step: -1, id: '123', expected: '123' },
+ ].forEach(({ step, id, expected }) => {
+ it(`with step ${step} and match, returns only value`, () => {
+ const params = createDiscussionNeighborParams(id, true, step);
+
+ expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe(
+ expected,
+ );
+ });
+ });
it('with no match, returns only value', () => {
const params = createDiscussionNeighborParams('bogus', true, 1);
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index ec4de925721..66fc74525ad 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -357,7 +357,7 @@ describe('Notes Store mutations', () => {
mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: true });
- state.discussions.forEach(discussion => {
+ state.discussions.forEach((discussion) => {
expect(discussion.expanded).toEqual(true);
});
});
@@ -371,7 +371,7 @@ describe('Notes Store mutations', () => {
mutations.SET_EXPAND_DISCUSSIONS(state, { discussionIds, expanded: false });
- state.discussions.forEach(discussion => {
+ state.discussions.forEach((discussion) => {
expect(discussion.expanded).toEqual(false);
});
});
@@ -698,7 +698,7 @@ describe('Notes Store mutations', () => {
});
describe('SET_APPLYING_BATCH_STATE', () => {
- const buildDiscussions = suggestionsInfo => {
+ const buildDiscussions = (suggestionsInfo) => {
const suggestions = suggestionsInfo.map(({ suggestionId }) => ({ id: suggestionId }));
const notes = suggestionsInfo.map(({ noteId }, index) => ({
@@ -738,7 +738,7 @@ describe('Notes Store mutations', () => {
const expectedSuggestions = [updatedSuggestion, suggestions[1]];
const actualSuggestions = state.discussions
- .map(discussion => discussion.notes.map(n => n.suggestions))
+ .map((discussion) => discussion.notes.map((n) => n.suggestions))
.flat(2);
expect(actualSuggestions).toEqual(expectedSuggestions);