@@ -6,6 +6,8 @@ import MainMenu from '@/views/MainView/MainMenu'
66import storedInquiries from '@/lib/storedInquiries'
77import { nextTick } from 'vue'
88import eventBus from '@/lib/eventBus'
9+ import actions from '@/store/actions'
10+ import mutations from '@/store/mutations'
911
1012let wrapper = null
1113
@@ -642,6 +644,101 @@ describe('MainMenu.vue', () => {
642644 expect ( eventBus . $emit . calledOnceWith ( 'inquirySaved' ) ) . to . equal ( true )
643645 } )
644646
647+ it ( 'Inquiry conflict after saving new inquiry: overwrite' , async ( ) => {
648+ const tab = {
649+ id : 1 ,
650+ name : null ,
651+ query : 'SELECT * FROM foo' ,
652+ updatedAt : undefined ,
653+ execute : sinon . stub ( ) ,
654+ dataView : { getOptionsForSave : sinon . stub ( ) } ,
655+ isSaved : false
656+ }
657+ const state = {
658+ currentTab : tab ,
659+ inquiries : [ ] ,
660+ tabs : [ tab ] ,
661+ db : { }
662+ }
663+ const store = createStore ( { state, mutations, actions } )
664+ const $route = { path : '/workspace' }
665+
666+ wrapper = mount ( MainMenu , {
667+ attachTo : document . body ,
668+ global : {
669+ mocks : { $route } ,
670+ stubs : {
671+ 'router-link' : true ,
672+ 'app-diagnostic-info' : true ,
673+ teleport : true ,
674+ transition : false
675+ } ,
676+ plugins : [ store ]
677+ }
678+ } )
679+
680+ await wrapper . find ( '#save-btn' ) . trigger ( 'click' )
681+
682+ // check that Save dialog is open
683+ expect ( wrapper . find ( '.dialog.vfm' ) . exists ( ) ) . to . equal ( true )
684+ expect ( wrapper . find ( '.dialog.vfm .dialog-header' ) . text ( ) ) . to . contain (
685+ 'Save inquiry'
686+ )
687+
688+ // enter the name
689+ await wrapper . find ( '.dialog-body input' ) . setValue ( 'foo' )
690+
691+ // find Save in the dialog and click
692+ await wrapper
693+ . findAll ( '.dialog-buttons-container button' )
694+ . find ( button => button . text ( ) === 'Save' )
695+ . trigger ( 'click' )
696+
697+ await nextTick ( )
698+
699+ // check that the dialog is closed
700+ await clock . tick ( 100 )
701+ expect ( wrapper . find ( '.dialog.vfm' ) . exists ( ) ) . to . equal ( false )
702+
703+ // check that now there is one inquiry saved
704+ expect ( state . inquiries . length ) . to . equal ( 1 )
705+ expect ( state . inquiries [ 0 ] . name ) . to . equal ( 'foo' )
706+ expect ( state . tabs [ 0 ] . name ) . to . equal ( 'foo' )
707+
708+ // change the inquiry in store (like it's updated in another tab)
709+ store . state . inquiries [ 0 ] . query = 'SELECT * FROM foo_updated_in_another_tab'
710+ store . state . inquiries [ 0 ] . updatedAt = '2025-05-15T00:00:10Z'
711+ store . state . currentTab . query = 'SELECT * FROM foo_new'
712+ store . state . currentTab . isSaved = false
713+ await nextTick ( )
714+ await wrapper . find ( '#save-btn' ) . trigger ( 'click' )
715+
716+ // check that the conflict dialog is open
717+ expect ( wrapper . find ( '.dialog.vfm' ) . exists ( ) ) . to . equal ( true )
718+ expect ( wrapper . find ( '.dialog.vfm .dialog-header' ) . text ( ) ) . to . contain (
719+ 'Inquiry saving conflict'
720+ )
721+
722+ // find Overwrite in the dialog and click
723+ await wrapper
724+ . findAll ( '.dialog-buttons-container button' )
725+ . find ( button => button . text ( ) === 'Overwrite' )
726+ . trigger ( 'click' )
727+
728+ await nextTick ( )
729+
730+ // check that the dialog is closed
731+ await clock . tick ( 100 )
732+ expect ( wrapper . find ( '.dialog.vfm' ) . exists ( ) ) . to . equal ( false )
733+
734+ // check that it's still one inquiry saved
735+ expect ( state . inquiries . length ) . to . equal ( 1 )
736+ expect ( state . inquiries [ 0 ] . name ) . to . equal ( 'foo' )
737+ expect ( state . tabs [ 0 ] . name ) . to . equal ( 'foo' )
738+ expect ( state . inquiries [ 0 ] . query ) . to . equal ( 'SELECT * FROM foo_new' )
739+ expect ( state . tabs [ 0 ] . query ) . to . equal ( 'SELECT * FROM foo_new' )
740+ } )
741+
645742 it ( 'Inquiry conflict: save as new' , async ( ) => {
646743 const tab = {
647744 id : 1 ,
0 commit comments