diff --git a/packages/ckeditor5-engine/src/view/observer/keyobserver.js b/packages/ckeditor5-engine/src/view/observer/keyobserver.js index 36a3f9d5de9..8b9e0111e01 100644 --- a/packages/ckeditor5-engine/src/view/observer/keyobserver.js +++ b/packages/ckeditor5-engine/src/view/observer/keyobserver.js @@ -29,8 +29,9 @@ export default class KeyObserver extends DomEventObserver { keyCode: domEvt.keyCode, altKey: domEvt.altKey, - ctrlKey: domEvt.ctrlKey || domEvt.metaKey, + ctrlKey: domEvt.ctrlKey, shiftKey: domEvt.shiftKey, + metaKey: domEvt.metaKey, get keystroke() { return getCode( this ); diff --git a/packages/ckeditor5-engine/tests/view/observer/keyobserver.js b/packages/ckeditor5-engine/tests/view/observer/keyobserver.js index 89345a84a86..8c3923f4d1f 100644 --- a/packages/ckeditor5-engine/tests/view/observer/keyobserver.js +++ b/packages/ckeditor5-engine/tests/view/observer/keyobserver.js @@ -84,17 +84,28 @@ describe( 'KeyObserver', () => { expect( getCode( data ) ).to.be.greaterThan( 111 ); } ); - it( 'should fire keydown ctrlKey set to true one meta (cmd) was pressed', () => { + it( 'should fire keydown with ctrlKey set to true once ctrl was pressed', () => { const spy = sinon.spy(); viewDocument.on( 'keydown', spy ); - observer.onDomEvent( { type: 'keydown', target: document.body, keyCode: 111, metaKey: true } ); + observer.onDomEvent( { type: 'keydown', target: document.body, keyCode: 111, ctrlKey: true } ); const data = spy.args[ 0 ][ 1 ]; expect( data ).to.have.property( 'ctrlKey', true ); } ); + it( 'should fire keydown with metaKey set to true once meta (cmd) was pressed', () => { + const spy = sinon.spy(); + + viewDocument.on( 'keydown', spy ); + + observer.onDomEvent( { type: 'keydown', target: document.body, keyCode: 111, metaKey: true } ); + + const data = spy.args[ 0 ][ 1 ]; + expect( data ).to.have.property( 'metaKey', true ); + } ); + it( 'should fire keyup with the target and key info', () => { const spy = sinon.spy(); diff --git a/packages/ckeditor5-list/docs/features/todo-lists.md b/packages/ckeditor5-list/docs/features/todo-lists.md index 6a7cceae5ce..92a0b45c499 100644 --- a/packages/ckeditor5-list/docs/features/todo-lists.md +++ b/packages/ckeditor5-list/docs/features/todo-lists.md @@ -16,7 +16,7 @@ To-do lists can be introduced using the dedicated toolbar button. Thanks to the ## Keyboard support -You can check and uncheck a list item by using the Ctrl + Space shortcut when the selection is in that item. +You can check and uncheck a list item by using the Ctrl + Enter ( + Enter on Mac) shortcut when the selection is in that item. ## Installation diff --git a/packages/ckeditor5-list/src/todolistediting.js b/packages/ckeditor5-list/src/todolistediting.js index ccc6fb1dbad..a0a6d568cf8 100644 --- a/packages/ckeditor5-list/src/todolistediting.js +++ b/packages/ckeditor5-list/src/todolistediting.js @@ -8,7 +8,11 @@ */ import { Plugin } from 'ckeditor5/src/core'; -import { getLocalizedArrowKeyCodeDirection } from 'ckeditor5/src/utils'; +import { + getCode, + parseKeystroke, + getLocalizedArrowKeyCodeDirection +} from 'ckeditor5/src/utils'; import ListCommand from './listcommand'; import ListEditing from './listediting'; @@ -22,6 +26,8 @@ import { modelViewInsertion } from './todolistconverters'; +const ITEM_TOGGLE_KEYSTROKE = parseKeystroke( 'Ctrl+Enter' ); + /** * The engine of the to-do list feature. It handles creating, editing and removing to-do lists and their items. * @@ -113,7 +119,12 @@ export default class TodoListEditing extends Plugin { this.listenTo( editing.view.document, 'keydown', jumpOverCheckmarkOnSideArrowKeyPress( model, editor.locale ) ); // Toggle check state of selected to-do list items on keystroke. - editor.keystrokes.set( 'Ctrl+space', () => editor.execute( 'checkTodoList' ) ); + this.listenTo( editing.view.document, 'keydown', ( evt, data ) => { + if ( getCode( data ) === ITEM_TOGGLE_KEYSTROKE ) { + editor.execute( 'checkTodoList' ); + evt.stop(); + } + }, { priority: 'high' } ); // Remove `todoListChecked` attribute when a host element is no longer a to-do list item. const listItemsToFix = new Set(); diff --git a/packages/ckeditor5-list/tests/todolistediting.js b/packages/ckeditor5-list/tests/todolistediting.js index e56df30fa23..0147faf5396 100644 --- a/packages/ckeditor5-list/tests/todolistediting.js +++ b/packages/ckeditor5-list/tests/todolistediting.js @@ -23,12 +23,16 @@ import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; +import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; +import { env } from '@ckeditor/ckeditor5-utils'; /* global Event, document */ describe( 'TodoListEditing', () => { let editor, model, modelDoc, modelRoot, view, viewDoc; + testUtils.createSinonSandbox(); + beforeEach( () => { return VirtualTestEditor .create( { @@ -1154,30 +1158,55 @@ describe( 'TodoListEditing', () => { sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); } ); + + it( 'should do nothing when other arrow key was pressed', () => { + setModelData( model, '[]bar' ); + + domEvtDataStub = { + keyCode: getCode( 'arrowDown' ), + preventDefault: sinon.spy(), + stopPropagation: sinon.spy(), + domTarget: { + ownerDocument: { + defaultView: { + getSelection: () => ( { rangeCount: 0 } ) + } + } + } + }; + + viewDoc.fire( 'keydown', domEvtDataStub ); + + sinon.assert.notCalled( domEvtDataStub.preventDefault ); + sinon.assert.notCalled( domEvtDataStub.stopPropagation ); + } ); } } ); - describe( 'Ctrl+space keystroke handling', () => { - let domEvtDataStub; + describe( 'Ctrl+enter keystroke handling', () => { + it( 'should execute CheckTodoListCommand', () => { + const command = editor.commands.get( 'checkTodoList' ); + + sinon.spy( command, 'execute' ); - beforeEach( () => { - domEvtDataStub = { - keyCode: getCode( 'space' ), - ctrlKey: true, + const domEvtDataStub = { + keyCode: getCode( 'enter' ), preventDefault: sinon.spy(), stopPropagation: sinon.spy() }; - } ); - it( 'should execute CheckTodoListCommand', () => { - const command = editor.commands.get( 'checkTodoList' ); - - sinon.spy( command, 'execute' ); + if ( env.isMac ) { + domEvtDataStub.metaKey = true; + } else { + domEvtDataStub.ctrlKey = true; + } + // First call. viewDoc.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( command.execute ); + // Second call. viewDoc.fire( 'keydown', domEvtDataStub ); sinon.assert.calledTwice( command.execute ); diff --git a/packages/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling.js b/packages/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling.js index 73183651c04..d133f020f40 100644 --- a/packages/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling.js +++ b/packages/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling.js @@ -171,8 +171,8 @@ for ( let code = 112; code <= 135; code++ ) { * @returns {Boolean} */ export function isNonTypingKeystroke( keyData ) { - // Keystrokes which contain Ctrl don't represent typing. - if ( keyData.ctrlKey ) { + // Keystrokes which contain Ctrl or Cmd don't represent typing. + if ( keyData.ctrlKey || keyData.metaKey ) { return true; } diff --git a/packages/ckeditor5-typing/tests/utils/injectunsafekeystrokeshandling.js b/packages/ckeditor5-typing/tests/utils/injectunsafekeystrokeshandling.js index 01d5c8dcd10..4852162abd6 100644 --- a/packages/ckeditor5-typing/tests/utils/injectunsafekeystrokeshandling.js +++ b/packages/ckeditor5-typing/tests/utils/injectunsafekeystrokeshandling.js @@ -17,6 +17,11 @@ describe( 'unsafe keystroke handling utils', () => { expect( isNonTypingKeystroke( { keyCode: keyCodes[ 0 ], ctrlKey: true } ), 'Ctrl+0' ).to.be.true; } ); + it( 'should return "true" for any keystroke with the Cmd key', () => { + expect( isNonTypingKeystroke( { keyCode: keyCodes.a, metaKey: true } ), '⌘a' ).to.be.true; + expect( isNonTypingKeystroke( { keyCode: keyCodes[ 0 ], metaKey: true } ), '⌘0' ).to.be.true; + } ); + it( 'should return "true" for all arrow keys', () => { expect( isNonTypingKeystroke( { keyCode: keyCodes.arrowup } ), 'arrow up' ).to.be.true; expect( isNonTypingKeystroke( { keyCode: keyCodes.arrowdown } ), 'arrow down' ).to.be.true; diff --git a/packages/ckeditor5-utils/src/keyboard.js b/packages/ckeditor5-utils/src/keyboard.js index 1feda514de4..fdd2d41febd 100644 --- a/packages/ckeditor5-utils/src/keyboard.js +++ b/packages/ckeditor5-utils/src/keyboard.js @@ -12,16 +12,17 @@ import CKEditorError from './ckeditorerror'; import env from './env'; -const macGlyphsToModifiers = { - '⌘': 'ctrl', - '⇧': 'shift', - '⌥': 'alt' +const modifiersToGlyphsMac = { + ctrl: '⌃', + cmd: '⌘', + alt: '⌥', + shift: '⇧' }; -const modifiersToMacGlyphs = { - 'ctrl': '⌘', - 'shift': '⇧', - 'alt': '⌥' +const modifiersToGlyphsNonMac = { + ctrl: 'Ctrl+', + alt: 'Alt+', + shift: 'Shift+' }; /** @@ -38,6 +39,10 @@ const modifiersToMacGlyphs = { */ export const keyCodes = generateKnownKeyCodes(); +const keyCodeNames = Object.fromEntries( + Object.entries( keyCodes ).map( ( [ name, code ] ) => [ code, name.charAt( 0 ).toUpperCase() + name.slice( 1 ) ] ) +); + /** * Converts a key name or a {@link module:utils/keyboard~KeystrokeInfo keystroke info} into a key code. * @@ -66,7 +71,8 @@ export function getCode( key ) { keyCode = key.keyCode + ( key.altKey ? keyCodes.alt : 0 ) + ( key.ctrlKey ? keyCodes.ctrl : 0 ) + - ( key.shiftKey ? keyCodes.shift : 0 ); + ( key.shiftKey ? keyCodes.shift : 0 ) + + ( key.metaKey ? keyCodes.cmd : 0 ); } return keyCode; @@ -96,7 +102,7 @@ export function parseKeystroke( keystroke ) { } return keystroke - .map( key => ( typeof key == 'string' ) ? getCode( key ) : key ) + .map( key => ( typeof key == 'string' ) ? getEnvKeyCode( key ) : key ) .reduce( ( key, sum ) => sum + key, 0 ); } @@ -108,22 +114,21 @@ export function parseKeystroke( keystroke ) { * @returns {String} Keystroke text specific for the environment. */ export function getEnvKeystrokeText( keystroke ) { - if ( !env.isMac ) { - return keystroke; - } + let keystrokeCode = parseKeystroke( keystroke ); + + const modifiersToGlyphs = Object.entries( env.isMac ? modifiersToGlyphsMac : modifiersToGlyphsNonMac ); + + const modifiers = modifiersToGlyphs.reduce( ( modifiers, [ name, glyph ] ) => { + // Modifier keys are stored as a bit mask so extract those from the keystroke code. + if ( ( keystrokeCode & keyCodes[ name ] ) != 0 ) { + keystrokeCode &= ~keyCodes[ name ]; + modifiers += glyph; + } + + return modifiers; + }, '' ); - return splitKeystrokeText( keystroke ) - // Replace modifiers (e.g. "ctrl") with Mac glyphs (e.g. "⌘") first. - .map( key => modifiersToMacGlyphs[ key.toLowerCase() ] || key ) - - // Decide whether to put "+" between keys in the keystroke or not. - .reduce( ( value, key ) => { - if ( value.slice( -1 ) in macGlyphsToModifiers ) { - return value + key; - } else { - return value + '+' + key; - } - } ); + return modifiers + ( keystrokeCode ? keyCodeNames[ keystrokeCode ] : '' ); } /** @@ -169,6 +174,23 @@ export function getLocalizedArrowKeyCodeDirection( keyCode, contentLanguageDirec } } +// Converts a key name to the key code with mapping based on the env. +// +// See: {@link module:utils/keyboard~getCode}. +// +// @param {String} key The key name (see {@link module:utils/keyboard~keyCodes}). +// @returns {Number} Key code. +function getEnvKeyCode( key ) { + // Don't remap modifier key for forced modifiers. + if ( key.endsWith( '!' ) ) { + return getCode( key.slice( 0, -1 ) ); + } + + const code = getCode( key ); + + return env.isMac && code == keyCodes.ctrl ? keyCodes.cmd : code; +} + /** * Determines if the provided key code moves the {@link module:engine/model/documentselection~DocumentSelection selection} * forward or backward considering the language direction of the editor content. @@ -203,11 +225,9 @@ function generateKnownKeyCodes() { // The idea about these numbers is that they do not collide with any real key codes, so we can use them // like bit masks. ctrl: 0x110000, - // Has the same code as ctrl, because their behaviour should be unified across the editor. - // See http://ckeditor.github.io/editor-recommendations/general-policies#ctrl-vs-cmd - cmd: 0x110000, shift: 0x220000, - alt: 0x440000 + alt: 0x440000, + cmd: 0x880000 }; // a-z @@ -249,17 +269,23 @@ function splitKeystrokeText( keystroke ) { /** * Whether the Alt modifier was pressed. * - * @member {Bolean} module:utils/keyboard~KeystrokeInfo#altKey + * @member {Boolean} module:utils/keyboard~KeystrokeInfo#altKey */ /** - * Whether the Ctrl or Cmd modifier was pressed. + * Whether the Ctrl modifier was pressed. * - * @member {Bolean} module:utils/keyboard~KeystrokeInfo#ctrlKey + * @member {Boolean} module:utils/keyboard~KeystrokeInfo#ctrlKey */ /** * Whether the Shift modifier was pressed. * - * @member {Bolean} module:utils/keyboard~KeystrokeInfo#shiftKey + * @member {Boolean} module:utils/keyboard~KeystrokeInfo#shiftKey + */ + +/** + * Whether the Cmd modifier was pressed. + * + * @member {Boolean} module:utils/keyboard~KeystrokeInfo#metaKey */ diff --git a/packages/ckeditor5-utils/tests/keyboard.js b/packages/ckeditor5-utils/tests/keyboard.js index d497a167c61..e7114906938 100644 --- a/packages/ckeditor5-utils/tests/keyboard.js +++ b/packages/ckeditor5-utils/tests/keyboard.js @@ -30,7 +30,7 @@ describe( 'Keyboard', () => { it( 'modifiers and other keys', () => { expect( keyCodes.delete ).to.equal( 46 ); expect( keyCodes.ctrl ).to.equal( 0x110000 ); - expect( keyCodes.cmd ).to.equal( 0x110000 ); + expect( keyCodes.cmd ).to.equal( 0x880000 ); expect( keyCodes.f1 ).to.equal( 112 ); expect( keyCodes.f12 ).to.equal( 123 ); @@ -73,40 +73,96 @@ describe( 'Keyboard', () => { } ); it( 'adds modifiers to the keystroke code', () => { - expect( getCode( { keyCode: 48, altKey: true, ctrlKey: true, shiftKey: true } ) ) - .to.equal( 48 + 0x110000 + 0x220000 + 0x440000 ); + expect( getCode( { keyCode: 48, altKey: true, ctrlKey: true, shiftKey: true, metaKey: true } ) ) + .to.equal( 48 + 0x110000 + 0x220000 + 0x440000 + 0x880000 ); } ); } ); describe( 'parseKeystroke', () => { - it( 'parses string', () => { - expect( parseKeystroke( 'ctrl+a' ) ).to.equal( 0x110000 + 65 ); - } ); + const initialEnvMac = env.isMac; - it( 'allows spacing', () => { - expect( parseKeystroke( 'ctrl + a' ) ).to.equal( 0x110000 + 65 ); + afterEach( () => { + env.isMac = initialEnvMac; } ); - it( 'is case-insensitive', () => { - expect( parseKeystroke( 'Ctrl+A' ) ).to.equal( 0x110000 + 65 ); - } ); + describe( 'on Macintosh', () => { + beforeEach( () => { + env.isMac = true; + } ); - it( 'works with an array', () => { - expect( parseKeystroke( [ 'ctrl', 'a' ] ) ).to.equal( 0x110000 + 65 ); - } ); + it( 'parses string', () => { + expect( parseKeystroke( 'ctrl+a' ) ).to.equal( 0x880000 + 65 ); + } ); - it( 'works with an array which contains numbers', () => { - expect( parseKeystroke( [ 'shift', 33 ] ) ).to.equal( 0x220000 + 33 ); - } ); + it( 'allows spacing', () => { + expect( parseKeystroke( 'ctrl + a' ) ).to.equal( 0x880000 + 65 ); + } ); + + it( 'is case-insensitive', () => { + expect( parseKeystroke( 'Ctrl+A' ) ).to.equal( 0x880000 + 65 ); + } ); + + it( 'works with an array', () => { + expect( parseKeystroke( [ 'ctrl', 'a' ] ) ).to.equal( 0x880000 + 65 ); + } ); + + it( 'works with an array which contains numbers', () => { + expect( parseKeystroke( [ 'shift', 33 ] ) ).to.equal( 0x220000 + 33 ); + } ); + + it( 'works with two modifiers', () => { + expect( parseKeystroke( 'ctrl+shift+a' ) ).to.equal( 0x880000 + 0x220000 + 65 ); + } ); - it( 'works with two modifiers', () => { - expect( parseKeystroke( 'ctrl+shift+a' ) ).to.equal( 0x110000 + 0x220000 + 65 ); + it( 'supports forced modifier', () => { + expect( parseKeystroke( 'ctrl!+a' ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'throws on unknown name', () => { + expectToThrowCKEditorError( () => { + parseKeystroke( 'foo' ); + }, 'keyboard-unknown-key', null ); + } ); } ); - it( 'throws on unknown name', () => { - expectToThrowCKEditorError( () => { - parseKeystroke( 'foo' ); - }, 'keyboard-unknown-key', null ); + describe( 'on non–Macintosh', () => { + beforeEach( () => { + env.isMac = false; + } ); + + it( 'parses string', () => { + expect( parseKeystroke( 'ctrl+a' ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'allows spacing', () => { + expect( parseKeystroke( 'ctrl + a' ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'is case-insensitive', () => { + expect( parseKeystroke( 'Ctrl+A' ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'works with an array', () => { + expect( parseKeystroke( [ 'ctrl', 'a' ] ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'works with an array which contains numbers', () => { + expect( parseKeystroke( [ 'shift', 33 ] ) ).to.equal( 0x220000 + 33 ); + } ); + + it( 'works with two modifiers', () => { + expect( parseKeystroke( 'ctrl+shift+a' ) ).to.equal( 0x110000 + 0x220000 + 65 ); + } ); + + it( 'supports forced modifier', () => { + expect( parseKeystroke( 'ctrl!+a' ) ).to.equal( 0x110000 + 65 ); + } ); + + it( 'throws on unknown name', () => { + expectToThrowCKEditorError( () => { + parseKeystroke( 'foo' ); + }, 'keyboard-unknown-key', null ); + } ); } ); } ); @@ -128,6 +184,12 @@ describe( 'Keyboard', () => { expect( getEnvKeystrokeText( 'ctrl+A' ) ).to.equal( '⌘A' ); } ); + it( 'replaces CTRL! with ⌃', () => { + expect( getEnvKeystrokeText( 'CTRL!' ) ).to.equal( '⌃' ); + expect( getEnvKeystrokeText( 'CTRL!+A' ) ).to.equal( '⌃A' ); + expect( getEnvKeystrokeText( 'ctrl!+A' ) ).to.equal( '⌃A' ); + } ); + it( 'replaces SHIFT with ⇧', () => { expect( getEnvKeystrokeText( 'SHIFT' ) ).to.equal( '⇧' ); expect( getEnvKeystrokeText( 'SHIFT+A' ) ).to.equal( '⇧A' ); @@ -145,11 +207,13 @@ describe( 'Keyboard', () => { expect( getEnvKeystrokeText( 'ALT+SHIFT+X' ) ).to.equal( '⌥⇧X' ); } ); - it( 'does not touch other keys', () => { - expect( getEnvKeystrokeText( 'ESC+A' ) ).to.equal( 'ESC+A' ); - expect( getEnvKeystrokeText( 'TAB' ) ).to.equal( 'TAB' ); + it( 'normalizes value', () => { + expect( getEnvKeystrokeText( 'ESC' ) ).to.equal( 'Esc' ); + expect( getEnvKeystrokeText( 'TAB' ) ).to.equal( 'Tab' ); expect( getEnvKeystrokeText( 'A' ) ).to.equal( 'A' ); - expect( getEnvKeystrokeText( 'A+CTRL+B' ) ).to.equal( 'A+⌘B' ); + expect( getEnvKeystrokeText( 'a' ) ).to.equal( 'A' ); + expect( getEnvKeystrokeText( 'CTRL+a' ) ).to.equal( '⌘A' ); + expect( getEnvKeystrokeText( 'ctrl+b' ) ).to.equal( '⌘B' ); } ); } ); @@ -158,13 +222,18 @@ describe( 'Keyboard', () => { env.isMac = false; } ); - it( 'does not touch anything', () => { - expect( getEnvKeystrokeText( 'CTRL+A' ) ).to.equal( 'CTRL+A' ); - expect( getEnvKeystrokeText( 'ctrl+A' ) ).to.equal( 'ctrl+A' ); - expect( getEnvKeystrokeText( 'SHIFT+A' ) ).to.equal( 'SHIFT+A' ); - expect( getEnvKeystrokeText( 'alt+A' ) ).to.equal( 'alt+A' ); - expect( getEnvKeystrokeText( 'CTRL+SHIFT+A' ) ).to.equal( 'CTRL+SHIFT+A' ); + it( 'normalizes value', () => { + expect( getEnvKeystrokeText( 'ESC' ) ).to.equal( 'Esc' ); + expect( getEnvKeystrokeText( 'TAB' ) ).to.equal( 'Tab' ); expect( getEnvKeystrokeText( 'A' ) ).to.equal( 'A' ); + expect( getEnvKeystrokeText( 'a' ) ).to.equal( 'A' ); + expect( getEnvKeystrokeText( 'CTRL+a' ) ).to.equal( 'Ctrl+A' ); + expect( getEnvKeystrokeText( 'CTRL!+a' ) ).to.equal( 'Ctrl+A' ); + expect( getEnvKeystrokeText( 'ctrl+b' ) ).to.equal( 'Ctrl+B' ); + expect( getEnvKeystrokeText( 'ctrl!+b' ) ).to.equal( 'Ctrl+B' ); + expect( getEnvKeystrokeText( 'SHIFT+A' ) ).to.equal( 'Shift+A' ); + expect( getEnvKeystrokeText( 'alt+A' ) ).to.equal( 'Alt+A' ); + expect( getEnvKeystrokeText( 'CTRL+SHIFT+A' ) ).to.equal( 'Ctrl+Shift+A' ); } ); } ); } ); diff --git a/packages/ckeditor5-utils/tests/keystrokehandler.js b/packages/ckeditor5-utils/tests/keystrokehandler.js index 45bb5613043..7f77abfbcd9 100644 --- a/packages/ckeditor5-utils/tests/keystrokehandler.js +++ b/packages/ckeditor5-utils/tests/keystrokehandler.js @@ -6,17 +6,25 @@ import EmitterMixin from '../src/emittermixin'; import KeystrokeHandler from '../src/keystrokehandler'; import { keyCodes } from '../src/keyboard'; +import env from '../src/env'; describe( 'KeystrokeHandler', () => { + const initialEnvMac = env.isMac; let emitter, keystrokes; beforeEach( () => { + env.isMac = false; + emitter = Object.create( EmitterMixin ); keystrokes = new KeystrokeHandler(); keystrokes.listenTo( emitter ); } ); + afterEach( () => { + env.isMac = initialEnvMac; + } ); + describe( 'listenTo()', () => { it( 'activates the listening on the emitter', () => { const spy = sinon.spy();