signal-desktop/ts/test-node/app/menu_test.ts
2022-01-11 09:28:04 -08:00

271 lines
7.2 KiB
TypeScript

// Copyright 2018-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { stub } from 'sinon';
import type { MenuItemConstructorOptions } from 'electron';
import type { MenuListType, MenuOptionsType } from '../../../app/menu';
import { createTemplate } from '../../../app/menu';
import { load as loadLocale } from '../../../app/locale';
const forceUpdate = stub();
const openContactUs = stub();
const openForums = stub();
const openJoinTheBeta = stub();
const openReleaseNotes = stub();
const openSupportPage = stub();
const setupAsNewDevice = stub();
const setupAsStandalone = stub();
const showAbout = stub();
const showDebugLog = stub();
const showKeyboardShortcuts = stub();
const showSettings = stub();
const showStickerCreator = stub();
const showWindow = stub();
const getExpectedEditMenu = (
includeSpeech: boolean
): MenuItemConstructorOptions => ({
label: '&Edit',
submenu: [
{ label: 'Undo', role: 'undo' },
{ label: 'Redo', role: 'redo' },
{ type: 'separator' },
{ label: 'Cut', role: 'cut' },
{ label: 'Copy', role: 'copy' },
{ label: 'Paste', role: 'paste' },
{ label: 'Paste and Match Style', role: 'pasteAndMatchStyle' },
{ label: 'Delete', role: 'delete' },
{ label: 'Select All', role: 'selectAll' },
...(includeSpeech
? ([
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ label: 'Start speaking', role: 'startSpeaking' },
{ label: 'Stop speaking', role: 'stopSpeaking' },
],
},
] as MenuListType)
: []),
],
});
const getExpectedViewMenu = (
zoomModifier: 'Command' | 'Control'
): MenuItemConstructorOptions => ({
label: '&View',
submenu: [
{ label: 'Actual Size', role: 'resetZoom' },
{ accelerator: `${zoomModifier}+=`, label: 'Zoom In', role: 'zoomIn' },
{ label: 'Zoom Out', role: 'zoomOut' },
{ type: 'separator' },
{ label: 'Toggle Full Screen', role: 'togglefullscreen' },
{ type: 'separator' },
{ label: 'Debug Log', click: showDebugLog },
{ type: 'separator' },
{ label: 'Toggle Developer Tools', role: 'toggleDevTools' },
{ label: 'Force Update', click: forceUpdate },
],
});
const getExpectedHelpMenu = (
includeAbout: boolean
): MenuItemConstructorOptions => ({
label: '&Help',
role: 'help',
submenu: [
{
label: 'Show Keyboard Shortcuts',
accelerator: 'CmdOrCtrl+/',
click: showKeyboardShortcuts,
},
{ type: 'separator' },
{ label: 'Contact Us', click: openContactUs },
{ label: 'Go to Release Notes', click: openReleaseNotes },
{ label: 'Go to Forums', click: openForums },
{ label: 'Go to Support Page', click: openSupportPage },
{ label: 'Join the Beta', click: openJoinTheBeta },
...(includeAbout
? ([
{ type: 'separator' },
{ label: 'About Signal Desktop', click: showAbout },
] as MenuListType)
: []),
],
});
const EXPECTED_MACOS: MenuListType = [
{
label: 'Signal Desktop',
submenu: [
{ label: 'About Signal Desktop', click: showAbout },
{ type: 'separator' },
{
label: 'Preferences…',
accelerator: 'CommandOrControl+,',
click: showSettings,
},
{ type: 'separator' },
{ label: 'Services', role: 'services' },
{ type: 'separator' },
{ label: 'Hide', role: 'hide' },
{ label: 'Hide Others', role: 'hideOthers' },
{ label: 'Show All', role: 'unhide' },
{ type: 'separator' },
{ label: 'Quit Signal', role: 'quit' },
],
},
{
label: '&File',
submenu: [
{ label: 'Create/upload sticker pack', click: showStickerCreator },
{ type: 'separator' },
{ accelerator: 'CmdOrCtrl+W', label: 'Close Window', role: 'close' },
],
},
getExpectedEditMenu(true),
getExpectedViewMenu('Command'),
{
label: '&Window',
role: 'window',
submenu: [
{ label: 'Minimize', accelerator: 'CmdOrCtrl+M', role: 'minimize' },
{ label: 'Zoom', role: 'zoom' },
{ label: 'Show', accelerator: 'CmdOrCtrl+Shift+0', click: showWindow },
{ type: 'separator' },
{ label: 'Bring All to Front', role: 'front' },
],
},
getExpectedHelpMenu(false),
];
const EXPECTED_WINDOWS: MenuListType = [
{
label: '&File',
submenu: [
{ label: 'Create/upload sticker pack', click: showStickerCreator },
{
label: 'Preferences…',
accelerator: 'CommandOrControl+,',
click: showSettings,
},
{ type: 'separator' },
{ label: 'Quit Signal', role: 'quit' },
],
},
getExpectedEditMenu(false),
getExpectedViewMenu('Control'),
{
label: '&Window',
role: 'window',
submenu: [{ label: 'Minimize', role: 'minimize' }],
},
getExpectedHelpMenu(true),
];
const EXPECTED_LINUX: MenuListType = EXPECTED_WINDOWS.map(menuItem => {
if (menuItem.label === '&View' && Array.isArray(menuItem.submenu)) {
return {
...menuItem,
submenu: menuItem.submenu.filter(
submenuItem => submenuItem.label !== 'Force Update'
),
};
}
return menuItem;
});
const PLATFORMS = [
{
label: 'macOS',
platform: 'darwin',
expectedDefault: EXPECTED_MACOS,
},
{
label: 'Windows',
platform: 'win32',
expectedDefault: EXPECTED_WINDOWS,
},
{
label: 'Linux',
platform: 'linux',
expectedDefault: EXPECTED_LINUX,
},
];
describe('createTemplate', () => {
const { messages } = loadLocale({
appLocale: 'en',
logger: {
error(arg: unknown) {
throw new Error(String(arg));
},
},
});
const actions = {
forceUpdate,
openContactUs,
openForums,
openJoinTheBeta,
openReleaseNotes,
openSupportPage,
setupAsNewDevice,
setupAsStandalone,
showAbout,
showDebugLog,
showKeyboardShortcuts,
showSettings,
showStickerCreator,
showWindow,
};
PLATFORMS.forEach(({ label, platform, expectedDefault }) => {
describe(label, () => {
it('should return the correct template without setup options', () => {
const options: MenuOptionsType = {
development: false,
devTools: true,
includeSetup: false,
isProduction: true,
platform,
...actions,
};
const actual = createTemplate(options, messages);
assert.deepEqual(actual, expectedDefault);
});
it('should return correct template with setup options', () => {
const options: MenuOptionsType = {
development: false,
devTools: true,
includeSetup: true,
isProduction: true,
platform,
...actions,
};
const expected: MenuListType = expectedDefault.map(menuItem => {
if (menuItem.label === '&File' && Array.isArray(menuItem.submenu)) {
return {
...menuItem,
submenu: [
{ label: 'Set Up as New Device', click: setupAsNewDevice },
{ type: 'separator' },
...menuItem.submenu,
],
};
}
return menuItem;
});
const actual = createTemplate(options, messages);
assert.deepEqual(actual, expected);
});
});
});
});