Files
element-web/test/unit-tests/components/viewmodels/composer/HistoryVisibleBannerViewModel-test.tsx
Skye Elliot ce9c66ba4c Update algorithm for history visible banner. (#31577)
* feat: Update algorithm for history visible banner.

- The banner now only shows for rooms with `shared` or `worldReadable`
  history visibility.
- The banner does not show in rooms in which the current user cannot
  send messages.

* tests: Add `getHistoryVisibility` to stub room.

* docs: Add description to `visible` condition check.

* docs: Fix spelling.

Co-authored-by: Florian Duros <florian.duros@ormaz.fr>

* chore: Remove `jest-sonar.xml`.

---------

Co-authored-by: Florian Duros <florian.duros@ormaz.fr>
2025-12-19 15:41:09 +00:00

200 lines
6.8 KiB
TypeScript

/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import { Room } from "matrix-js-sdk/src/matrix";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
import SettingsStore, { type CallbackFn } from "../../../../../src/settings/SettingsStore";
import { mkEvent, stubClient, upsertRoomStateEvents } from "../../../../test-utils";
import { HistoryVisibleBannerViewModel } from "../../../../../src/viewmodels/composer/HistoryVisibleBannerViewModel";
describe("HistoryVisibleBannerViewModel", () => {
const ROOM_ID = "!roomId:example.org";
let room: Room;
let watcherCallbacks: CallbackFn[];
let acknowledgedHistoryVisibility: boolean;
beforeEach(() => {
watcherCallbacks = [];
acknowledgedHistoryVisibility = false;
jest.spyOn(SettingsStore, "setValue").mockImplementation(async (settingName, roomId, level, value) => {
if (settingName === "acknowledgedHistoryVisibility") {
acknowledgedHistoryVisibility = value;
}
watcherCallbacks.forEach((callbackFn) => callbackFn(settingName, roomId, level, value, value));
});
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId) => {
if (settingName === "acknowledgedHistoryVisibility") {
return acknowledgedHistoryVisibility;
}
if (settingName === "feature_share_history_on_invite") {
return true;
}
return SettingsStore.getDefaultValue(settingName);
});
jest.spyOn(SettingsStore, "watchSetting").mockImplementation((settingName, roomId, callbackFn) => {
watcherCallbacks.push(callbackFn);
return `mockWatcherId-${settingName}-${roomId}`;
});
stubClient();
room = new Room(ROOM_ID, {} as any, "@user:example.org");
});
afterEach(() => {
jest.clearAllMocks();
});
it("should not show the banner in unencrypted rooms", () => {
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
expect(vm.getSnapshot().visible).toBe(false);
});
it("should not show the banner in encrypted rooms with joined history visibility", () => {
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
content: {
history_visibility: "joined",
},
user: "@user1:server",
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
expect(vm.getSnapshot().visible).toBe(false);
});
it("should not show the banner if it has been dismissed", async () => {
await SettingsStore.setValue("acknowledgedHistoryVisibility", ROOM_ID, SettingLevel.ROOM_ACCOUNT, true);
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
user: "@user1:server",
content: {
history_visibility: "shared",
},
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
expect(vm.getSnapshot().visible).toBe(false);
vm.dispose();
});
it("should not show the banner in threads", () => {
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
user: "@user1:server",
content: {
history_visibility: "shared",
},
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: "some thread ID" });
expect(vm.getSnapshot().visible).toBe(false);
vm.dispose();
});
it("should not show the banner if the user cannot send messages", () => {
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
user: "@user1:server",
content: {
history_visibility: "shared",
},
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: false, threadId: null });
expect(vm.getSnapshot().visible).toBe(false);
vm.dispose();
});
it("should not show the banner if history visibility is `invited`", () => {
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
user: "@user1:server",
content: {
history_visibility: "invited",
},
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
expect(vm.getSnapshot().visible).toBe(false);
vm.dispose();
});
it("should show the banner in encrypted rooms with shared history visibility", async () => {
upsertRoomStateEvents(room, [
mkEvent({
event: true,
type: "m.room.encryption",
user: "@user1:server",
content: {},
}),
mkEvent({
event: true,
type: "m.room.history_visibility",
user: "@user1:server",
content: {
history_visibility: "shared",
},
}),
]);
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
expect(vm.getSnapshot().visible).toBe(true);
await vm.onClose();
expect(vm.getSnapshot().visible).toBe(false);
});
});