Support rendering notification badges on platforms that do their own icon overlays (#30315)
* Support rendering a seperate overlay icon on supported platforms. * Add required globals. * i18n-ize * Add tests * lint * lint * lint * update copyrights * Fix test * lint * Fixup * lint * remove unused string * fix test
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2024-2025 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
|
||||
import { UpdateCheckStatus } from "../../../../src/BasePlatform";
|
||||
import { Action } from "../../../../src/dispatcher/actions";
|
||||
@@ -26,18 +27,20 @@ jest.mock("../../../../src/rageshake/rageshake", () => ({
|
||||
}));
|
||||
|
||||
describe("ElectronPlatform", () => {
|
||||
const initialiseValues = jest.fn().mockReturnValue({
|
||||
protocol: "io.element.desktop",
|
||||
sessionId: "session-id",
|
||||
config: { _config: true },
|
||||
supportedSettings: { setting1: false, setting2: true },
|
||||
supportsBadgeOverlay: false,
|
||||
});
|
||||
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(),
|
||||
initialise: jest.fn().mockResolvedValue({
|
||||
protocol: "io.element.desktop",
|
||||
sessionId: "session-id",
|
||||
config: { _config: true },
|
||||
supportedSettings: { setting1: false, setting2: true },
|
||||
}),
|
||||
initialise: initialiseValues,
|
||||
setSettingValue: jest.fn().mockResolvedValue(undefined),
|
||||
getSettingValue: jest.fn().mockResolvedValue(undefined),
|
||||
} as unknown as MockedObject<Electron>;
|
||||
@@ -405,4 +408,101 @@ describe("ElectronPlatform", () => {
|
||||
state: "connected",
|
||||
});
|
||||
});
|
||||
|
||||
describe("Notification overlay badges", () => {
|
||||
beforeEach(() => {
|
||||
initialiseValues.mockReturnValue({
|
||||
protocol: "io.element.desktop",
|
||||
sessionId: "session-id",
|
||||
config: { _config: true },
|
||||
supportsBadgeOverlay: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should send a badge with a notification count", async () => {
|
||||
const platform = new ElectronPlatform();
|
||||
await platform.initialised;
|
||||
platform.setNotificationCount(1);
|
||||
// Badges are sent asynchronously
|
||||
await waitFor(() => {
|
||||
const ipcMessage = mockElectron.send.mock.lastCall;
|
||||
expect(ipcMessage?.[1]).toEqual(1);
|
||||
expect(ipcMessage?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("should update badge and skip duplicates", async () => {
|
||||
const platform = new ElectronPlatform();
|
||||
await platform.initialised;
|
||||
platform.setNotificationCount(1);
|
||||
platform.setNotificationCount(1); // Test that duplicates do not fire.
|
||||
platform.setNotificationCount(2);
|
||||
// Badges are sent asynchronously
|
||||
await waitFor(() => {
|
||||
const [ipcMessageA, ipcMessageB] = mockElectron.send.mock.calls.filter(
|
||||
(call) => call[0] === "setBadgeCount",
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(1);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(2);
|
||||
expect(ipcMessageB?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
});
|
||||
});
|
||||
it("should remove badge when notification count zeros", async () => {
|
||||
const platform = new ElectronPlatform();
|
||||
await platform.initialised;
|
||||
platform.setNotificationCount(1);
|
||||
platform.setNotificationCount(0); // Test that duplicates do not fire.
|
||||
// Badges are sent asynchronously
|
||||
await waitFor(() => {
|
||||
const [ipcMessageB, ipcMessageA] = mockElectron.send.mock.calls.filter(
|
||||
(call) => call[0] === "setBadgeCount",
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(1);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(0);
|
||||
expect(ipcMessageB?.[2]).toBeNull();
|
||||
});
|
||||
});
|
||||
it("should show an error badge when the application errors", async () => {
|
||||
const platform = new ElectronPlatform();
|
||||
await platform.initialised;
|
||||
platform.setErrorStatus(true);
|
||||
// Badges are sent asynchronously
|
||||
await waitFor(() => {
|
||||
const ipcMessage = mockElectron.send.mock.calls.find((call) => call[0] === "setBadgeCount");
|
||||
|
||||
expect(ipcMessage?.[1]).toEqual(0);
|
||||
expect(ipcMessage?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessage?.[3]).toEqual(true);
|
||||
});
|
||||
});
|
||||
it("should restore after error is resolved", async () => {
|
||||
const platform = new ElectronPlatform();
|
||||
await platform.initialised;
|
||||
platform.setErrorStatus(true);
|
||||
platform.setErrorStatus(false);
|
||||
// Badges are sent asynchronously
|
||||
await waitFor(() => {
|
||||
const [ipcMessageB, ipcMessageA] = mockElectron.send.mock.calls.filter(
|
||||
(call) => call[0] === "setBadgeCount",
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(0);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessageA?.[3]).toEqual(true);
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(0);
|
||||
expect(ipcMessageB?.[2]).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user