From b00d32188ba0af16e05f2dfd3d20a03f23f06b31 Mon Sep 17 00:00:00 2001
From: Stanislav Lashmanov <slashmanov@gitlab.com>
Date: Tue, 11 Feb 2025 09:51:57 +0000
Subject: [PATCH] Migrate components using Batch comments Vuex store to Pinia

---
 .../components/diff_file_drafts.vue           |   6 +-
 .../batch_comments/components/draft_note.vue  |  13 ++-
 .../components/drafts_count.vue               |   6 +-
 .../components/preview_dropdown.vue           |  18 ++-
 .../batch_comments/components/review_bar.vue  |  10 +-
 .../components/submit_dropdown.vue            |  19 +++-
 .../javascripts/batch_comments/index.js       |   8 +-
 .../javascripts/batch_comments/store/index.js |   2 +-
 .../javascripts/batch_comments/store/state.js |   9 --
 .../stores/modules/batch_comments/state.js    |   2 +-
 .../javascripts/diffs/components/app.vue      |  10 --
 .../diffs/components/tree_list_height.vue     |   7 +-
 .../diffs/mixins/draft_comments.js            |   6 +-
 app/assets/javascripts/mr_notes/init.js       |  11 ++
 .../notes/components/note_form.vue            |  15 ++-
 app/assets/javascripts/notes/index.js         |   2 +
 .../notes/mixins/diff_line_note_form.js       |  27 +++--
 app/assets/javascripts/pinia/instance.js      |   3 +-
 .../components/submit_dropdown_spec.js        |  16 +++
 .../components/diff_line_note_form_spec.js    |  20 +++-
 .../notes/components/note_form_spec.js        |  27 ++++-
 .../components/diff_file_drafts_spec.js       |  43 +++----
 .../components/draft_note_spec.js             |  36 +++---
 .../components/drafts_count_spec.js           |  23 ++--
 .../components/preview_dropdown_spec.js       | 105 +++++++++++-------
 .../components/publish_dropdown_spec.js       |  17 ++-
 .../components/review_bar_spec.js             |  12 +-
 .../components/submit_dropdown_spec.js        |  33 +++---
 .../diffs/components/diff_content_spec.js     |  44 +++++---
 .../diffs/components/diff_discussions_spec.js |  16 +++
 .../diffs/components/diff_view_spec.js        |  47 +++++---
 .../notes/components/note_form_spec.js        |  22 +++-
 .../components/noteable_discussion_spec.js    |  18 ++-
 .../notes/components/notes_app_spec.js        |  13 +++
 34 files changed, 443 insertions(+), 223 deletions(-)
 delete mode 100644 app/assets/javascripts/batch_comments/store/state.js

diff --git a/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue b/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
index 671cb8f7f4791..b16f903f8514a 100644
--- a/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
+++ b/app/assets/javascripts/batch_comments/components/diff_file_drafts.vue
@@ -1,8 +1,8 @@
 <script>
-// eslint-disable-next-line no-restricted-imports
-import { mapGetters } from 'vuex';
+import { mapState } from 'pinia';
 import imageDiff from '~/diffs/mixins/image_diff';
 import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
