diff --git a/spec/api-global-shortcut-spec.ts b/spec/api-global-shortcut-spec.ts index a88d08647347..cf6f9fc7d752 100644 --- a/spec/api-global-shortcut-spec.ts +++ b/spec/api-global-shortcut-spec.ts @@ -2,51 +2,15 @@ import { globalShortcut } from 'electron/main'; import { expect } from 'chai'; +import { singleModifierCombinations, doubleModifierCombinations } from './lib/accelerator-helpers'; import { ifdescribe } from './lib/spec-helpers'; -const modifiers = [ - 'CmdOrCtrl', - 'Alt', - process.platform === 'darwin' ? 'Option' : null, - 'AltGr', - 'Shift', - 'Super', - 'Meta' -].filter(Boolean); - -const keyCodes = [ - ...Array.from({ length: 10 }, (_, i) => `${i}`), // 0 to 9 - ...Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i)), // A to Z - ...Array.from({ length: 24 }, (_, i) => `F${i + 1}`), // F1 to F24 - ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ';', ':', '+', '=', - '<', ',', '_', '-', '>', '.', '?', '/', '~', '`', '{', ']', '[', '|', '\\', - '}', '"', 'Plus', 'Space', 'Tab', 'Capslock', 'Numlock', 'Scrolllock', - 'Backspace', 'Delete', 'Insert', 'Return', 'Enter', 'Up', 'Down', 'Left', - 'Right', 'Home', 'End', 'PageUp', 'PageDown', 'Escape', 'Esc', 'PrintScreen', - 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', - 'numdec', 'numadd', 'numsub', 'nummult', 'numdiv' -]; - ifdescribe(process.platform !== 'win32')('globalShortcut module', () => { beforeEach(() => { globalShortcut.unregisterAll(); }); it('can register and unregister single accelerators', () => { - const singleModifierCombinations = modifiers.flatMap( - mod => keyCodes.map(key => { - return key === '+' ? `${mod}+Plus` : `${mod}+${key}`; - }) - ); - - const doubleModifierCombinations = modifiers.flatMap( - (mod1, i) => modifiers.slice(i + 1).flatMap( - mod2 => keyCodes.map(key => { - return key === '+' ? `${mod1}+${mod2}+Plus` : `${mod1}+${mod2}+${key}`; - }) - ) - ); - const combinations = [...singleModifierCombinations, ...doubleModifierCombinations]; combinations.forEach((accelerator) => { diff --git a/spec/api-menu-spec.ts b/spec/api-menu-spec.ts index e3343e8cf107..9e8143e94ac8 100644 --- a/spec/api-menu-spec.ts +++ b/spec/api-menu-spec.ts @@ -7,6 +7,7 @@ import { once } from 'node:events'; import * as path from 'node:path'; import { setTimeout } from 'node:timers/promises'; +import { singleModifierCombinations } from './lib/accelerator-helpers'; import { ifit } from './lib/spec-helpers'; import { closeWindow } from './lib/window-helpers'; import { sortMenuItems } from '../lib/browser/api/menu-utils'; @@ -927,19 +928,22 @@ describe('Menu module', function () { w.show(); }); - it('does not crash when rendering menu item with Super or meta accelerator', async () => { - const menu = Menu.buildFromTemplate([{ - label: 'Test Super', - accelerator: 'Super+Ctrl+T' - }, { - label: 'Test Meta', - accelerator: 'Meta+Ctrl+T' - }]); - const menuWillClose = once(menu, 'menu-will-close'); - menu.popup({ window: w }); - menu.closePopup(); - await menuWillClose; - }); + const chunkSize = 10; + let chunkCount = 0; + const totalChunks = Math.ceil(singleModifierCombinations.length / chunkSize); + for (let i = 0; i < singleModifierCombinations.length; i += chunkSize) { + const chunk = singleModifierCombinations.slice(i, i + chunkSize); + it(`does not crash when rendering menu item with single accelerator combinations ${++chunkCount}/${totalChunks}`, async () => { + const menu = Menu.buildFromTemplate([ + ...chunk.map(combination => ({ + label: `Test ${combination}`, + accelerator: combination + })) + ]); + menu.popup({ window: w }); + menu.closePopup(); + }); + } }); describe('Menu.setApplicationMenu', () => { diff --git a/spec/lib/accelerator-helpers.ts b/spec/lib/accelerator-helpers.ts new file mode 100644 index 000000000000..0ed3dd807b85 --- /dev/null +++ b/spec/lib/accelerator-helpers.ts @@ -0,0 +1,41 @@ +/** + * @fileoverview A set of helper functions to make it easier to work + * with accelerators across tests. + */ + +const modifiers = [ + 'CmdOrCtrl', + 'Alt', + process.platform === 'darwin' ? 'Option' : null, + 'AltGr', + 'Shift', + 'Super', + 'Meta' +].filter(Boolean); + +const keyCodes = [ + ...Array.from({ length: 10 }, (_, i) => `${i}`), // 0 to 9 + ...Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i)), // A to Z + ...Array.from({ length: 24 }, (_, i) => `F${i + 1}`), // F1 to F24 + ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ';', ':', '+', '=', + '<', ',', '_', '-', '>', '.', '?', '/', '~', '`', '{', ']', '[', '|', '\\', + '}', '"', 'Plus', 'Space', 'Tab', 'Capslock', 'Numlock', 'Scrolllock', + 'Backspace', 'Delete', 'Insert', 'Return', 'Enter', 'Up', 'Down', 'Left', + 'Right', 'Home', 'End', 'PageUp', 'PageDown', 'Escape', 'Esc', 'PrintScreen', + 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', + 'numdec', 'numadd', 'numsub', 'nummult', 'numdiv' +]; + +export const singleModifierCombinations = modifiers.flatMap( + mod => keyCodes.map(key => { + return key === '+' ? `${mod}+Plus` : `${mod}+${key}`; + }) +); + +export const doubleModifierCombinations = modifiers.flatMap( + (mod1, i) => modifiers.slice(i + 1).flatMap( + mod2 => keyCodes.map(key => { + return key === '+' ? `${mod1}+${mod2}+Plus` : `${mod1}+${mod2}+${key}`; + }) + ) +);