[MM-55720] Add menu item to open developer tools for Call Widget window (#2936)

* Add menu item to open developer tools for Call Widget window

* Add dedicated Developer Tools submenu
This commit is contained in:
Claudio Costa 2024-01-09 17:31:06 -06:00 committed by GitHub
parent b4a8a447a2
commit 3308730f13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 151 additions and 24 deletions

View file

@ -82,7 +82,9 @@
"main.menus.app.view.actualSize": "Actual Size",
"main.menus.app.view.clearCacheAndReload": "Clear Cache and Reload",
"main.menus.app.view.devToolsAppWrapper": "Developer Tools for Application Wrapper",
"main.menus.app.view.devToolsCurrentCallWidget": "Developer Tools for Call Widget",
"main.menus.app.view.devToolsCurrentServer": "Developer Tools for Current Server",
"main.menus.app.view.devToolsSubMenu": "Developer Tools",
"main.menus.app.view.downloads": "Downloads",
"main.menus.app.view.find": "Find..",
"main.menus.app.view.fullscreen": "Toggle Full Screen",

View file

@ -10,8 +10,27 @@ import ServerManager from 'common/servers/serverManager';
import ServerViewState from 'app/serverViewState';
import CallsWidgetWindow from 'main/windows/callsWidgetWindow';
import {createTemplate} from './app';
jest.mock('fs-extra', () => ({
readFileSync: jest.fn(),
writeFileSync: jest.fn(),
existsSync: jest.fn(),
copySync: jest.fn(),
}));
jest.mock('electron-extension-installer', () => {
return () => ({
REACT_DEVELOPER_TOOLS: 'react-developer-tools',
});
});
jest.mock('electron-context-menu', () => {
return () => jest.fn();
});
jest.mock('electron', () => {
class NotificationMock {
static isSupported = jest.fn();
@ -38,6 +57,9 @@ jest.mock('electron', () => {
removeListener: jest.fn(),
},
Notification: NotificationMock,
nativeImage: {
createFromPath: jest.fn(),
},
};
});
jest.mock('fs', () => ({
@ -67,11 +89,19 @@ jest.mock('main/downloadsManager', () => ({
jest.mock('main/views/viewManager', () => ({}));
jest.mock('main/windows/mainWindow', () => ({
sendToRenderer: jest.fn(),
on: jest.fn(),
}));
jest.mock('main/windows/settingsWindow', () => ({}));
jest.mock('common/views/View', () => ({
getViewDisplayName: (name) => name,
}));
jest.mock('main/AutoLauncher', () => ({
enable: jest.fn(),
disable: jest.fn(),
}));
jest.mock('main/windows/callsWidgetWindow', () => ({
isOpen: jest.fn(),
}));
describe('main/menus/app', () => {
const config = {
@ -305,4 +335,45 @@ describe('main/menus/app', () => {
const helpSubmenu = menu.find((subMenu) => subMenu.id === 'help')?.submenu;
expect(helpSubmenu).toContainObject({id: 'diagnostics'});
});
it('should show developer tools submenu', () => {
const menu = createTemplate(config);
const appMenu = menu.find((item) => item.label === 'main.menus.app.view');
expect(appMenu).not.toBe(undefined);
const devToolsSubMenu = appMenu.submenu.find((item) => item.label === 'main.menus.app.view.devToolsSubMenu');
expect(devToolsSubMenu.submenu.length).toBe(2);
expect(devToolsSubMenu.submenu[0].label).toBe('main.menus.app.view.devToolsAppWrapper');
expect(devToolsSubMenu.submenu[1].label).toBe('main.menus.app.view.devToolsCurrentServer');
});
it('should not show menu item if widget window is not open', () => {
const menu = createTemplate(config);
const appMenu = menu.find((item) => item.label === 'main.menus.app.view');
expect(appMenu).not.toBe(undefined);
const devToolsSubMenu = appMenu.submenu.find((item) => item.label === 'main.menus.app.view.devToolsSubMenu');
expect(devToolsSubMenu).not.toBe(undefined);
const menuItem = devToolsSubMenu.submenu.find((item) => item.label === 'main.menus.app.view.devToolsCurrentCallWidget');
expect(menuItem).toBe(undefined);
});
it('should show menu item if widget window is open', () => {
CallsWidgetWindow.isOpen = jest.fn(() => true);
const menu = createTemplate(config);
const appMenu = menu.find((item) => item.label === 'main.menus.app.view');
expect(appMenu).not.toBe(undefined);
const devToolsSubMenu = appMenu.submenu.find((item) => item.label === 'main.menus.app.view.devToolsSubMenu');
expect(devToolsSubMenu).not.toBe(undefined);
const menuItem = devToolsSubMenu.submenu.find((item) => item.label === 'main.menus.app.view.devToolsCurrentCallWidget');
expect(menuItem).not.toBe(undefined);
});
});

View file

@ -20,6 +20,7 @@ import downloadsManager from 'main/downloadsManager';
import Diagnostics from 'main/diagnostics';
import ViewManager from 'main/views/viewManager';
import SettingsWindow from 'main/windows/settingsWindow';
import CallsWidgetWindow from 'main/windows/callsWidgetWindow';
export function createTemplate(config: Config, updateManager: UpdateManager) {
const separatorItem: MenuItemConstructorOptions = {
@ -125,6 +126,43 @@ export function createTemplate(config: Config, updateManager: UpdateManager) {
}],
});
const devToolsSubMenu = [
{
label: localizeMessage('main.menus.app.view.devToolsAppWrapper', 'Developer Tools for Application Wrapper'),
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Alt+Command+I';
}
return 'Ctrl+Shift+I';
})(),
click(item: Electron.MenuItem, focusedWindow?: WebContents) {
if (focusedWindow) {
// toggledevtools opens it in the last known position, so sometimes it goes below the browserview
if (focusedWindow.isDevToolsOpened()) {
focusedWindow.closeDevTools();
} else {
focusedWindow.openDevTools({mode: 'detach'});
}
}
},
},
{
label: localizeMessage('main.menus.app.view.devToolsCurrentServer', 'Developer Tools for Current Server'),
click() {
ViewManager.getCurrentView()?.openDevTools();
},
},
];
if (CallsWidgetWindow.isOpen()) {
devToolsSubMenu.push({
label: localizeMessage('main.menus.app.view.devToolsCurrentCallWidget', 'Developer Tools for Call Widget'),
click() {
CallsWidgetWindow.openDevTools();
},
});
}
const viewSubMenu = [{
label: localizeMessage('main.menus.app.view.find', 'Find..'),
accelerator: 'CmdOrCtrl+F',
@ -176,28 +214,8 @@ export function createTemplate(config: Config, updateManager: UpdateManager) {
return downloadsManager.openDownloadsDropdown();
},
}, separatorItem, {
label: localizeMessage('main.menus.app.view.devToolsAppWrapper', 'Developer Tools for Application Wrapper'),
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Alt+Command+I';
}
return 'Ctrl+Shift+I';
})(),
click(item: Electron.MenuItem, focusedWindow?: WebContents) {
if (focusedWindow) {
// toggledevtools opens it in the last known position, so sometimes it goes below the browserview
if (focusedWindow.isDevToolsOpened()) {
focusedWindow.closeDevTools();
} else {
focusedWindow.openDevTools({mode: 'detach'});
}
}
},
}, {
label: localizeMessage('main.menus.app.view.devToolsCurrentServer', 'Developer Tools for Current Server'),
click() {
ViewManager.getCurrentView()?.openDevTools();
},
label: localizeMessage('main.menus.app.view.devToolsSubMenu', 'Developer Tools'),
submenu: devToolsSubMenu,
}];
if (process.platform !== 'darwin' && process.platform !== 'win32') {

View file

@ -7,7 +7,7 @@ import {BrowserWindow, desktopCapturer, systemPreferences, ipcMain} from 'electr
import ServerViewState from 'app/serverViewState';
import {CALLS_WIDGET_SHARE_SCREEN} from 'common/communication';
import {CALLS_WIDGET_SHARE_SCREEN, UPDATE_SHORTCUT_MENU} from 'common/communication';
import {
MINIMUM_CALLS_WIDGET_WIDTH,
MINIMUM_CALLS_WIDGET_HEIGHT,
@ -34,6 +34,7 @@ jest.mock('electron', () => ({
on: jest.fn(),
off: jest.fn(),
handle: jest.fn(),
emit: jest.fn(),
},
desktopCapturer: {
getSources: jest.fn(),
@ -114,6 +115,7 @@ describe('main/windows/callsWidgetWindow', () => {
width: MINIMUM_CALLS_WIDGET_WIDTH,
height: MINIMUM_CALLS_WIDGET_HEIGHT,
});
expect(ipcMain.emit).toHaveBeenCalledWith(UPDATE_SHORTCUT_MENU);
});
it('should open dev tools when environment variable is set', async () => {
@ -796,4 +798,26 @@ describe('main/windows/callsWidgetWindow', () => {
expect(view.sendToRenderer).toBeCalledWith('some-channel', 'thecallchannelid');
});
});
describe('isOpen', () => {
const callsWidgetWindow = new CallsWidgetWindow();
it('undefined', () => {
expect(callsWidgetWindow.isOpen()).toBe(false);
});
it('open', () => {
callsWidgetWindow.win = {
isDestroyed: jest.fn(() => false),
};
expect(callsWidgetWindow.isOpen()).toBe(true);
});
it('destroyed', () => {
callsWidgetWindow.win = {
isDestroyed: jest.fn(() => true),
};
expect(callsWidgetWindow.isOpen()).toBe(false);
});
});
});

View file

@ -28,6 +28,7 @@ import {
CALLS_WIDGET_SHARE_SCREEN,
DESKTOP_SOURCES_MODAL_REQUEST,
GET_DESKTOP_SOURCES,
UPDATE_SHORTCUT_MENU,
} from 'common/communication';
import {MattermostBrowserView} from 'main/views/MattermostBrowserView';
@ -87,10 +88,18 @@ export class CallsWidgetWindow {
return this.mainView?.view.server.id;
}
public isOpen() {
return Boolean(this.win && !this.win.isDestroyed());
}
/**
* Helper functions
*/
public openDevTools = () => {
this.win?.webContents.openDevTools({mode: 'detach'});
}
getViewURL = () => {
return this.mainView?.view.server.url;
}
@ -203,6 +212,7 @@ export class CallsWidgetWindow {
*/
private onClosed = () => {
ipcMain.emit(UPDATE_SHORTCUT_MENU);
delete this.win;
delete this.mainView;
delete this.options;
@ -238,9 +248,11 @@ export class CallsWidgetWindow {
this.win.setMenuBarVisibility(false);
if (process.env.MM_DEBUG_CALLS_WIDGET) {
this.win.webContents.openDevTools({mode: 'detach'});
this.openDevTools();
}
ipcMain.emit(UPDATE_SHORTCUT_MENU);
this.setBounds(initialBounds);
}