Device manager - tweak string formatting of default device name (#23457)

* tweak string formatting of default device name

* cheaters path to beating quality gate

* more electronplatform test coverage

* remove test that throw errors

* cover some more window.electrons

* more coverage

* empty line
This commit is contained in:
Kerry 2022-10-12 15:35:52 +02:00 committed by GitHub
parent 44eeb6fddc
commit 0e8e472138
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 297 additions and 21 deletions

View file

@ -10,10 +10,10 @@
"Download Completed": "Download Completed", "Download Completed": "Download Completed",
"Open": "Open", "Open": "Open",
"Dismiss": "Dismiss", "Dismiss": "Dismiss",
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)", "%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s",
"Go to your browser to complete Sign In": "Go to your browser to complete Sign In", "Go to your browser to complete Sign In": "Go to your browser to complete Sign In",
"Unknown device": "Unknown device", "Unknown device": "Unknown device",
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)", "%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s on %(osName)s",
"Powered by Matrix": "Powered by Matrix", "Powered by Matrix": "Powered by Matrix",
"Use %(brand)s on mobile": "Use %(brand)s on mobile", "Use %(brand)s on mobile": "Use %(brand)s on mobile",
"Unsupported browser": "Unsupported browser", "Unsupported browser": "Unsupported browser",

View file

