@@ -176,6 +176,96 @@ describe('Inline Toolbar', () => {
176176 } ) ;
177177
178178 describe ( 'Shortcuts' , ( ) => {
179+ it ( 'should work when multiple editor instances are present on the same page' , ( ) => {
180+ const toolActivated1 = cy . stub ( ) . as ( 'toolActivated1' ) ;
181+ const toolActivated2 = cy . stub ( ) . as ( 'toolActivated2' ) ;
182+
183+ /* eslint-disable jsdoc/require-jsdoc */
184+ class Marker1 implements InlineTool {
185+ public static isInline = true ;
186+ public static shortcut = 'CMD+SHIFT+M' ;
187+ public render ( ) : MenuConfig {
188+ return {
189+ icon : 'm' ,
190+ title : 'Marker' ,
191+ onActivate : ( ) => { toolActivated1 ( ) ; } ,
192+ } ;
193+ }
194+ }
195+ class Marker2 implements InlineTool {
196+ public static isInline = true ;
197+ public static shortcut = 'CMD+SHIFT+M' ;
198+ public render ( ) : MenuConfig {
199+ return {
200+ icon : 'm' ,
201+ title : 'Marker' ,
202+ onActivate : ( ) => { toolActivated2 ( ) ; } ,
203+ } ;
204+ }
205+ }
206+ /* eslint-enable jsdoc/require-jsdoc */
207+
208+ /** Create first editor */
209+ cy . createEditor ( {
210+ data : {
211+ blocks : [ { type : 'paragraph' , data : { text : 'First editor text' } } ] ,
212+ } ,
213+ tools : { marker : Marker1 } ,
214+ } ) ;
215+
216+ /** Create second editor with a different holder */
217+ cy . window ( ) . then ( ( win ) => {
218+ const holder = win . document . createElement ( 'div' ) ;
219+
220+ holder . id = 'editorjs2' ;
221+ holder . dataset . cy = 'editorjs2' ;
222+ win . document . body . appendChild ( holder ) ;
223+
224+ return new Promise < void > ( ( resolve ) => {
225+ const editor2 = new win . EditorJS ( {
226+ holder : 'editorjs2' ,
227+ data : {
228+ blocks : [ { type : 'paragraph' , data : { text : 'Second editor text' } } ] ,
229+ } ,
230+ tools : { marker : Marker2 } ,
231+ } ) ;
232+
233+ editor2 . isReady . then ( ( ) => resolve ( ) ) ;
234+ } ) ;
235+ } ) ;
236+
237+ /** Select text in first editor to open its inline toolbar and register its shortcuts */
238+ cy . get ( '[data-cy=editorjs]' )
239+ . find ( '.ce-paragraph' )
240+ . selectText ( 'editor' ) ;
241+
242+ /** Select text in second editor — closes the first editor's toolbar and opens the second's */
243+ cy . get ( '[data-cy=editorjs2]' )
244+ . find ( '.ce-paragraph' )
245+ . selectText ( 'editor' ) ;
246+
247+ /** Wait for the second editor's inline toolbar to be visible before dispatching the shortcut */
248+ cy . get ( '[data-cy=editorjs2] [data-cy="inline-toolbar"] .ce-popover__container' )
249+ . should ( 'be.visible' ) ;
250+
251+ cy . document ( ) . then ( ( doc ) => {
252+ doc . dispatchEvent ( new KeyboardEvent ( 'keydown' , {
253+ bubbles : true ,
254+ cancelable : true ,
255+ key : 'M' ,
256+ code : 'KeyM' ,
257+ keyCode : 77 ,
258+ which : 77 ,
259+ metaKey : true ,
260+ shiftKey : true ,
261+ } ) ) ;
262+ } ) ;
263+
264+ /** Second editor's shortcut should fire, first editor's should not */
265+ cy . get ( '@toolActivated2' ) . should ( 'have.been.called' ) ;
266+ cy . get ( '@toolActivated1' ) . should ( 'not.have.been.called' ) ;
267+ } ) ;
268+
179269 it ( 'should work in read-only mode' , ( ) => {
180270 const toolSurround = cy . stub ( ) . as ( 'toolSurround' ) ;
181271
0 commit comments