+import { useBatchComments } from '~/batch_comments/store';
 import DraftNote from './draft_note.vue';
 
 export default {
@@ -33,7 +33,7 @@ export default {
     },
   },
   computed: {
-    ...mapGetters('batchComments', ['draftsForFile']),
+    ...mapState(useBatchComments, ['draftsForFile']),
     drafts() {
       return this.draftsForFile(this.fileHash).filter(
         (f) => f.position?.position_type === this.positionType,
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index c015aa0affce4..051ea16459936 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,11 +1,13 @@
 <script>
 import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
 // eslint-disable-next-line no-restricted-imports
-import { mapActions, mapGetters, mapMutations, mapState } from 'vuex';
+import { mapActions as mapVuexActions } from 'vuex';
+import { mapActions, mapState } from 'pinia';
 import SafeHtml from '~/vue_shared/directives/safe_html';
 import NoteableNote from '~/notes/components/noteable_note.vue';
 import * as types from '~/batch_comments/stores/modules/batch_comments/mutation_types';
 import { clearDraft } from '~/lib/utils/autosave';
+import { useBatchComments } from '~/batch_comments/store';
 
 export default {
   components: {
@@ -43,8 +45,7 @@ export default {
     };
   },
   computed: {
-    ...mapState('batchComments', ['isPublishing']),
-    ...mapGetters('batchComments', ['isPublishingDraft']),
+    ...mapState(useBatchComments, ['isPublishing', 'isPublishingDraft']),
     draftCommands() {
       return this.draft.references.commands;
     },
@@ -59,17 +60,17 @@ export default {
     }
   },
   methods: {
-    ...mapActions('batchComments', [
+    ...mapActions(useBatchComments, [
       'deleteDraft',
       'updateDraft',
       'publishSingleDraft',
       'scrollToDraft',
       'toggleResolveDiscussion',
     ]),
-    ...mapMutations('batchComments', {
+    ...mapActions(useBatchComments, {
       setDraftEditing: types.SET_DRAFT_EDITING,
     }),
-    ...mapActions(['setSelectedCommentPositionHover']),
+    ...mapVuexActions(['setSelectedCommentPositionHover']),
     update(data) {
       this.updateDraft(data);
     },
diff --git a/app/assets/javascripts/batch_comments/components/drafts_count.vue b/app/assets/javascripts/batch_comments/components/drafts_count.vue
index 2430b5e5a5a65..d857b89f0fc84 100644
--- a/app/assets/javascripts/batch_comments/components/drafts_count.vue
+++ b/app/assets/javascripts/batch_comments/components/drafts_count.vue
@@ -1,7 +1,7 @@
 <script>
 import { GlBadge } from '@gitlab/ui';
-// eslint-disable-next-line no-restricted-imports
-import { mapGetters } from 'vuex';
+import { mapState } from 'pinia';
+import { useBatchComments } from '~/batch_comments/store';
 
 export default {
   components: {
@@ -15,7 +15,7 @@ export default {
     },
   },
   computed: {
-    ...mapGetters('batchComments', ['draftsCount']),
+    ...mapState(useBatchComments, ['draftsCount']),
   },
 };
 </script>
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index 63b536a76047f..93c394943befd 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -1,8 +1,14 @@
 <script>
 import { GlIcon, GlDisclosureDropdown, GlButton } from '@gitlab/ui';
+import { mapState, mapActions } from 'pinia';
 // eslint-disable-next-line no-restricted-imports
-import { mapActions, mapGetters, mapState } from 'vuex';
+import {
+  mapActions as mapVuexActions,
+  mapGetters as mapVuexGetters,
+  mapState as mapVuexState,
+} from 'vuex';
 import { setUrlParams, visitUrl } from '~/lib/utils/url_utility';
+import { useBatchComments } from '~/batch_comments/store';
 import PreviewItem from './preview_item.vue';
 import DraftsCount from './drafts_count.vue';
 
@@ -15,9 +21,9 @@ export default {
     GlButton,
   },
   computed: {
-    ...mapState('diffs', ['viewDiffsFileByFile']),
-    ...mapGetters('batchComments', ['draftsCount', 'sortedDrafts']),
-    ...mapGetters(['getNoteableData']),
+    ...mapVuexState('diffs', ['viewDiffsFileByFile']),
+    ...mapState(useBatchComments, ['draftsCount', 'sortedDrafts']),
+    ...mapVuexGetters(['getNoteableData']),
     listItems() {
       const sortedDraftCount = this.sortedDrafts.length - 1;
       return this.sortedDrafts.map((item, index) => ({
@@ -31,8 +37,8 @@ export default {
     },
   },
   methods: {
-    ...mapActions('diffs', ['goToFile']),
-    ...mapActions('batchComments', ['scrollToDraft']),
+    ...mapVuexActions('diffs', ['goToFile']),
+    ...mapActions(useBatchComments, ['scrollToDraft']),
     isOnLatestDiff(draft) {
       return draft.position?.head_sha === this.getNoteableData.diff_head_sha;
     },
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 46906a5a2a89b..9406090cede6c 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -1,10 +1,12 @@
 <script>
+import { mapActions } from 'pinia';
 // eslint-disable-next-line no-restricted-imports
-import { mapActions, mapGetters } from 'vuex';
+import { mapGetters as mapVuexGetters } from 'vuex';
 import { GlButton, GlTooltipDirective as GlTooltip, GlModal } from '@gitlab/ui';
 import { __ } from '~/locale';
 import toast from '~/vue_shared/plugins/global_toast';
 import { SET_REVIEW_BAR_RENDERED } from '~/batch_comments/stores/modules/batch_comments/mutation_types';
+import { useBatchComments } from '~/batch_comments/store';
 import { REVIEW_BAR_VISIBLE_CLASS_NAME } from '../constants';
 import PreviewDropdown from './preview_dropdown.vue';
 import SubmitDropdown from './submit_dropdown.vue';
@@ -26,7 +28,7 @@ export default {
     };
   },
   computed: {
-    ...mapGetters(['isNotesFetched']),
+    ...mapVuexGetters(['isNotesFetched']),
   },
   watch: {
     isNotesFetched() {
@@ -37,13 +39,13 @@ export default {
   },
   mounted() {
     document.body.classList.add(REVIEW_BAR_VISIBLE_CLASS_NAME);
-    this.$store.commit(`batchComments/${SET_REVIEW_BAR_RENDERED}`);
+    useBatchComments()[SET_REVIEW_BAR_RENDERED]();
   },
   beforeDestroy() {
     document.body.classList.remove(REVIEW_BAR_VISIBLE_CLASS_NAME);
   },
   methods: {
-    ...mapActions('batchComments', ['expandAllDiscussions', 'discardDrafts']),
+    ...mapActions(useBatchComments, ['expandAllDiscussions', 'discardDrafts']),
     async discardReviews() {
       this.discarding = true;
 
diff --git a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
index d4d623c4fc8cb..7912d8e4fc997 100644
--- a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
@@ -7,8 +7,9 @@ import {
   GlFormRadioGroup,
   GlLoadingIcon,
 } from '@gitlab/ui';
+import { mapActions, mapState } from 'pinia';
 // eslint-disable-next-line no-restricted-imports
-import { mapGetters, mapActions, mapState } from 'vuex';
+import { mapGetters as mapVuexGetters, mapState as mapVuexState } from 'vuex';
 import { __ } from '~/locale';
 import { createAlert } from '~/alert';
 import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
@@ -19,6 +20,7 @@ import { CLEAR_AUTOSAVE_ENTRY_EVENT, CONTENT_EDITOR_PASTE } from '~/vue_shared/c
 import markdownEditorEventHub from '~/vue_shared/components/markdown/eventhub';
 import { trackSavedUsingEditor } from '~/vue_shared/components/markdown/tracking';
 import { updateText } from '~/lib/utils/text_markdown';
+import { useBatchComments } from '~/batch_comments/store';
 import userCanApproveQuery from '../queries/can_approve.query.graphql';
 
 export default {
@@ -78,9 +80,14 @@ export default {
     };
   },
   computed: {
-    ...mapGetters(['getNotesData', 'getNoteableData', 'noteableType', 'getCurrentUserLastNote']),
-    ...mapState('batchComments', ['shouldAnimateReviewButton']),
-    ...mapState('diffs', ['projectPath']),
+    ...mapVuexGetters([
+      'getNotesData',
+      'getNoteableData',
+      'noteableType',
+      'getCurrentUserLastNote',
+    ]),
+    ...mapState(useBatchComments, ['shouldAnimateReviewButton']),
+    ...mapVuexState('diffs', ['projectPath']),
     autocompleteDataSources() {
       return gl.GfmAutoComplete?.dataSources;
     },
@@ -138,7 +145,7 @@ export default {
     this.noteData.noteable_id = this.getNoteableData.id;
   },
   methods: {
-    ...mapActions('batchComments', ['publishReview', 'clearDrafts']),
+    ...mapActions(useBatchComments, ['publishReview', 'clearDrafts']),
     repositionDropdown() {
       this.$refs.submitDropdown?.$refs.dropdown?.updatePopper();
     },
@@ -151,7 +158,7 @@ export default {
       try {
         const { note, reviewer_state: reviewerState } = this.noteData;
 
-        await this.publishReview(this.noteData);
+        await this.publishReview({ ...this.noteData });
 
         markdownEditorEventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, this.autosaveKey);
 
diff --git a/app/assets/javascripts/batch_comments/index.js b/app/assets/javascripts/batch_comments/index.js
index daed6906a09e4..a07093139c174 100644
--- a/app/assets/javascripts/batch_comments/index.js
+++ b/app/assets/javascripts/batch_comments/index.js
@@ -1,11 +1,11 @@
 import Vue from 'vue';
 import VueApollo from 'vue-apollo';
-// eslint-disable-next-line no-restricted-imports
-import { mapActions, mapGetters } from 'vuex';
+import { mapActions, mapState } from 'pinia';
 import { parseBoolean } from '~/lib/utils/common_utils';
 import { apolloProvider } from '~/graphql_shared/issuable_client';
 import store from '~/mr_notes/stores';
 import { pinia } from '~/pinia/instance';
+import { useBatchComments } from '~/batch_comments/store';
 
 export const initReviewBar = () => {
   const el = document.getElementById('js-review-bar');
@@ -28,13 +28,13 @@ export const initReviewBar = () => {
       canSummarize: parseBoolean(el.dataset.canSummarize),
     },
     computed: {
-      ...mapGetters('batchComments', ['draftsCount']),
+      ...mapState(useBatchComments, ['draftsCount']),
     },
     mounted() {
       this.fetchDrafts();
     },
     methods: {
-      ...mapActions('batchComments', ['fetchDrafts']),
+      ...mapActions(useBatchComments, ['fetchDrafts']),
     },
     render(createElement) {
       if (this.draftsCount === 0) return null;
diff --git a/app/assets/javascripts/batch_comments/store/index.js b/app/assets/javascripts/batch_comments/store/index.js
index 67eb044679a6d..1522056476bfc 100644
--- a/app/assets/javascripts/batch_comments/store/index.js
+++ b/app/assets/javascripts/batch_comments/store/index.js
@@ -11,13 +11,13 @@ export const useBatchComments = defineStore('batchComments', {
   },
   state() {
     return {
-      withBatchComments: true,
       isDraftsFetched: false,
       drafts: [],
       isPublishing: false,
       currentlyPublishingDrafts: [],
       shouldAnimateReviewButton: false,
       reviewBarRendered: false,
+      isMergeRequest: false,
     };
   },
   actions: {
diff --git a/app/assets/javascripts/batch_comments/store/state.js b/app/assets/javascripts/batch_comments/store/state.js
deleted file mode 100644
index 1efc00059d082..0000000000000
--- a/app/assets/javascripts/batch_comments/store/state.js
+++ /dev/null
@@ -1,9 +0,0 @@
-export default () => ({
-  withBatchComments: true,
-  isDraftsFetched: false,
-  drafts: [],
-  isPublishing: false,
-  currentlyPublishingDrafts: [],
-  shouldAnimateReviewButton: false,
-  reviewBarRendered: false,
-});
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js
index 1efc00059d082..ed9dfb7f05335 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js
@@ -1,9 +1,9 @@
 export default () => ({
-  withBatchComments: true,
   isDraftsFetched: false,
   drafts: [],
   isPublishing: false,
   currentlyPublishingDrafts: [],
   shouldAnimateReviewButton: false,
   reviewBarRendered: false,
+  isMergeRequest: false,
 });
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 0897c3184519f..c6aadaee3efe0 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -27,10 +27,6 @@ import { __ } from '~/locale';
 import notesEventHub from '~/notes/event_hub';
 import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
 import getMRCodequalityAndSecurityReports from 'ee_else_ce/diffs/components/graphql/get_mr_codequality_and_security_reports.query.graphql';
-import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
-import { useNotes } from '~/notes/store/legacy_notes';
-import { useBatchComments } from '~/batch_comments/store';
-import { useMrNotes } from '~/mr_notes/store/legacy_mr_notes';
 import { sortFindingsByFile } from '../utils/sort_findings_by_file';
 import {
   MR_TREE_SHOW_KEY,
@@ -416,12 +412,6 @@ export default {
     diffsApp.instrument();
   },
   created() {
-    // Pinia stores must be initialized manually during migration, otherwise they won't sync with Vuex
-    useNotes();
-    useLegacyDiffs();
-    useBatchComments();
-    useMrNotes();
-
     this.adjustView();
     this.subscribeToEvents();
 
diff --git a/app/assets/javascripts/diffs/components/tree_list_height.vue b/app/assets/javascripts/diffs/components/tree_list_height.vue
index 816dbf56e76e9..c5fc225d7dcf3 100644
--- a/app/assets/javascripts/diffs/components/tree_list_height.vue
+++ b/app/assets/javascripts/diffs/components/tree_list_height.vue
@@ -1,8 +1,8 @@
 <script>
 import { debounce } from 'lodash';
-// eslint-disable-next-line no-restricted-imports
-import { mapState, mapGetters } from 'vuex';
+import { mapState } from 'pinia';
 import { contentTop } from '~/lib/utils/common_utils';
+import { useBatchComments } from '~/batch_comments/store';
 
 const MAX_ITEMS_ON_NARROW_SCREEN = 8;
 // Should be enough for the very long titles (10+ lines) on the max smallest screen
@@ -28,8 +28,7 @@ export default {
     };
   },
   computed: {
-    ...mapState('batchComments', ['reviewBarRendered']),
-    ...mapGetters('batchComments', ['draftsCount']),
+    ...mapState(useBatchComments, ['reviewBarRendered', 'draftsCount']),
     reviewBarEnabled() {
       return this.draftsCount > 0;
     },
diff --git a/app/assets/javascripts/diffs/mixins/draft_comments.js b/app/assets/javascripts/diffs/mixins/draft_comments.js
index 4d54dcfa765dc..44c4aa1533da8 100644
--- a/app/assets/javascripts/diffs/mixins/draft_comments.js
+++ b/app/assets/javascripts/diffs/mixins/draft_comments.js
@@ -1,10 +1,10 @@
-// eslint-disable-next-line no-restricted-imports
-import { mapGetters } from 'vuex';
+import { mapState } from 'pinia';
+import { useBatchComments } from '~/batch_comments/store';
 import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
 
 export default {
   computed: {
-    ...mapGetters('batchComments', [
+    ...mapState(useBatchComments, [
       'shouldRenderDraftRow',
       'shouldRenderParallelDraftRow',
       'draftsForLine',
diff --git a/app/assets/javascripts/mr_notes/init.js b/app/assets/javascripts/mr_notes/init.js
index ef621f4d98803..5fa6e35a0273d 100644
--- a/app/assets/javascripts/mr_notes/init.js
+++ b/app/assets/javascripts/mr_notes/init.js
@@ -8,6 +8,11 @@ import { initOverviewTabCounter } from '~/mr_notes/init_count';
 import { getDerivedMergeRequestInformation } from '~/diffs/utils/merge_request';
 import { getReviewsForMergeRequest } from '~/diffs/utils/file_reviews';
 import { DIFF_VIEW_COOKIE_NAME, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useBatchComments } from '~/batch_comments/store';
+import { useMrNotes } from '~/mr_notes/store/legacy_mr_notes';
+import { pinia } from '~/pinia/instance';
 
 function setupMrNotesState(store, notesDataset, diffsDataset) {
   const noteableData = JSON.parse(notesDataset.noteableData);
@@ -45,6 +50,12 @@ function setupMrNotesState(store, notesDataset, diffsDataset) {
 }
 
 export function initMrStateLazyLoad(store = mrNotes) {
+  // Pinia stores must be initialized manually during migration, otherwise they won't sync with Vuex
+  useNotes(pinia);
+  useLegacyDiffs(pinia);
+  useBatchComments(pinia).$patch({ isMergeRequest: true });
+  useMrNotes(pinia);
+
   store.dispatch('setActiveTab', window.mrTabs.getCurrentAction());
   window.mrTabs.eventHub.$on('MergeRequestTabChange', (value) =>
     store.dispatch('setActiveTab', value),
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 0a7603887970f..34589fab68887 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -1,12 +1,14 @@
 <script>
 import { GlButton, GlSprintf, GlLink, GlFormCheckbox } from '@gitlab/ui';
+import { mapState } from 'pinia';
 // eslint-disable-next-line no-restricted-imports
-import { mapGetters, mapActions, mapState } from 'vuex';
+import { mapGetters as mapVuexGetters, mapActions as mapVuexActions } from 'vuex';
 import { mergeUrlParams } from '~/lib/utils/url_utility';
 import { __ } from '~/locale';
 import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin';
 import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
 import { trackSavedUsingEditor } from '~/vue_shared/components/markdown/tracking';
+import { useBatchComments } from '~/batch_comments/store';
 import eventHub from '../event_hub';
 import issuableStateMixin from '../mixins/issuable_state';
 import resolvable from '../mixins/resolvable';
@@ -134,22 +136,19 @@ export default {
     };
   },
   computed: {
-    ...mapGetters([
+    ...mapVuexGetters([
       'getDiscussionLastNote',
       'getNoteableData',
       'getNoteableDataByProp',
       'getNotesDataByProp',
       'getUserDataByProp',
     ]),
-    ...mapState({
-      withBatchComments: (state) => state.batchComments?.withBatchComments,
-    }),
-    ...mapGetters('batchComments', ['hasDrafts']),
+    ...mapState(useBatchComments, ['hasDrafts', 'withBatchComments', 'isMergeRequest']),
     autocompleteDataSources() {
       return gl.GfmAutoComplete?.dataSources;
     },
     showBatchCommentsActions() {
-      return this.withBatchComments && this.noteId === '' && !this.discussion.for_commit;
+      return this.isMergeRequest && this.noteId === '' && !this.discussion.for_commit;
     },
     showResolveDiscussionToggle() {
       if (!this.discussion?.notes) return false;
@@ -268,7 +267,7 @@ export default {
     this.updatePlaceholder();
   },
   methods: {
-    ...mapActions(['toggleResolveNote']),
+    ...mapVuexActions(['toggleResolveNote']),
     shouldToggleResolved(beforeSubmitDiscussionState) {
       return (
         this.showResolveDiscussionToggle && beforeSubmitDiscussionState !== this.newResolvedState()
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 0931d404be06c..035673ffec993 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -4,6 +4,7 @@ import { apolloProvider } from '~/graphql_shared/issuable_client';
 import { convertToGraphQLId } from '~/graphql_shared/utils';
 import { parseBoolean } from '~/lib/utils/common_utils';
 import { getLocationHash } from '~/lib/utils/url_utility';
+import { pinia } from '~/pinia/instance';
 import NotesApp from './components/notes_app.vue';
 import { store } from './stores';
 import { getNotesFilterData } from './utils/get_notes_filter_data';
@@ -55,6 +56,7 @@ export default ({ editorAiActions = [] } = {}) => {
       NotesApp,
     },
     store,
+    pinia,
     apolloProvider,
     provide: {
       showTimelineViewToggle,
diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
index c0d6536a07b73..26d575825d624 100644
--- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -1,5 +1,10 @@
+import { mapState, mapActions } from 'pinia';
 // eslint-disable-next-line no-restricted-imports
-import { mapActions, mapGetters, mapState } from 'vuex';
+import {
+  mapActions as mapVuexActions,
+  mapGetters as mapVuexGetters,
+  mapState as mapVuexState,
+} from 'vuex';
 import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils';
 import {
   TEXT_DIFF_POSITION_TYPE,
@@ -11,21 +16,25 @@ import { clearDraft } from '~/lib/utils/autosave';
 import { sprintf } from '~/locale';
 import { formatLineRange } from '~/notes/components/multiline_comment_utils';
 import { SAVING_THE_COMMENT_FAILED, SOMETHING_WENT_WRONG } from '~/diffs/i18n';
+import { useBatchComments } from '~/batch_comments/store';
 
 export default {
   computed: {
-    ...mapState({
+    ...mapVuexState({
       noteableData: (state) => state.notes.noteableData,
       notesData: (state) => state.notes.notesData,
-      withBatchComments: (state) => state.batchComments?.withBatchComments,
     }),
-    ...mapGetters('diffs', ['getDiffFileByHash']),
-    ...mapGetters('batchComments', ['shouldRenderDraftRowInDiscussion', 'draftForDiscussion']),
-    ...mapState('diffs', ['commit', 'showWhitespace']),
+    ...mapVuexGetters('diffs', ['getDiffFileByHash']),
+    ...mapState(useBatchComments, [
+      'shouldRenderDraftRowInDiscussion',
+      'draftForDiscussion',
+      'isMergeRequest',
+    ]),
+    ...mapVuexState('diffs', ['commit', 'showWhitespace']),
   },
   methods: {
-    ...mapActions('diffs', ['cancelCommentForm', 'toggleFileCommentForm']),
-    ...mapActions('batchComments', ['addDraftToReview', 'saveDraft', 'insertDraftIntoDrafts']),
+    ...mapVuexActions('diffs', ['cancelCommentForm', 'toggleFileCommentForm']),
+    ...mapActions(useBatchComments, ['addDraftToReview', 'saveDraft', 'insertDraftIntoDrafts']),
     // eslint-disable-next-line max-params
     addReplyToReview(noteText, isResolving, parentElement, errorCallback) {
       const postData = getDraftReplyFormData({
@@ -129,7 +138,7 @@ export default {
       });
     },
     showDraft(replyId) {
-      return this.withBatchComments && this.shouldRenderDraftRowInDiscussion(replyId);
+      return this.isMergeRequest && this.shouldRenderDraftRowInDiscussion(replyId);
     },
   },
 };
diff --git a/app/assets/javascripts/pinia/instance.js b/app/assets/javascripts/pinia/instance.js
index 0a167472926d9..74178e54bb885 100644
--- a/app/assets/javascripts/pinia/instance.js
+++ b/app/assets/javascripts/pinia/instance.js
@@ -1,11 +1,12 @@
 import Vue from 'vue';
 import { createPinia, PiniaVuePlugin } from 'pinia';
-import { syncWithVuex } from '~/pinia/plugins';
+import { globalAccessorPlugin, syncWithVuex } from '~/pinia/plugins';
 
 Vue.use(PiniaVuePlugin);
 
 const pinia = createPinia();
 
 pinia.use(syncWithVuex);
+pinia.use(globalAccessorPlugin);
 
 export { pinia };
diff --git a/ee/spec/frontend/batch_comments/components/submit_dropdown_spec.js b/ee/spec/frontend/batch_comments/components/submit_dropdown_spec.js
index f395c1d6c257a..df40e9c5db85f 100644
--- a/ee/spec/frontend/batch_comments/components/submit_dropdown_spec.js
+++ b/ee/spec/frontend/batch_comments/components/submit_dropdown_spec.js
@@ -3,6 +3,8 @@ import VueApollo from 'vue-apollo';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
 import { GlDisclosureDropdown } from '@gitlab/ui';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import createMockApollo from 'helpers/mock_apollo_helper';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import waitForPromises from 'helpers/wait_for_promises';
@@ -10,13 +12,19 @@ import SubmitDropdown from '~/batch_comments/components/submit_dropdown.vue';
 import userCanApproveQuery from '~/batch_comments/queries/can_approve.query.graphql';
 import { updateText } from '~/lib/utils/text_markdown';
 import SummarizeMyReview from 'ee/batch_comments/components/summarize_my_review.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 
 jest.mock('~/lib/utils/text_markdown');
 
 Vue.use(Vuex);
 Vue.use(VueApollo);
+Vue.use(PiniaVuePlugin);
 
 let wrapper;
+let pinia;
 let publishReview;
 
 function factory({
@@ -76,6 +84,7 @@ function factory({
   });
   wrapper = mountExtended(SubmitDropdown, {
     store,
+    pinia,
     apolloProvider,
     stubs: { SummarizeMyReview },
     provide: { canSummarize },
@@ -83,6 +92,13 @@ function factory({
 }
 
 describe('Batch comments submit dropdown', () => {
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments();
+  });
+
   it.each`
     requirePasswordToApprove | exists   | existsText
     ${true}                  | ${true}  | ${'shows'}
diff --git a/ee/spec/frontend/diffs/components/diff_line_note_form_spec.js b/ee/spec/frontend/diffs/components/diff_line_note_form_spec.js
index 03d1d05ca094a..c9cce1c8f2ae7 100644
--- a/ee/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/ee/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
 import Vue from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
+import { createTestingPinia } from '@pinia/testing';
 import waitForPromises from 'helpers/wait_for_promises';
 import { sprintf } from '~/locale';
 import { createAlert } from '~/alert';
@@ -10,6 +11,10 @@ import note from 'jest/notes/mock_data';
 import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
 import NoteForm from '~/notes/components/note_form.vue';
 import { SOMETHING_WENT_WRONG, SAVING_THE_COMMENT_FAILED } from '~/diffs/i18n';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 
 Vue.use(Vuex);
 jest.mock('~/alert');
@@ -17,7 +22,7 @@ jest.mock('~/alert');
 describe('EE DiffLineNoteForm', () => {
   let wrapper;
 
-  const saveDraft = jest.fn();
+  let saveDraft;
 
   const createStoreOptions = (headSha) => {
     const state = {
@@ -52,10 +57,6 @@ describe('EE DiffLineNoteForm', () => {
             cancelCommentForm: jest.fn(),
           },
         },
-        batchComments: {
-          namespaced: true,
-          actions: { saveDraft },
-        },
       },
     };
   };
@@ -84,7 +85,14 @@ describe('EE DiffLineNoteForm', () => {
 
   const submitNoteAddToReview = () =>
     wrapper.findComponent(NoteForm).vm.$emit('handleFormUpdateAddToReview', note);
-  const saveDraftCommitId = () => saveDraft.mock.calls[0][1].data.note.commit_id;
+  const saveDraftCommitId = () => saveDraft.mock.calls[0][0].data.note.commit_id;
+
+  beforeEach(() => {
+    createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    saveDraft = useBatchComments().saveDraft.mockImplementation(() => Promise.resolve());
+  });
 
   describe('when user submits note to review', () => {
     it('should call saveDraft action with commit_id === null when store has no commit', () => {
diff --git a/ee/spec/frontend/notes/components/note_form_spec.js b/ee/spec/frontend/notes/components/note_form_spec.js
index a6d49e16b7192..61d92b73dc1d5 100644
--- a/ee/spec/frontend/notes/components/note_form_spec.js
+++ b/ee/spec/frontend/notes/components/note_form_spec.js
@@ -1,10 +1,18 @@
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
+// eslint-disable-next-line no-restricted-imports
+import Vuex from 'vuex';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import CommentTemperature from 'ee_component/ai/components/comment_temperature.vue';
-import batchComments from '~/batch_comments/stores/modules/batch_comments';
 import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
 import NoteForm from '~/notes/components/note_form.vue';
 import createStore from '~/notes/stores';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useBatchComments } from '~/batch_comments/store';
+import mrNotesStore from '~/mr_notes/stores/modules';
 import {
   notesDataMock,
   noteableDataMock,
@@ -15,8 +23,11 @@ jest.mock('~/lib/utils/autosave');
 
 const badNote = 'very bad note';
 
+Vue.use(PiniaVuePlugin);
+
 describe('issue_comment_form component', () => {
   let wrapper;
+  let pinia;
 
   const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
   const findMarkdownEditorTextarea = () => findMarkdownEditor().find('textarea');
@@ -32,6 +43,9 @@ describe('issue_comment_form component', () => {
     stubs = {},
     store = createStore(),
   } = {}) => {
+    store.registerModule('page', new Vuex.Store(mrNotesStore));
+    // eslint-disable-next-line no-param-reassign
+    store.state.page.activeTab = 'diffs';
     store.dispatch('setNoteableData', {
       ...noteableDataMock,
       noteableType,
@@ -41,6 +55,7 @@ describe('issue_comment_form component', () => {
 
     wrapper = mountExtended(NoteForm, {
       store,
+      pinia,
       propsData: {
         isEditing: false,
         noteBody: 'Magni suscipit eius consectetur enim et ex et commodi.',
@@ -59,6 +74,13 @@ describe('issue_comment_form component', () => {
     });
   };
 
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments().$patch({ isMergeRequest: true });
+  });
+
   describe('markdown editor', () => {
     it('shows markdown editor', () => {
       createComponentWrapper();
@@ -193,7 +215,6 @@ describe('issue_comment_form component', () => {
           beforeEach(() => {
             bootstrapFn = (updatedNoteBody = badNote) => {
               const store = createStore();
-              store.registerModule('batchComments', batchComments());
               createComponentWrapper({
                 noteableType,
                 initialData: { updatedNoteBody },
diff --git a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
index d1ce8be6c4273..c62cc9f24ff5e 100644
--- a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
+++ b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
@@ -1,37 +1,42 @@
-import { shallowMount } from '@vue/test-utils';
 import Vue from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
+import { shallowMount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
 import DraftNote from '~/batch_comments/components/draft_note.vue';
 import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
+import * as mockData from '../../notes/mock_data';
 
-Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
 describe('Batch comments diff file drafts component', () => {
   let wrapper;
+  let pinia;
 
   function factory(propsData = {}) {
-    const store = new Vuex.Store({
-      modules: {
-        batchComments: {
-          namespaced: true,
-          getters: {
-            draftsForFile: () => () => [
-              { id: 1, position: { position_type: 'file' } },
-              { id: 2, position: { position_type: 'file' } },
-            ],
-          },
-        },
-      },
-    });
-
     wrapper = shallowMount(DiffFileDrafts, {
-      store,
+      pinia,
       propsData: { fileHash: 'filehash', positionType: 'file', ...propsData },
     });
   }
 
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments().drafts = [
+      ...mockData.draftComments.map((draft) => ({
+        ...draft,
+        file_hash: 'filehash',
+        position: { position_type: 'file' },
+      })),
+    ];
+  });
+
   it('renders list of draft notes', () => {
     factory();
 
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index e5e3ae373fe3c..d859f557b608f 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -1,5 +1,6 @@
 import { nextTick } from 'vue';
 import { GlBadge } from '@gitlab/ui';
+import { createTestingPinia } from '@pinia/testing';
 import { shallowMount } from '@vue/test-utils';
 import { stubComponent } from 'helpers/stub_component';
 import DraftNote from '~/batch_comments/components/draft_note.vue';
@@ -7,6 +8,10 @@ import { createStore } from '~/batch_comments/stores';
 import NoteableNote from '~/notes/components/noteable_note.vue';
 import { clearDraft } from '~/lib/utils/autosave';
 import * as types from '~/batch_comments/stores/modules/batch_comments/mutation_types';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useBatchComments } from '~/batch_comments/store';
 import { createDraft } from '../mock_data';
 
 jest.mock('~/behaviors/markdown/render_gfm');
@@ -51,6 +56,9 @@ describe('Batch comments draft note component', () => {
   const findNoteableNote = () => wrapper.findComponent(NoteableNote);
 
   beforeEach(() => {
+    createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
     store = createStore();
     draft = createDraft();
   });
@@ -84,7 +92,7 @@ describe('Batch comments draft note component', () => {
 
       findNoteableNote().vm.$emit('handleUpdateNote', formData);
 
-      expect(store.dispatch).toHaveBeenCalledWith('batchComments/updateDraft', formData);
+      expect(useBatchComments().updateDraft).toHaveBeenCalledWith(formData);
     });
   });
 
@@ -95,7 +103,7 @@ describe('Batch comments draft note component', () => {
 
       findNoteableNote().vm.$emit('handleDeleteNote', draft);
 
-      expect(store.dispatch).toHaveBeenCalledWith('batchComments/deleteDraft', draft);
+      expect(useBatchComments().deleteDraft).toHaveBeenCalledWith(draft);
     });
   });
 
@@ -153,14 +161,10 @@ describe('Batch comments draft note component', () => {
     it(`sets opened state`, async () => {
       createComponent({ draft });
       await findNoteableNote().vm.$emit('handleEdit');
-      expect(store.commit).toHaveBeenCalledWith(
-        `batchComments/${types.SET_DRAFT_EDITING}`,
-        {
-          draftId: draft.id,
-          isEditing: true,
-        },
-        undefined,
-      );
+      expect(useBatchComments()[types.SET_DRAFT_EDITING]).toHaveBeenCalledWith({
+        draftId: draft.id,
+        isEditing: true,
+      });
     });
 
     it(`resets opened state on form close`, async () => {
@@ -168,14 +172,10 @@ describe('Batch comments draft note component', () => {
       createComponent({ draft });
       await findNoteableNote().vm.$emit('cancelForm');
       expect(findNoteableNote().props('restoreFromAutosave')).toBe(false);
-      expect(store.commit).toHaveBeenCalledWith(
-        `batchComments/${types.SET_DRAFT_EDITING}`,
-        {
-          draftId: draft.id,
-          isEditing: false,
-        },
-        undefined,
-      );
+      expect(useBatchComments()[types.SET_DRAFT_EDITING]).toHaveBeenCalledWith({
+        draftId: draft.id,
+        isEditing: false,
+      });
     });
 
     it(`clears autosave key on form cancel`, () => {
diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js
index 850a7efb4ed39..dcbd9e0af4127 100644
--- a/spec/frontend/batch_comments/components/drafts_count_spec.js
+++ b/spec/frontend/batch_comments/components/drafts_count_spec.js
@@ -1,18 +1,27 @@
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
 import { mount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import DraftsCount from '~/batch_comments/components/drafts_count.vue';
-import { createStore } from '~/batch_comments/stores';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
+
+Vue.use(PiniaVuePlugin);
 
 describe('Batch comments drafts count component', () => {
-  let store;
   let wrapper;
+  let pinia;
 
   beforeEach(() => {
-    store = createStore();
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
 
-    store.state.batchComments.drafts.push('comment');
+    useBatchComments().drafts.push('comment');
 
-    wrapper = mount(DraftsCount, { store });
+    wrapper = mount(DraftsCount, { pinia });
   });
 
   it('renders count', () => {
@@ -24,7 +33,7 @@ describe('Batch comments drafts count component', () => {
 
     expect(el.text()).toContain('draft');
 
-    store.state.batchComments.drafts.push('comment 2');
+    useBatchComments().drafts.push('comment 2');
     await nextTick();
 
     expect(el.text()).toContain('drafts');
diff --git a/spec/frontend/batch_comments/components/preview_dropdown_spec.js b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
index c0ad40b75adb0..b4b97a2d29fb6 100644
--- a/spec/frontend/batch_comments/components/preview_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
@@ -2,59 +2,86 @@ import Vue, { nextTick } from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
 import { mount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import { TEST_HOST } from 'helpers/test_constants';
 import { visitUrl } from '~/lib/utils/url_utility';
 import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
 import PreviewItem from '~/batch_comments/components/preview_item.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { createCustomGetters } from 'helpers/pinia_helpers';
+import { useBatchComments } from '~/batch_comments/store';
 
 jest.mock('~/lib/utils/url_utility', () => ({
   visitUrl: jest.fn(),
   setUrlParams: jest.requireActual('~/lib/utils/url_utility').setUrlParams,
+  joinPaths: jest.fn(),
+  doesHashExistInUrl: jest.fn(),
 }));
 
 Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
-let wrapper;
-
-const goToFile = jest.fn();
-const scrollToDraft = jest.fn();
-
-const findPreviewItem = () => wrapper.findComponent(PreviewItem);
-
-function factory({ viewDiffsFileByFile = false, draftsCount = 1, sortedDrafts = [] } = {}) {
-  const store = new Vuex.Store({
-    modules: {
-      diffs: {
-        namespaced: true,
-        actions: {
-          goToFile,
-        },
-        state: {
-          viewDiffsFileByFile,
+describe('Batch comments preview dropdown', () => {
+  let wrapper;
+  let pinia;
+  let batchCommentsGetters;
+
+  const goToFile = jest.fn();
+
+  const findPreviewItem = () => wrapper.findComponent(PreviewItem);
+
+  function factory({ viewDiffsFileByFile = false, draftsCount = 1, sortedDrafts = [] } = {}) {
+    batchCommentsGetters = {
+      draftsCount,
+      sortedDrafts,
+    };
+    const store = new Vuex.Store({
+      modules: {
+        diffs: {
+          namespaced: true,
+          actions: {
+            goToFile,
+          },
+          state: {
+            viewDiffsFileByFile,
+          },
         },
-      },
-      batchComments: {
-        namespaced: true,
-        actions: { scrollToDraft },
-        getters: { draftsCount: () => draftsCount, sortedDrafts: () => sortedDrafts },
-      },
-      notes: {
-        getters: {
-          getNoteableData: () => ({ diff_head_sha: '123' }),
+        notes: {
+          getters: {
+            getNoteableData: () => ({ diff_head_sha: '123' }),
+          },
         },
       },
-    },
-  });
+    });
 
-  wrapper = mount(PreviewDropdown, {
-    store,
-    stubs: {
-      PreviewItem: true,
-    },
+    wrapper = mount(PreviewDropdown, {
+      store,
+      pinia,
+      stubs: {
+        PreviewItem: true,
+      },
+    });
+  }
+
+  beforeEach(() => {
+    batchCommentsGetters = {};
+    pinia = createTestingPinia({
+      plugins: [
+        globalAccessorPlugin,
+        createCustomGetters(() => ({
+          batchComments: batchCommentsGetters,
+          legacyNotes: {},
+          legacyDiffs: {},
+        })),
+      ],
+    });
+    useLegacyDiffs();
+    useNotes();
   });
-}
 
-describe('Batch comments preview dropdown', () => {
   describe('clicking draft', () => {
     it('toggles active file when viewDiffsFileByFile is true', async () => {
       factory({
@@ -67,8 +94,7 @@ describe('Batch comments preview dropdown', () => {
       expect(goToFile).toHaveBeenCalledWith(expect.anything(), { path: 'foo' });
 
       await nextTick();
-      expect(scrollToDraft).toHaveBeenCalledWith(
-        expect.anything(),
+      expect(useBatchComments().scrollToDraft).toHaveBeenCalledWith(
         expect.objectContaining({ id: 1, file_hash: 'hash' }),
       );
     });
@@ -83,8 +109,7 @@ describe('Batch comments preview dropdown', () => {
 
       await nextTick();
 
-      expect(scrollToDraft).toHaveBeenCalledWith(
-        expect.anything(),
+      expect(useBatchComments().scrollToDraft).toHaveBeenCalledWith(
         expect.objectContaining({ id: 1 }),
       );
     });
@@ -99,7 +124,7 @@ describe('Batch comments preview dropdown', () => {
 
       await nextTick();
 
-      expect(scrollToDraft).not.toHaveBeenCalled();
+      expect(useBatchComments().scrollToDraft).not.toHaveBeenCalled();
       expect(visitUrl).toHaveBeenCalledWith(`${TEST_HOST}/?commit_id=1234#note_1`);
     });
   });
diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
index 2fe73f30a4ca0..47c17ed64b337 100644
--- a/spec/frontend/batch_comments/components/publish_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
@@ -1,30 +1,45 @@
 import { GlDisclosureDropdown } from '@gitlab/ui';
 import { shallowMount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
 import Vue from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
+import { PiniaVuePlugin } from 'pinia';
 import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
 import { createStore } from '~/mr_notes/stores';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 import { createDraft } from '../mock_data';
 
 jest.mock('~/behaviors/markdown/render_gfm');
 
 Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
 describe('Batch comments publish dropdown component', () => {
   let wrapper;
+  let pinia;
   const draft = createDraft();
 
   function createComponent() {
     const store = createStore();
-    store.state.batchComments.drafts.push(draft, { ...draft, id: 2 });
 
     wrapper = shallowMount(PreviewDropdown, {
       store,
+      pinia,
       stubs: { GlDisclosureDropdown },
     });
   }
 
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments().drafts = [draft, { ...draft, id: 2 }];
+  });
+
   it('renders list of drafts', () => {
     createComponent();
 
diff --git a/spec/frontend/batch_comments/components/review_bar_spec.js b/spec/frontend/batch_comments/components/review_bar_spec.js
index 2cf56d0d67323..2ea4268606761 100644
--- a/spec/frontend/batch_comments/components/review_bar_spec.js
+++ b/spec/frontend/batch_comments/components/review_bar_spec.js
@@ -1,8 +1,13 @@
 import { nextTick } from 'vue';
+import { createTestingPinia } from '@pinia/testing';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import ReviewBar from '~/batch_comments/components/review_bar.vue';
 import { REVIEW_BAR_VISIBLE_CLASS_NAME } from '~/batch_comments/constants';
 import toast from '~/vue_shared/plugins/global_toast';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 import createStore from '../create_batch_comments_store';
 
 jest.mock('~/vue_shared/plugins/global_toast');
@@ -24,6 +29,9 @@ describe('Batch comments review bar component', () => {
   };
 
   beforeEach(() => {
+    createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
     document.body.className = '';
   });
 
@@ -59,11 +67,9 @@ describe('Batch comments review bar component', () => {
     it('calls discardReviews when primary action on modal is triggered', () => {
       createComponent();
 
-      const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation();
-
       findDiscardReviewModal().vm.$emit('primary');
 
-      expect(dispatchSpy).toHaveBeenCalledWith('batchComments/discardDrafts', undefined);
+      expect(useBatchComments().discardDrafts).toHaveBeenCalled();
     });
 
     it('creates a toast message when finished', async () => {
diff --git a/spec/frontend/batch_comments/components/submit_dropdown_spec.js b/spec/frontend/batch_comments/components/submit_dropdown_spec.js
index 125242c4119d5..0e1984b83b1b9 100644
--- a/spec/frontend/batch_comments/components/submit_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/submit_dropdown_spec.js
@@ -1,8 +1,10 @@
 import { GlDisclosureDropdown } from '@gitlab/ui';
+import { createTestingPinia } from '@pinia/testing';
 import Vue from 'vue';
 import VueApollo from 'vue-apollo';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
+import { PiniaVuePlugin } from 'pinia';
 import createMockApollo from 'helpers/mock_apollo_helper';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import waitForPromises from 'helpers/wait_for_promises';
@@ -11,20 +13,24 @@ import { mockTracking } from 'helpers/tracking_helper';
 import userCanApproveQuery from '~/batch_comments/queries/can_approve.query.graphql';
 import { CLEAR_AUTOSAVE_ENTRY_EVENT } from '~/vue_shared/constants';
 import markdownEditorEventHub from '~/vue_shared/components/markdown/eventhub';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 
 jest.mock('~/autosave');
 jest.mock('~/vue_shared/components/markdown/eventhub');
 
 Vue.use(VueApollo);
 Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
 let wrapper;
-let publishReview;
+let pinia;
 let trackingSpy;
 let getCurrentUserLastNote;
 
 function factory({ canApprove = true, shouldAnimateReviewButton = false } = {}) {
-  publishReview = jest.fn().mockResolvedValue();
   trackingSpy = mockTracking(undefined, null, jest.spyOn);
   const requestHandlers = [
     [
@@ -48,6 +54,8 @@ function factory({ canApprove = true, shouldAnimateReviewButton = false } = {})
   const apolloProvider = createMockApollo(requestHandlers);
   getCurrentUserLastNote = Vue.observable({ id: 1 });
 
+  useBatchComments().shouldAnimateReviewButton = shouldAnimateReviewButton;
+
   const store = new Vuex.Store({
     getters: {
       getNotesData: () => ({
@@ -68,18 +76,11 @@ function factory({ canApprove = true, shouldAnimateReviewButton = false } = {})
           projectPath: 'gitlab-org/gitlab',
         },
       },
-      batchComments: {
-        namespaced: true,
-        state: { shouldAnimateReviewButton },
-        actions: {
-          publishReview,
-          clearDrafts: jest.fn(),
-        },
-      },
     },
   });
   wrapper = mountExtended(SubmitDropdown, {
     store,
+    pinia,
     apolloProvider,
   });
 }
@@ -90,6 +91,12 @@ const findForm = () => wrapper.findByTestId('submit-gl-form');
 const findSubmitDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
 
 describe('Batch comments submit dropdown', () => {
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+  });
+
   afterEach(() => {
     window.mrTabs = null;
   });
@@ -97,11 +104,11 @@ describe('Batch comments submit dropdown', () => {
   it('calls publishReview with note data', async () => {
     factory();
 
-    findCommentTextarea().setValue('Hello world');
+    await findCommentTextarea().setValue('Hello world');
 
     await findForm().vm.$emit('submit', { preventDefault: jest.fn() });
 
-    expect(publishReview).toHaveBeenCalledWith(expect.anything(), {
+    expect(useBatchComments().publishReview).toHaveBeenCalledWith({
       noteable_type: 'merge_request',
       noteable_id: 1,
       note: 'Hello world',
@@ -249,7 +256,7 @@ describe('Batch comments submit dropdown', () => {
 
     findForm().vm.$emit('submit', { preventDefault: jest.fn() });
 
-    expect(publishReview).toHaveBeenCalledWith(expect.anything(), {
+    expect(useBatchComments().publishReview).toHaveBeenCalledWith({
       noteable_type: 'merge_request',
       noteable_id: 1,
       note: 'Hello world',
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 076459dec2234..8992a258f7e09 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -1,8 +1,10 @@
 import { GlLoadingIcon } from '@gitlab/ui';
+import { createTestingPinia } from '@pinia/testing';
 import { shallowMount } from '@vue/test-utils';
 import Vue from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
+import { PiniaVuePlugin } from 'pinia';
 import waitForPromises from 'helpers/wait_for_promises';
 import { sprintf } from '~/locale';
 import { createAlert } from '~/alert';
@@ -16,13 +18,19 @@ import NoteForm from '~/notes/components/note_form.vue';
 import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
 import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
 import { SOMETHING_WENT_WRONG, SAVING_THE_COMMENT_FAILED } from '~/diffs/i18n';
+import { createCustomGetters } from 'helpers/pinia_helpers';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
 import { getDiffFileMock } from '../mock_data/diff_file';
 
 Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 jest.mock('~/alert');
 
 describe('DiffContent', () => {
   let wrapper;
+  let pinia;
 
   const saveDiffDiscussionMock = jest.fn();
   const closeDiffFileCommentFormMock = jest.fn();
@@ -52,20 +60,6 @@ describe('DiffContent', () => {
         getUserData: getUserDataGetterMock,
       },
       modules: {
-        /*
-        we need extra batchComments since vue-test-utils does not
-        stub async components properly
-        */
-        batchComments: {
-          namespaced: true,
-          getters: {
-            draftsForFile: () => () => true,
-            draftsForLine: () => () => true,
-            shouldRenderDraftRow: () => () => true,
-            hasParallelDraftLeft: () => () => true,
-            hasParallelDraftRight: () => () => true,
-          },
-        },
         diffs: {
           namespaced: true,
           state: {
@@ -94,11 +88,33 @@ describe('DiffContent', () => {
         ...defaultProps,
         ...props,
       },
+      pinia,
       store: fakeStore,
       provide: { glFeatures },
     });
   };
 
+  beforeEach(() => {
+    pinia = createTestingPinia({
+      plugins: [
+        globalAccessorPlugin,
+        createCustomGetters(() => ({
+          legacyNotes: {},
+          legacyDiffs: {},
+          batchComments: {
+            draftsForFile: () => () => true,
+            draftsForLine: () => () => true,
+            shouldRenderDraftRow: () => () => true,
+            hasParallelDraftLeft: () => () => true,
+            hasParallelDraftRight: () => () => true,
+          },
+        })),
+      ],
+    });
+    useLegacyDiffs();
+    useNotes();
+  });
+
   describe('with text based files', () => {
     afterEach(() => {
       [isParallelViewGetterMock, isInlineViewGetterMock].forEach((m) => m.mockRestore());
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index 25081535b3777..c6939dd23be47 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,16 +1,25 @@
+import Vue from 'vue';
 import { GlIcon } from '@gitlab/ui';
 import { mount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
 import { createStore } from '~/mr_notes/stores';
 import DiscussionNotes from '~/notes/components/discussion_notes.vue';
 import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
 import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
 import discussionsMockData from '../mock_data/diff_discussions';
 
 jest.mock('~/behaviors/markdown/render_gfm');
 
+Vue.use(PiniaVuePlugin);
+
 describe('DiffDiscussions', () => {
   let store;
+  let pinia;
   let wrapper;
   const getDiscussionsMockData = () => [{ ...discussionsMockData }];
 
@@ -18,6 +27,7 @@ describe('DiffDiscussions', () => {
     store = createStore();
     wrapper = mount(DiffDiscussions, {
       store,
+      pinia,
       propsData: {
         discussions,
         ...props,
@@ -27,6 +37,12 @@ describe('DiffDiscussions', () => {
 
   const findNoteableDiscussion = () => wrapper.findComponent(NoteableDiscussion);
 
+  beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+  });
+
   describe('template', () => {
     it('should have notes list', () => {
       createComponent();
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
index bb8320ec4730d..9ce0452ca296d 100644
--- a/spec/frontend/diffs/components/diff_view_spec.js
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -1,15 +1,26 @@
 import { shallowMount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
 import Vue from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
 import { throttle } from 'lodash';
+import { PiniaVuePlugin } from 'pinia';
 import DiffView from '~/diffs/components/diff_view.vue';
 import DraftNote from '~/batch_comments/components/draft_note.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { createCustomGetters } from 'helpers/pinia_helpers';
+
+Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
 jest.mock('lodash/throttle', () => jest.fn((fn) => fn));
 const lodash = jest.requireActual('lodash');
 
 describe('DiffView', () => {
+  let pinia;
+
   const DiffExpansionCell = { template: `<div/>` };
   const DiffRow = { template: `<div/>` };
   const DiffCommentCell = { template: `<div/>` };
@@ -18,19 +29,6 @@ describe('DiffView', () => {
   const getDiffRow = (wrapper) => wrapper.findComponent(DiffRow).vm;
 
   const createWrapper = ({ props } = {}) => {
-    Vue.use(Vuex);
-
-    const batchComments = {
-      getters: {
-        shouldRenderDraftRow: () => false,
-        shouldRenderParallelDraftRow: () => () => true,
-        draftsForLine: () => false,
-        draftsForFile: () => false,
-        hasParallelDraftLeft: () => false,
-        hasParallelDraftRight: () => false,
-      },
-      namespaced: true,
-    };
     const diffs = {
       actions: { showCommentForm },
       getters: { commitId: () => 'abc123', fileLineCoverage: () => ({}) },
@@ -42,7 +40,7 @@ describe('DiffView', () => {
     };
 
     const store = new Vuex.Store({
-      modules: { diffs, notes, batchComments },
+      modules: { diffs, notes },
     });
 
     const propsData = {
@@ -53,11 +51,30 @@ describe('DiffView', () => {
     };
 
     const stubs = { DiffExpansionCell, DiffRow, DiffCommentCell };
-    return shallowMount(DiffView, { propsData, store, stubs });
+    return shallowMount(DiffView, { propsData, pinia, store, stubs });
   };
 
   beforeEach(() => {
     throttle.mockImplementation(lodash.throttle);
+    pinia = createTestingPinia({
+      plugins: [
+        globalAccessorPlugin,
+        createCustomGetters(() => ({
+          legacyNotes: {},
+          legacyDiffs: {},
+          batchComments: {
+            shouldRenderDraftRow: () => false,
+            shouldRenderParallelDraftRow: () => () => true,
+            draftsForLine: () => false,
+            draftsForFile: () => false,
+            hasParallelDraftLeft: () => false,
+            hasParallelDraftRight: () => false,
+          },
+        })),
+      ],
+    });
+    useLegacyDiffs();
+    useNotes();
   });
 
   afterEach(() => {
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index 6fc9ae78ca7c7..c0d4ac814261a 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,6 +1,7 @@
 import { GlLink, GlFormCheckbox } from '@gitlab/ui';
-import { nextTick } from 'vue';
-import batchComments from '~/batch_comments/stores/modules/batch_comments';
+import Vue, { nextTick } from 'vue';
+import { createTestingPinia } from '@pinia/testing';
+import { PiniaVuePlugin } from 'pinia';
 import NoteForm from '~/notes/components/note_form.vue';
 import createStore from '~/notes/stores';
 import MarkdownField from '~/vue_shared/components/markdown/field.vue';
@@ -11,12 +12,19 @@ import notesEventHub from '~/notes/event_hub';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import { mockTracking } from 'helpers/tracking_helper';
 import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 import { noteableDataMock, notesDataMock, discussionMock, note } from '../mock_data';
 
 jest.mock('~/lib/utils/autosave');
 
+Vue.use(PiniaVuePlugin);
+
 describe('issue_note_form component', () => {
   let store;
+  let pinia;
   let wrapper;
   let textarea;
   let props;
@@ -25,6 +33,7 @@ describe('issue_note_form component', () => {
   const createComponentWrapper = (propsData = {}, provide = {}, stubs = {}) => {
     wrapper = mountExtended(NoteForm, {
       store,
+      pinia,
       propsData: {
         ...props,
         ...propsData,
@@ -53,6 +62,11 @@ describe('issue_note_form component', () => {
   const findMarkdownField = () => wrapper.findComponent(MarkdownField);
 
   beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments().$patch({ isMergeRequest: true });
+
     store = createStore();
     store.dispatch('setNoteableData', noteableDataMock);
     store.dispatch('setNotesData', notesDataMock);
@@ -287,8 +301,6 @@ describe('issue_note_form component', () => {
 
   describe('with batch comments', () => {
     beforeEach(() => {
-      store.registerModule('batchComments', batchComments());
-
       createComponentWrapper({
         isDraft: true,
         noteId: '',
@@ -338,7 +350,7 @@ describe('issue_note_form component', () => {
       });
 
       it('sends the event to indicate that a draft has been added to the review', () => {
-        store.state.batchComments.drafts = [{ note: 'A' }];
+        useBatchComments().drafts = [{ note: 'A' }];
         createComponentWrapper({
           isDraft: true,
           noteId: '',
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index eff88c26d7e02..e79757c56b948 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -3,6 +3,8 @@ import Vue, { nextTick } from 'vue';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
 import MockAdapter from 'axios-mock-adapter';
+import { PiniaVuePlugin } from 'pinia';
+import { createTestingPinia } from '@pinia/testing';
 import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json';
 import waitForPromises from 'helpers/wait_for_promises';
 import axios from '~/lib/utils/axios_utils';
@@ -19,7 +21,10 @@ import { COMMENT_FORM } from '~/notes/i18n';
 import notesModule from '~/notes/stores/modules';
 import { sprintf } from '~/locale';
 import { createAlert } from '~/alert';
-
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useBatchComments } from '~/batch_comments/store';
 import {
   noteableDataMock,
   discussionMock,
@@ -30,12 +35,14 @@ import {
 import { useLocalStorageSpy } from '../../__helpers__/local_storage_helper';
 
 Vue.use(Vuex);
+Vue.use(PiniaVuePlugin);
 
 jest.mock('~/behaviors/markdown/render_gfm');
 jest.mock('~/alert');
 
 describe('noteable_discussion component', () => {
   let store;
+  let pinia;
   let wrapper;
   let axiosMock;
 
@@ -58,11 +65,16 @@ describe('noteable_discussion component', () => {
 
     wrapper = mountExtended(NoteableDiscussion, {
       store,
+      pinia,
       propsData: { discussion },
     });
   };
 
   beforeEach(() => {
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+    useBatchComments();
     axiosMock = new MockAdapter(axios);
     createComponent();
   });
@@ -127,6 +139,7 @@ describe('noteable_discussion component', () => {
         store.dispatch('setUserData', userDataMock);
         wrapper = mount(NoteableDiscussion, {
           store,
+          pinia,
           propsData: { discussion: discussionMock },
         });
         expect(wrapper.find('.note-edit-form').exists()).toBe(hasDraft);
@@ -290,6 +303,7 @@ describe('noteable_discussion component', () => {
 
         wrapper = mount(NoteableDiscussion, {
           store,
+          pinia,
           propsData: { discussion: discussionMock },
         });
       });
@@ -308,6 +322,7 @@ describe('noteable_discussion component', () => {
 
         wrapper = mount(NoteableDiscussion, {
           store,
+          pinia,
           propsData: { discussion: discussionMock },
         });
       });
@@ -324,6 +339,7 @@ describe('noteable_discussion component', () => {
     const mock = jest.fn();
     wrapper = mount(NoteableDiscussion, {
       store,
+      pinia,
       propsData: { discussion: discussionMock },
       stubs: { NoteForm: { methods: { append: mock }, render() {} } },
     });
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index a10f4d1cefee3..32aacecfcaa95 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -1,7 +1,9 @@
 import { mount, shallowMount } from '@vue/test-utils';
+import { createTestingPinia } from '@pinia/testing';
 import AxiosMockAdapter from 'axios-mock-adapter';
 import $ from 'jquery';
 import Vue, { nextTick } from 'vue';
+import { PiniaVuePlugin } from 'pinia';
 import VueApollo from 'vue-apollo';
 import setWindowLocation from 'helpers/set_window_location_helper';
 import { mockTracking } from 'helpers/tracking_helper';
@@ -25,6 +27,9 @@ import { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
 import { Mousetrap } from '~/lib/mousetrap';
 import { ISSUABLE_COMMENT_OR_REPLY, keysFor } from '~/behaviors/shortcuts/keybindings';
 import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
+import { useNotes } from '~/notes/store/legacy_notes';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { globalAccessorPlugin } from '~/pinia/plugins';
 import createMockApollo from 'helpers/mock_apollo_helper';
 import noteQuery from '~/notes/graphql/note.query.graphql';
 import * as mockData from '../mock_data';
@@ -45,11 +50,14 @@ const propsData = {
   notesFilterValue: TEST_NOTES_FILTER_VALUE,
 };
 
+Vue.use(PiniaVuePlugin);
+
 describe('note_app', () => {
   let axiosMock;
   let mountComponent;
   let wrapper;
   let store;
+  let pinia;
 
   const initStore = (notesData = propsData.notesData) => {
     store.dispatch('setNotesData', notesData);
@@ -78,6 +86,10 @@ describe('note_app', () => {
     axiosMock = new AxiosMockAdapter(axios);
     Vue.use(VueApollo);
 
+    pinia = createTestingPinia({ plugins: [globalAccessorPlugin] });
+    useLegacyDiffs();
+    useNotes();
+
     store = createStore();
 
     mountComponent = ({ props = {} } = {}) => {
@@ -98,6 +110,7 @@ describe('note_app', () => {
             ...props,
           },
           store,
+          pinia,
         },
       );
     };
-- 
GitLab