@ -45,7 +45,6 @@ import VectorBasePlatform from './VectorBasePlatform';
import { SeshatIndexManager } from "./SeshatIndexManager"; import { SeshatIndexManager } from "./SeshatIndexManager";
import { IPCManager } from "./IPCManager"; import { IPCManager } from "./IPCManager";
const electron = window.electron;
const isMac = navigator.platform.toUpperCase().includes('MAC'); const isMac = navigator.platform.toUpperCase().includes('MAC');
function platformFriendlyName(): string { function platformFriendlyName(): string {
@ -70,7 +69,7 @@ function platformFriendlyName(): string {
function onAction(payload: ActionPayload): void { function onAction(payload: ActionPayload): void {
// Whitelist payload actions, no point sending most across // Whitelist payload actions, no point sending most across
if (['call_state'].includes(payload.action)) { if (['call_state'].includes(payload.action)) {
electron.send('app_onAction', payload); window.electron.send('app_onAction', payload);
} }
} }
@ -103,7 +102,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
false if there is not false if there is not
or the error if one is encountered or the error if one is encountered
*/ */
electron.on('check_updates', (event, status) => { window.electron.on('check_updates', (event, status) => {
dis.dispatch<CheckUpdatesPayload>({ dis.dispatch<CheckUpdatesPayload>({
action: Action.CheckUpdates, action: Action.CheckUpdates,
...getUpdateCheckStatus(status), ...getUpdateCheckStatus(status),
@ -111,27 +110,27 @@ export default class ElectronPlatform extends VectorBasePlatform {
}); });
// try to flush the rageshake logs to indexeddb before quit. // try to flush the rageshake logs to indexeddb before quit.
electron.on('before-quit', function() { window.electron.on('before-quit', function() {
logger.log('element-desktop closing'); logger.log('element-desktop closing');
rageshake.flush(); rageshake.flush();
}); });
electron.on('update-downloaded', this.onUpdateDownloaded); window.electron.on('update-downloaded', this.onUpdateDownloaded);
electron.on('preferences', () => { window.electron.on('preferences', () => {
dis.fire(Action.ViewUserSettings); dis.fire(Action.ViewUserSettings);
}); });
electron.on('userDownloadCompleted', (ev, { id, name }) => { window.electron.on('userDownloadCompleted', (ev, { id, name }) => {
const key = `DOWNLOAD_TOAST_${id}`; const key = `DOWNLOAD_TOAST_${id}`;
const onAccept = () => { const onAccept = () => {
electron.send('userDownloadAction', { id, open: true }); window.electron.send('userDownloadAction', { id, open: true });
ToastStore.sharedInstance().dismissToast(key); ToastStore.sharedInstance().dismissToast(key);
}; };
const onDismiss = () => { const onDismiss = () => {
electron.send('userDownloadAction', { id }); window.electron.send('userDownloadAction', { id });
}; };
ToastStore.sharedInstance().addOrReplaceToast({ ToastStore.sharedInstance().addOrReplaceToast({
@ -187,7 +186,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
if (this.notificationCount === count) return; if (this.notificationCount === count) return;
super.setNotificationCount(count); super.setNotificationCount(count);
electron.send('setBadgeCount', count); window.electron.send('setBadgeCount', count);
} }
public supportsNotifications(): boolean { public supportsNotifications(): boolean {
@ -233,7 +232,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
} }
public loudNotification(ev: MatrixEvent, room: Room) { public loudNotification(ev: MatrixEvent, room: Room) {
electron.send('loudNotification'); window.electron.send('loudNotification');
} }
public needsUrlTooltips(): boolean { public needsUrlTooltips(): boolean {
@ -269,19 +268,19 @@ export default class ElectronPlatform extends VectorBasePlatform {
public startUpdateCheck() { public startUpdateCheck() {
super.startUpdateCheck(); super.startUpdateCheck();
electron.send('check_updates'); window.electron.send('check_updates');
} }
public installUpdate() { public installUpdate() {
// IPC to the main process to install the update, since quitAndInstall // IPC to the main process to install the update, since quitAndInstall
// doesn't fire the before-quit event so the main process needs to know // doesn't fire the before-quit event so the main process needs to know
// it should exit. // it should exit.
electron.send('install_update'); window.electron.send('install_update');
} }
public getDefaultDeviceDisplayName(): string { public getDefaultDeviceDisplayName(): string {
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
return _t('%(brand)s Desktop (%(platformName)s)', { return _t('%(brand)s Desktop: %(platformName)s', {
brand, brand,
platformName: platformFriendlyName(), platformName: platformFriendlyName(),
}); });

View file

@ -19,8 +19,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { ElectronChannel } from "../../@types/global"; import { ElectronChannel } from "../../@types/global";
const electron = window.electron;
interface IPCPayload { interface IPCPayload {
id?: number; id?: number;
error?: string; error?: string;
@ -35,7 +33,7 @@ export class IPCManager {
private readonly sendChannel: ElectronChannel = "ipcCall", private readonly sendChannel: ElectronChannel = "ipcCall",
private readonly recvChannel: ElectronChannel = "ipcReply", private readonly recvChannel: ElectronChannel = "ipcReply",
) { ) {
electron.on(this.recvChannel, this.onIpcReply); window.electron.on(this.recvChannel, this.onIpcReply);
} }
public async call(name: string, ...args: any[]): Promise<any> { public async call(name: string, ...args: any[]): Promise<any> {

View file

@ -210,7 +210,7 @@ export default class WebPlatform extends VectorBasePlatform {
let osName = ua.getOS().name || "unknown OS"; let osName = ua.getOS().name || "unknown OS";
// Stylise the value from the parser to match Apple's current branding. // Stylise the value from the parser to match Apple's current branding.
if (osName === "Mac OS") osName = "macOS"; if (osName === "Mac OS") osName = "macOS";
return _t('%(appName)s (%(browserName)s, %(osName)s)', { return _t('%(appName)s: %(browserName)s on %(osName)s', {
appName, appName,
browserName, browserName,
osName, osName,

View file

@ -0,0 +1,279 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import request from 'browser-request';
import EventEmitter from 'events';
import { logger } from 'matrix-js-sdk/src/logger';
import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk/src/matrix';
import { UpdateCheckStatus } from 'matrix-react-sdk/src/BasePlatform';
import { Action } from 'matrix-react-sdk/src/dispatcher/actions';
import dispatcher from 'matrix-react-sdk/src/dispatcher/dispatcher';
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake';
import ElectronPlatform from '../../../../src/vector/platform/ElectronPlatform';
jest.mock('matrix-react-sdk/src/rageshake/rageshake', () => ({
flush: jest.fn()
}))
describe('ElectronPlatform', () => {
const defaultUserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36';
const mockElectron = {
on: jest.fn(),
send: jest.fn()
};
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');
const dispatchFireSpy = jest.spyOn(dispatcher, 'fire');
const logSpy = jest.spyOn(logger, 'log').mockImplementation(() => {});
const userId = '@alice:server.org';
const deviceId = 'device-id';
window.electron = mockElectron;
beforeEach(() => {
window.electron = mockElectron;
jest.clearAllMocks();
delete window.navigator;
window.navigator = { userAgent: defaultUserAgent } as unknown as Navigator;
});
const getElectronEventHandlerCall = (eventType: string): [type: string, handler: Function] | undefined =>
mockElectron.on.mock.calls.find(([type]) => type === eventType);
it('flushes rageshake before quitting', () => {
new ElectronPlatform();
const [event, handler] = getElectronEventHandlerCall('before-quit');
// correct event bound
expect(event).toBeTruthy();
handler();
expect(logSpy).toHaveBeenCalled();
expect(rageshake.flush).toHaveBeenCalled();
});
it('dispatches view settings action on preferences event', () => {
new ElectronPlatform();
const [event, handler] = getElectronEventHandlerCall('preferences');
// correct event bound
expect(event).toBeTruthy();
handler();
expect(dispatchFireSpy).toHaveBeenCalledWith(Action.ViewUserSettings);
});
describe('updates', () => {
it('dispatches on check updates action', () => {
new ElectronPlatform();
const [event, handler] = getElectronEventHandlerCall('check_updates');
// correct event bound
expect(event).toBeTruthy();
handler({}, true);
expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.CheckUpdates,
status: UpdateCheckStatus.Downloading
})
});
it('dispatches on check updates action when update not available', () => {
new ElectronPlatform();
const [, handler] = getElectronEventHandlerCall('check_updates');
handler({}, false);
expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.CheckUpdates,
status: UpdateCheckStatus.NotAvailable
})
});
it('starts update check', () => {
const platform = new ElectronPlatform();
platform.startUpdateCheck();
expect(mockElectron.send).toHaveBeenCalledWith('check_updates')
});
it('installs update', () => {
const platform = new ElectronPlatform();
platform.installUpdate();
expect(mockElectron.send).toHaveBeenCalledWith('install_update')
});
});
it('returns human readable name', () => {
const platform = new ElectronPlatform();
expect(platform.getHumanReadableName()).toEqual('Electron Platform');
});
describe("getDefaultDeviceDisplayName", () => {
it.each([[
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"Element Desktop: macOS",
],
[
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) electron/1.0.0 Chrome/53.0.2785.113 Electron/1.4.3 Safari/537.36",
"Element Desktop: Windows",
],
[
"Mozilla/5.0 (X11; Linux i686; rv:21.0) Gecko/20100101 Firefox/21.0",
"Element Desktop: Linux",
],
[
"Mozilla/5.0 (X11; FreeBSD i686; rv:21.0) Gecko/20100101 Firefox/21.0",
"Element Desktop: FreeBSD",
],
[
"Mozilla/5.0 (X11; OpenBSD i686; rv:21.0) Gecko/20100101 Firefox/21.0",
"Element Desktop: OpenBSD",
],
[
"Mozilla/5.0 (X11; SunOS i686; rv:21.0) Gecko/20100101 Firefox/21.0",
"Element Desktop: SunOS",
],
[
"custom user agent",
"Element Desktop: Unknown",
],
])("%s = %s", (userAgent, result) => {
delete window.navigator;
window.navigator = { userAgent } as unknown as Navigator;
const platform = new ElectronPlatform();
expect(platform.getDefaultDeviceDisplayName()).toEqual(result);
});
});
it('returns true for needsUrlTooltips', () => {
const platform = new ElectronPlatform();
expect(platform.needsUrlTooltips()).toBe(true);
});
it('should override browser shortcuts', () => {
const platform = new ElectronPlatform();
expect(platform.overrideBrowserShortcuts()).toBe(true);
});
it('allows overriding native context menus', () => {
const platform = new ElectronPlatform();
expect(platform.allowOverridingNativeContextMenus()).toBe(true);
});
it('indicates support for desktop capturer', () => {
const platform = new ElectronPlatform();
expect(platform.supportsDesktopCapturer()).toBe(true);
});
it('indicates no support for jitsi screensharing', () => {
const platform = new ElectronPlatform();
expect(platform.supportsJitsiScreensharing()).toBe(false);
});
describe('notifications', () => {
it('indicates support for notifications', () => {
const platform = new ElectronPlatform();
expect(platform.supportsNotifications()).toBe(true);
});
it('may send notifications', () => {
const platform = new ElectronPlatform();
expect(platform.maySendNotifications()).toBe(true);
});
it('pretends to request notification permission', async () => {
const platform = new ElectronPlatform();
const result = await platform.requestNotificationPermission();
expect(result).toEqual('granted');
});
it('creates a loud notification', async () => {
const platform = new ElectronPlatform();
platform.loudNotification(new MatrixEvent(), new Room('!room:server', {} as any, userId));
expect(mockElectron.send).toHaveBeenCalledWith('loudNotification');
});
it('sets notification count when count is changing', async () => {
const platform = new ElectronPlatform();
platform.setNotificationCount(0);
// not called because matches internal notificaiton count
expect(mockElectron.send).not.toHaveBeenCalledWith('setBadgeCount', 0);
platform.setNotificationCount(1);
expect(mockElectron.send).toHaveBeenCalledWith('setBadgeCount', 1);
});
});
describe('spellcheck', () => {
it('indicates support for spellcheck settings', () => {
const platform = new ElectronPlatform();
expect(platform.supportsSpellCheckSettings()).toBe(true);
});
it('gets available spellcheck languages', () => {
const platform = new ElectronPlatform();
mockElectron.send.mockClear();
platform.getAvailableSpellCheckLanguages();
const [channel, { name }] = mockElectron.send.mock.calls[0];
expect(channel).toEqual("ipcCall");
expect(name).toEqual('getAvailableSpellCheckLanguages')
});
});
describe('pickle key', () => {
it('makes correct ipc call to get pickle key', () => {
const platform = new ElectronPlatform();
mockElectron.send.mockClear();
platform.getPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('getPickleKey')
expect(args).toEqual([userId, deviceId])
});
it('makes correct ipc call to create pickle key', () => {
const platform = new ElectronPlatform();
mockElectron.send.mockClear();
platform.createPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('createPickleKey')
expect(args).toEqual([userId, deviceId])
});
it('makes correct ipc call to destroy pickle key', () => {
const platform = new ElectronPlatform();
mockElectron.send.mockClear();
platform.destroyPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('destroyPickleKey')
expect(args).toEqual([userId, deviceId])
});
});
describe('versions', () => {
it('calls install update', () => {
const platform = new ElectronPlatform();
platform.installUpdate();
expect(mockElectron.send).toHaveBeenCalledWith('install_update');
});
});
});

View file

@ -65,7 +65,7 @@ describe('WebPlatform', () => {
it.each([[ it.each([[
"https://develop.element.io/#/room/!foo:bar", "https://develop.element.io/#/room/!foo:bar",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"develop.element.io (Chrome, macOS)", "develop.element.io: Chrome on macOS",
]])("%s & %s = %s", (url, userAgent, result) => { ]])("%s & %s = %s", (url, userAgent, result) => {
delete window.navigator; delete window.navigator;
window.navigator = { userAgent } as unknown as Navigator; window.navigator = { userAgent } as unknown as Navigator;