diff options
Diffstat (limited to 'spec/frontend/notes')
-rw-r--r-- | spec/frontend/notes/components/discussion_actions_spec.js | 14 | ||||
-rw-r--r-- | spec/frontend/notes/components/discussion_filter_spec.js | 5 | ||||
-rw-r--r-- | spec/frontend/notes/components/discussion_navigator_spec.js (renamed from spec/frontend/notes/components/discussion_keyboard_navigator_spec.js) | 38 | ||||
-rw-r--r-- | spec/frontend/notes/components/discussion_notes_spec.js | 47 | ||||
-rw-r--r-- | spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/notes/components/note_actions_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/notes/components/note_awards_list_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/notes/components/noteable_discussion_spec.js | 21 | ||||
-rw-r--r-- | spec/frontend/notes/components/noteable_note_spec.js | 38 | ||||
-rw-r--r-- | spec/frontend/notes/mixins/discussion_navigation_spec.js | 31 | ||||
-rw-r--r-- | spec/frontend/notes/stores/actions_spec.js | 85 | ||||
-rw-r--r-- | spec/frontend/notes/stores/mutation_spec.js | 32 |
12 files changed, 281 insertions, 38 deletions
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js index 44dc148933c..3e1e43d0c6a 100644 --- a/spec/frontend/notes/components/discussion_actions_spec.js +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -21,7 +21,7 @@ const createUnallowedNote = () => describe('DiscussionActions', () => { let wrapper; - const createComponentFactory = (shallow = true) => props => { + const createComponentFactory = (shallow = true) => (props, options) => { const store = createStore(); const mountFn = shallow ? shallowMount : mount; @@ -35,6 +35,11 @@ describe('DiscussionActions', () => { shouldShowJumpToNextDiscussion: true, ...props, }, + provide: { + glFeatures: { + hideJumpToNextUnresolvedInThreads: options?.hideJumpToNextUnresolvedInThreads, + }, + }, }); }; @@ -96,6 +101,13 @@ 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); diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js index 7f042c0e9de..9a7896475e6 100644 --- a/spec/frontend/notes/components/discussion_filter_spec.js +++ b/spec/frontend/notes/components/discussion_filter_spec.js @@ -1,8 +1,8 @@ -import createEventHub from '~/helpers/event_hub_factory'; 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 createEventHub from '~/helpers/event_hub_factory'; import axios from '~/lib/utils/axios_utils'; import notesModule from '~/notes/stores/modules'; @@ -10,7 +10,6 @@ import DiscussionFilter from '~/notes/components/discussion_filter.vue'; import { DISCUSSION_FILTERS_DEFAULT_VALUE, DISCUSSION_FILTER_TYPES } from '~/notes/constants'; import { discussionFiltersMock, discussionMock } from '../mock_data'; -import { TEST_HOST } from 'jest/helpers/test_constants'; const localVue = createLocalVue(); diff --git a/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js b/spec/frontend/notes/components/discussion_navigator_spec.js index e932133b869..122814b8e3f 100644 --- a/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js +++ b/spec/frontend/notes/components/discussion_navigator_spec.js @@ -1,9 +1,11 @@ /* global Mousetrap */ import 'mousetrap'; +import Vue from 'vue'; import { shallowMount, createLocalVue } from '@vue/test-utils'; -import DiscussionKeyboardNavigator from '~/notes/components/discussion_keyboard_navigator.vue'; +import DiscussionNavigator from '~/notes/components/discussion_navigator.vue'; +import eventHub from '~/notes/event_hub'; -describe('notes/components/discussion_keyboard_navigator', () => { +describe('notes/components/discussion_navigator', () => { const localVue = createLocalVue(); let wrapper; @@ -11,7 +13,7 @@ describe('notes/components/discussion_keyboard_navigator', () => { let jumpToPreviousDiscussion; const createComponent = () => { - wrapper = shallowMount(DiscussionKeyboardNavigator, { + wrapper = shallowMount(DiscussionNavigator, { mixins: [ localVue.extend({ methods: { @@ -29,10 +31,29 @@ describe('notes/components/discussion_keyboard_navigator', () => { }); afterEach(() => { - wrapper.destroy(); + if (wrapper) { + wrapper.destroy(); + } wrapper = null; }); + describe('on create', () => { + let onSpy; + let vm; + + beforeEach(() => { + onSpy = jest.spyOn(eventHub, '$on'); + vm = new (Vue.extend(DiscussionNavigator))(); + }); + + it('listens for jumpToFirstUnresolvedDiscussion events', () => { + expect(onSpy).toHaveBeenCalledWith( + 'jumpToFirstUnresolvedDiscussion', + vm.jumpToFirstUnresolvedDiscussion, + ); + }); + }); + describe('on mount', () => { beforeEach(() => { createComponent(); @@ -52,11 +73,16 @@ describe('notes/components/discussion_keyboard_navigator', () => { }); describe('on destroy', () => { + let jumpFn; + beforeEach(() => { jest.spyOn(Mousetrap, 'unbind'); + jest.spyOn(eventHub, '$off'); createComponent(); + jumpFn = wrapper.vm.jumpToFirstUnresolvedDiscussion; + wrapper.destroy(); }); @@ -65,6 +91,10 @@ describe('notes/components/discussion_keyboard_navigator', () => { expect(Mousetrap.unbind).toHaveBeenCalledWith('p'); }); + it('unbinds event hub listeners', () => { + expect(eventHub.$off).toHaveBeenCalledWith('jumpToFirstUnresolvedDiscussion', jumpFn); + }); + it('does not call jumpToNextDiscussion when pressing `n`', () => { Mousetrap.trigger('n'); diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js index 5a10deefd09..8cc98f978c2 100644 --- a/spec/frontend/notes/components/discussion_notes_spec.js +++ b/spec/frontend/notes/components/discussion_notes_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { getByRole } from '@testing-library/dom'; import '~/behaviors/markdown/render_gfm'; import { SYSTEM_NOTE } from '~/notes/constants'; import DiscussionNotes from '~/notes/components/discussion_notes.vue'; @@ -9,14 +10,20 @@ import SystemNote from '~/vue_shared/components/notes/system_note.vue'; import createStore from '~/notes/stores'; import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data'; +const LINE_RANGE = {}; +const DISCUSSION_WITH_LINE_RANGE = { + ...discussionMock, + position: { + line_range: LINE_RANGE, + }, +}; + describe('DiscussionNotes', () => { + let store; let wrapper; - const createComponent = props => { - const store = createStore(); - store.dispatch('setNoteableData', noteableDataMock); - store.dispatch('setNotesData', notesDataMock); - + const getList = () => getByRole(wrapper.element, 'list'); + const createComponent = (props, features = {}) => { wrapper = shallowMount(DiscussionNotes, { store, propsData: { @@ -31,11 +38,21 @@ describe('DiscussionNotes', () => { slots: { 'avatar-badge': '<span class="avatar-badge-slot-content" />', }, + provide: { + glFeatures: { multilineComments: true, ...features }, + }, }); }; + beforeEach(() => { + store = createStore(); + store.dispatch('setNoteableData', noteableDataMock); + store.dispatch('setNotesData', notesDataMock); + }); + afterEach(() => { wrapper.destroy(); + wrapper = null; }); describe('rendering', () => { @@ -160,6 +177,26 @@ describe('DiscussionNotes', () => { }); }); + describe.each` + desc | props | features | event | expectedCalls + ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]} + ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]} + ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]} + ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]} + ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]} + ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]} + `('$desc and features $features', ({ props, event, features, expectedCalls }) => { + beforeEach(() => { + createComponent(props, features); + jest.spyOn(store, 'dispatch'); + }); + + it(`calls store ${expectedCalls.length} times on ${event}`, () => { + getList().dispatchEvent(new MouseEvent(event)); + expect(store.dispatch.mock.calls).toEqual(expectedCalls); + }); + }); + describe('componentData', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js index e62fb5db2c0..4348445f7ca 100644 --- a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js +++ b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js @@ -1,4 +1,4 @@ -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import { TEST_HOST } from 'spec/test_constants'; import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; @@ -23,7 +23,7 @@ describe('ResolveWithIssueButton', () => { }); it('it should have a link with the provided link property as href', () => { - const button = wrapper.find(GlDeprecatedButton); + const button = wrapper.find(GlButton); expect(button.attributes().href).toBe(url); }); diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js index 5cc56cdefae..97d1752726b 100644 --- a/spec/frontend/notes/components/note_actions_spec.js +++ b/spec/frontend/notes/components/note_actions_spec.js @@ -1,10 +1,10 @@ import Vue from 'vue'; import { shallowMount, createLocalVue, createWrapper } from '@vue/test-utils'; import { TEST_HOST } from 'spec/test_constants'; +import AxiosMockAdapter from 'axios-mock-adapter'; import createStore from '~/notes/stores'; import noteActions from '~/notes/components/note_actions.vue'; import { userDataMock } from '../mock_data'; -import AxiosMockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; describe('noteActions', () => { diff --git a/spec/frontend/notes/components/note_awards_list_spec.js b/spec/frontend/notes/components/note_awards_list_spec.js index 822b1f9efce..dce5424f154 100644 --- a/spec/frontend/notes/components/note_awards_list_spec.js +++ b/spec/frontend/notes/components/note_awards_list_spec.js @@ -1,10 +1,10 @@ import Vue from 'vue'; import AxiosMockAdapter from 'axios-mock-adapter'; +import { TEST_HOST } from 'jest/helpers/test_constants'; import axios from '~/lib/utils/axios_utils'; import createStore from '~/notes/stores'; import awardsNote from '~/notes/components/note_awards_list.vue'; import { noteableDataMock, notesDataMock } from '../mock_data'; -import { TEST_HOST } from 'jest/helpers/test_constants'; describe('note_awards_list component', () => { let store; diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js index b14ec2a65be..1c6603899d3 100644 --- a/spec/frontend/notes/components/noteable_discussion_spec.js +++ b/spec/frontend/notes/components/noteable_discussion_spec.js @@ -1,4 +1,6 @@ import { mount, createLocalVue } 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 ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; @@ -12,8 +14,6 @@ import { loggedOutnoteableData, userDataMock, } from '../mock_data'; -import mockDiffFile from 'jest/diffs/mock_data/diff_file'; -import { trimText } from 'helpers/text_helper'; const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; @@ -89,6 +89,23 @@ describe('noteable_discussion component', () => { }); }); + it('should expand discussion', async () => { + const expandDiscussion = jest.fn(); + const discussion = { ...discussionMock }; + discussion.expanded = false; + + wrapper.setProps({ discussion }); + wrapper.setMethods({ expandDiscussion }); + + await wrapper.vm.$nextTick(); + + wrapper.vm.showReplyForm(); + + await wrapper.vm.$nextTick(); + + expect(expandDiscussion).toHaveBeenCalledWith({ discussionId: discussion.id }); + }); + it('does not render jump to thread button', () => { expect(wrapper.find('*[data-original-title="Jump to next unresolved thread"]').exists()).toBe( false, diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js index fc238feb974..a08e86d92d3 100644 --- a/spec/frontend/notes/components/noteable_note_spec.js +++ b/spec/frontend/notes/components/noteable_note_spec.js @@ -83,18 +83,34 @@ describe('issue_note', () => { }); }); - it('should render multiline comment if editing discussion root', () => { - wrapper.setProps({ discussionRoot: true }); - wrapper.vm.isEditing = true; - - return wrapper.vm.$nextTick().then(() => { - expect(findMultilineComment().exists()).toBe(true); + it('should only render if it has everything it needs', () => { + const position = { + line_range: { + start: { + line_code: 'abc_1_1', + type: null, + old_line: '', + new_line: '', + }, + end: { + line_code: 'abc_2_2', + type: null, + old_line: '2', + new_line: '2', + }, + }, + }; + const line = { + line_code: 'abc_1_1', + type: null, + old_line: '1', + new_line: '1', + }; + wrapper.setProps({ + note: { ...note, position }, + discussionRoot: true, + line, }); - }); - - it('should not render multiline comment form unless it is the discussion root', () => { - wrapper.setProps({ discussionRoot: false }); - wrapper.vm.isEditing = true; return wrapper.vm.$nextTick().then(() => { expect(findMultilineComment().exists()).toBe(false); diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js index ecff95b6fe0..11c0bbfefc9 100644 --- a/spec/frontend/notes/mixins/discussion_navigation_spec.js +++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js @@ -1,11 +1,11 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { setHTMLFixture } from 'helpers/fixtures'; import * as utils from '~/lib/utils/common_utils'; import discussionNavigation from '~/notes/mixins/discussion_navigation'; import eventHub from '~/notes/event_hub'; import createEventHub from '~/helpers/event_hub_factory'; import notesModule from '~/notes/stores/modules'; -import { setHTMLFixture } from 'helpers/fixtures'; const discussion = (id, index) => ({ id, @@ -66,6 +66,35 @@ describe('Discussion navigation mixin', () => { const findDiscussion = (selector, id) => document.querySelector(`${selector}[data-discussion-id="${id}"]`); + describe('jumpToFirstUnresolvedDiscussion method', () => { + let vm; + + beforeEach(() => { + createComponent(); + + ({ vm } = wrapper); + + jest.spyOn(store, 'dispatch'); + jest.spyOn(vm, 'jumpToNextDiscussion'); + }); + + it('triggers the setCurrentDiscussionId action with null as the value', () => { + vm.jumpToFirstUnresolvedDiscussion(); + + expect(store.dispatch).toHaveBeenCalledWith('setCurrentDiscussionId', null); + }); + + it('triggers the jumpToNextDiscussion action when the previous store action succeeds', () => { + store.dispatch.mockResolvedValue(); + + vm.jumpToFirstUnresolvedDiscussion(); + + return vm.$nextTick().then(() => { + expect(vm.jumpToNextDiscussion).toHaveBeenCalled(); + }); + }); + }); + describe('cycle through discussions', () => { beforeEach(() => { window.mrTabs = { eventHub: createEventHub(), tabShown: jest.fn() }; diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index 909a4a797ae..6b8d0790669 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -1,7 +1,7 @@ import { TEST_HOST } from 'spec/test_constants'; import AxiosMockAdapter from 'axios-mock-adapter'; import Api from '~/api'; -import Flash from '~/flash'; +import { deprecatedCreateFlash as Flash } from '~/flash'; import * as actions from '~/notes/stores/actions'; import * as mutationTypes from '~/notes/stores/mutation_types'; import * as notesConstants from '~/notes/constants'; @@ -19,7 +19,9 @@ import { } from '../mock_data'; import axios from '~/lib/utils/axios_utils'; import * as utils from '~/notes/stores/utils'; -import updateIssueConfidentialMutation from '~/sidebar/components/confidential/queries/update_issue_confidential.mutation.graphql'; +import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql'; +import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql'; +import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql'; const TEST_ERROR_MESSAGE = 'Test error message'; jest.mock('~/flash'); @@ -1219,7 +1221,7 @@ describe('Actions Notes Store', () => { }); }); - describe('updateConfidentialityOnIssue', () => { + describe('updateConfidentialityOnIssuable', () => { state = { noteableData: { confidential: false } }; const iid = '1'; const projectPath = 'full/path'; @@ -1234,13 +1236,13 @@ describe('Actions Notes Store', () => { }); it('calls gqClient mutation one time', () => { - actions.updateConfidentialityOnIssue({ commit: () => {}, state, getters }, actionArgs); + actions.updateConfidentialityOnIssuable({ commit: () => {}, state, getters }, actionArgs); expect(utils.gqClient.mutate).toHaveBeenCalledTimes(1); }); it('calls gqClient mutation with the correct values', () => { - actions.updateConfidentialityOnIssue({ commit: () => {}, state, getters }, actionArgs); + actions.updateConfidentialityOnIssuable({ commit: () => {}, state, getters }, actionArgs); expect(utils.gqClient.mutate).toHaveBeenCalledWith({ mutation: updateIssueConfidentialMutation, @@ -1253,7 +1255,7 @@ describe('Actions Notes Store', () => { const commitSpy = jest.fn(); return actions - .updateConfidentialityOnIssue({ commit: commitSpy, state, getters }, actionArgs) + .updateConfidentialityOnIssuable({ commit: commitSpy, state, getters }, actionArgs) .then(() => { expect(commitSpy).toHaveBeenCalledWith( mutationTypes.SET_ISSUE_CONFIDENTIAL, @@ -1263,4 +1265,75 @@ describe('Actions Notes Store', () => { }); }); }); + + describe.each` + issuableType + ${'issue'} | ${'merge_request'} + `('updateLockedAttribute for issuableType=$issuableType', ({ issuableType }) => { + // Payload for mutation query + state = { noteableData: { discussion_locked: false } }; + const targetType = issuableType; + const getters = { getNoteableData: { iid: '1', targetType } }; + + // Target state after mutation + const locked = true; + const actionArgs = { fullPath: 'full/path', locked }; + const input = { iid: '1', projectPath: 'full/path', locked: true }; + + // Helper functions + const targetMutation = () => { + return targetType === 'issue' ? updateIssueLockMutation : updateMergeRequestLockMutation; + }; + + const mockResolvedValue = () => { + return targetType === 'issue' + ? { data: { issueSetLocked: { issue: { discussionLocked: locked } } } } + : { data: { mergeRequestSetLocked: { mergeRequest: { discussionLocked: locked } } } }; + }; + + beforeEach(() => { + jest.spyOn(utils.gqClient, 'mutate').mockResolvedValue(mockResolvedValue()); + }); + + it('calls gqClient mutation one time', () => { + actions.updateLockedAttribute({ commit: () => {}, state, getters }, actionArgs); + + expect(utils.gqClient.mutate).toHaveBeenCalledTimes(1); + }); + + it('calls gqClient mutation with the correct values', () => { + actions.updateLockedAttribute({ commit: () => {}, state, getters }, actionArgs); + + expect(utils.gqClient.mutate).toHaveBeenCalledWith({ + mutation: targetMutation(), + variables: { input }, + }); + }); + + describe('on success of mutation', () => { + it('calls commit with the correct values', () => { + const commitSpy = jest.fn(); + + return actions + .updateLockedAttribute({ commit: commitSpy, state, getters }, actionArgs) + .then(() => { + expect(commitSpy).toHaveBeenCalledWith(mutationTypes.SET_ISSUABLE_LOCK, locked); + }); + }); + }); + }); + + describe('updateDiscussionPosition', () => { + it('update the assignees state', done => { + const updatedPosition = { discussionId: 1, position: { test: true } }; + testAction( + actions.updateDiscussionPosition, + updatedPosition, + { state: { discussions: [] } }, + [{ type: mutationTypes.UPDATE_DISCUSSION_POSITION, payload: updatedPosition }], + [], + done, + ); + }); + }); }); diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js index 0ad18ba9b6a..b953bffc4fe 100644 --- a/spec/frontend/notes/stores/mutation_spec.js +++ b/spec/frontend/notes/stores/mutation_spec.js @@ -833,13 +833,27 @@ describe('Notes Store mutations', () => { state = { noteableData: { confidential: false } }; }); - it('sets sort order', () => { + it('should set issuable as confidential', () => { mutations.SET_ISSUE_CONFIDENTIAL(state, true); expect(state.noteableData.confidential).toBe(true); }); }); + describe('SET_ISSUABLE_LOCK', () => { + let state; + + beforeEach(() => { + state = { noteableData: { discussion_locked: false } }; + }); + + it('should set issuable as locked', () => { + mutations.SET_ISSUABLE_LOCK(state, true); + + expect(state.noteableData.discussion_locked).toBe(true); + }); + }); + describe('UPDATE_ASSIGNEES', () => { it('should update assignees', () => { const state = { @@ -851,4 +865,20 @@ describe('Notes Store mutations', () => { expect(state.noteableData.assignees).toEqual([userDataMock.id]); }); }); + + describe('UPDATE_DISCUSSION_POSITION', () => { + it('should upate the discusion position', () => { + const discussion1 = { id: 1, position: { line_code: 'abc_1_1' } }; + const discussion2 = { id: 2, position: { line_code: 'abc_2_2' } }; + const discussion3 = { id: 3, position: { line_code: 'abc_3_3' } }; + const state = { + discussions: [discussion1, discussion2, discussion3], + }; + const discussion1Position = { ...discussion1.position }; + const position = { ...discussion1Position, test: true }; + + mutations.UPDATE_DISCUSSION_POSITION(state, { discussionId: discussion1.id, position }); + expect(state.discussions[0].position).toEqual(position); + }); + }); }); |