Device manager - test coverage for Notifier (#9392)

* use correct default for notification silencing

* test notifications with no local notifications setting event

* test notifier from cli event to trigger

* lint
This commit is contained in:
Kerry 2022-10-13 09:07:48 +02:00 committed by GitHub
parent 776ffa4764
commit 1e9872662a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 12 deletions

View file

@ -431,6 +431,7 @@ export const Notifier = {
const room = MatrixClientPeg.get().getRoom(roomId); const room = MatrixClientPeg.get().getRoom(roomId);
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev); const actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
if (actions?.notify) { if (actions?.notify) {
this._performCustomEventHandling(ev); this._performCustomEventHandling(ev);

View file

@ -29,7 +29,7 @@ import {
createLocalNotificationSettingsIfNeeded, createLocalNotificationSettingsIfNeeded,
getLocalNotificationAccountDataEventType, getLocalNotificationAccountDataEventType,
} from "../src/utils/notifications"; } from "../src/utils/notifications";
import { getMockClientWithEventEmitter, mkEvent, mkRoom, mockPlatformPeg } from "./test-utils"; import { getMockClientWithEventEmitter, mkEvent, mkRoom, mockClientMethodsUser, mockPlatformPeg } from "./test-utils";
import { IncomingCallToast } from "../src/toasts/IncomingCallToast"; import { IncomingCallToast } from "../src/toasts/IncomingCallToast";
jest.mock("../src/utils/notifications", () => ({ jest.mock("../src/utils/notifications", () => ({
@ -54,22 +54,28 @@ describe("Notifier", () => {
let accountDataEventKey: string; let accountDataEventKey: string;
let accountDataStore = {}; let accountDataStore = {};
const userId = "@bob:example.org";
beforeEach(() => { beforeEach(() => {
accountDataStore = {}; accountDataStore = {};
mockClient = getMockClientWithEventEmitter({ mockClient = getMockClientWithEventEmitter({
getUserId: jest.fn().mockReturnValue("@bob:example.org"), ...mockClientMethodsUser(userId),
isGuest: jest.fn().mockReturnValue(false), isGuest: jest.fn().mockReturnValue(false),
getAccountData: jest.fn().mockImplementation(eventType => accountDataStore[eventType]), getAccountData: jest.fn().mockImplementation(eventType => accountDataStore[eventType]),
setAccountData: jest.fn().mockImplementation((eventType, content) => { setAccountData: jest.fn().mockImplementation((eventType, content) => {
accountDataStore[eventType] = new MatrixEvent({ accountDataStore[eventType] = content ? new MatrixEvent({
type: eventType, type: eventType,
content, content,
}); }) : undefined;
}), }),
decryptEventIfNeeded: jest.fn(), decryptEventIfNeeded: jest.fn(),
getRoom: jest.fn(), getRoom: jest.fn(),
getPushActionsForEvent: jest.fn(), getPushActionsForEvent: jest.fn(),
}); });
mockClient.pushRules = {
global: undefined,
};
accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId); accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId);
testRoom = mkRoom(mockClient, roomId); testRoom = mkRoom(mockClient, roomId);
@ -78,6 +84,7 @@ describe("Notifier", () => {
supportsNotifications: jest.fn().mockReturnValue(true), supportsNotifications: jest.fn().mockReturnValue(true),
maySendNotifications: jest.fn().mockReturnValue(true), maySendNotifications: jest.fn().mockReturnValue(true),
displayNotification: jest.fn(), displayNotification: jest.fn(),
loudNotification: jest.fn(),
}); });
Notifier.isBodyEnabled = jest.fn().mockReturnValue(true); Notifier.isBodyEnabled = jest.fn().mockReturnValue(true);
@ -85,12 +92,128 @@ describe("Notifier", () => {
mockClient.getRoom.mockReturnValue(testRoom); mockClient.getRoom.mockReturnValue(testRoom);
}); });
describe('triggering notification from events', () => {
let hasStartedNotiferBefore = false;
const event = new MatrixEvent({
sender: '@alice:server.org',
type: 'm.room.message',
room_id: '!room:server.org',
content: {
body: 'hey',
},
});
beforeEach(() => {
// notifier defines some listener functions in start
// and references them in stop
// so blows up if stopped before it was started
if (hasStartedNotiferBefore) {
Notifier.stop();
}
Notifier.start();
hasStartedNotiferBefore = true;
mockClient.getRoom.mockReturnValue(testRoom);
mockClient.getPushActionsForEvent.mockReturnValue({
notify: true,
tweaks: {
sound: true,
},
});
const enabledSettings = [
'notificationsEnabled',
'audioNotificationsEnabled',
];
// enable notifications by default
jest.spyOn(SettingsStore, "getValue").mockImplementation(
settingName => enabledSettings.includes(settingName),
);
});
afterAll(() => {
Notifier.stop();
});
it('does not create notifications before syncing has started', () => {
mockClient!.emit(ClientEvent.Event, event);
expect(MockPlatform.displayNotification).not.toHaveBeenCalled();
expect(MockPlatform.loudNotification).not.toHaveBeenCalled();
});
it('does not create notifications for own event', () => {
const ownEvent = new MatrixEvent({ sender: userId });
mockClient!.emit(ClientEvent.Sync, SyncState.Syncing);
mockClient!.emit(ClientEvent.Event, ownEvent);
expect(MockPlatform.displayNotification).not.toHaveBeenCalled();
expect(MockPlatform.loudNotification).not.toHaveBeenCalled();
});
it('does not create notifications when event does not have notify push action', () => {
mockClient.getPushActionsForEvent.mockReturnValue({
notify: false,
tweaks: {
sound: true,
},
});
mockClient!.emit(ClientEvent.Sync, SyncState.Syncing);
mockClient!.emit(ClientEvent.Event, event);
expect(MockPlatform.displayNotification).not.toHaveBeenCalled();
expect(MockPlatform.loudNotification).not.toHaveBeenCalled();
});
it('creates desktop notification when enabled', () => {
mockClient!.emit(ClientEvent.Sync, SyncState.Syncing);
mockClient!.emit(ClientEvent.Event, event);
expect(MockPlatform.displayNotification).toHaveBeenCalledWith(
testRoom.name,
'hey',
null,
testRoom,
event,
);
});
it('creates a loud notification when enabled', () => {
mockClient!.emit(ClientEvent.Sync, SyncState.Syncing);
mockClient!.emit(ClientEvent.Event, event);
expect(MockPlatform.loudNotification).toHaveBeenCalledWith(
event, testRoom,
);
});
it('does not create loud notification when event does not have sound tweak in push actions', () => {
mockClient.getPushActionsForEvent.mockReturnValue({
notify: true,
tweaks: {
sound: false,
},
});
mockClient!.emit(ClientEvent.Sync, SyncState.Syncing);
mockClient!.emit(ClientEvent.Event, event);
// desktop notification created
expect(MockPlatform.displayNotification).toHaveBeenCalled();
// without noisy
expect(MockPlatform.loudNotification).not.toHaveBeenCalled();
});
});
describe("_displayPopupNotification", () => { describe("_displayPopupNotification", () => {
it.each([ it.each([
{ silenced: true, count: 0 }, { event: { is_silenced: true }, count: 0 },
{ silenced: false, count: 1 }, { event: { is_silenced: false }, count: 1 },
])("does not dispatch when notifications are silenced", ({ silenced, count }) => { { event: undefined, count: 1 },
mockClient.setAccountData(accountDataEventKey, { is_silenced: silenced }); ])("does not dispatch when notifications are silenced", ({ event, count }) => {
mockClient.setAccountData(accountDataEventKey, event);
Notifier._displayPopupNotification(testEvent, testRoom); Notifier._displayPopupNotification(testEvent, testRoom);
expect(MockPlatform.displayNotification).toHaveBeenCalledTimes(count); expect(MockPlatform.displayNotification).toHaveBeenCalledTimes(count);
}); });
@ -98,14 +221,15 @@ describe("Notifier", () => {
describe("_playAudioNotification", () => { describe("_playAudioNotification", () => {
it.each([ it.each([
{ silenced: true, count: 0 }, { event: { is_silenced: true }, count: 0 },
{ silenced: false, count: 1 }, { event: { is_silenced: false }, count: 1 },
])("does not dispatch when notifications are silenced", ({ silenced, count }) => { { event: undefined, count: 1 },
])("does not dispatch when notifications are silenced", ({ event, count }) => {
// It's not ideal to only look at whether this function has been called // It's not ideal to only look at whether this function has been called
// but avoids starting to look into DOM stuff // but avoids starting to look into DOM stuff
Notifier.getSoundForRoom = jest.fn(); Notifier.getSoundForRoom = jest.fn();
mockClient.setAccountData(accountDataEventKey, { is_silenced: silenced }); mockClient.setAccountData(accountDataEventKey, event);
Notifier._playAudioNotification(testEvent, testRoom); Notifier._playAudioNotification(testEvent, testRoom);
expect(Notifier.getSoundForRoom).toHaveBeenCalledTimes(count); expect(Notifier.getSoundForRoom).toHaveBeenCalledTimes(count);
}); });