Rewrite tons of tests
This commit is contained in:
129
playwright/e2e/timeline/media-preview-settings.spec.ts
Normal file
129
playwright/e2e/timeline/media-preview-settings.spec.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022, 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 * as fs from "node:fs";
|
||||
import { type EventType, type MsgType } from "matrix-js-sdk/src/types";
|
||||
import { JoinRule } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type { Locator, Page } from "@playwright/test";
|
||||
import { test, expect } from "../../element-web-test";
|
||||
import { Bot } from "../../pages/bot";
|
||||
|
||||
const ROOM_NAME = "Test room";
|
||||
const OLD_NAME = "Alan";
|
||||
|
||||
const MEDIA_FILE = fs.readFileSync("playwright/sample-files/riot.png");
|
||||
|
||||
test.describe("Media preview settings", () => {
|
||||
test.use({
|
||||
displayName: OLD_NAME,
|
||||
room: async ({ app, page, homeserver, bot, user }, use) => {
|
||||
const mxc = (await bot.uploadContent(MEDIA_FILE, { name: "image.png", type: "image/png" })).content_uri;
|
||||
const roomId = await bot.createRoom({
|
||||
name: ROOM_NAME,
|
||||
invite: [user.userId],
|
||||
initial_state: [{ type: "m.room.avatar", content: { url: mxc }, state_key: "" }],
|
||||
});
|
||||
await bot.sendEvent(roomId, null, "m.room.message" as EventType, {
|
||||
msgtype: "m.image" as MsgType,
|
||||
body: "image.png",
|
||||
url: mxc,
|
||||
});
|
||||
|
||||
await use({ roomId });
|
||||
},
|
||||
});
|
||||
|
||||
test("should be able to hide avatars of inviters", { tag: "@screenshot" }, async ({ page, app, room, user }) => {
|
||||
let settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Hide avatars of room and inviter").click();
|
||||
await app.closeDialog();
|
||||
await app.viewRoomById(room.roomId);
|
||||
expect(page.getByRole("complementary").filter({ hasText: "Do you want to join Test room" })).toMatchScreenshot(
|
||||
"invite-no-avatar.png",
|
||||
);
|
||||
expect(
|
||||
page.getByRole("tree", { name: "Rooms" }).getByRole("treeitem", { name: "Test room" }),
|
||||
).toMatchScreenshot("invite-room-tree-no-avatar.png");
|
||||
|
||||
// And then go back to being visible
|
||||
settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Hide avatars of room and inviter").click();
|
||||
await app.closeDialog();
|
||||
await page.goto("#/home");
|
||||
await app.viewRoomById(room.roomId);
|
||||
expect(page.getByRole("complementary").filter({ hasText: "Do you want to join Test room" })).toMatchScreenshot(
|
||||
"invite-with-avatar.png",
|
||||
);
|
||||
expect(
|
||||
page.getByRole("tree", { name: "Rooms" }).getByRole("treeitem", { name: "Test room" }),
|
||||
).toMatchScreenshot("invite-room-tree-with-avatar.png");
|
||||
});
|
||||
|
||||
test("should be able to hide media in rooms globally", async ({ page, app, room, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always hide" }).click();
|
||||
await app.closeDialog();
|
||||
await app.viewRoomById(room.roomId);
|
||||
await page.getByRole("button", { name: "Accept" }).click();
|
||||
await expect(page.getByText("Show image")).toBeVisible();
|
||||
});
|
||||
test("should be able to hide media in non-private rooms globally", async ({ page, app, room, user, bot }) => {
|
||||
await bot.sendStateEvent(room.roomId, "m.room.join_rules", {
|
||||
join_rule: "public",
|
||||
});
|
||||
const settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Show media in timeline").getByLabel("In private rooms").click();
|
||||
await app.closeDialog();
|
||||
await app.viewRoomById(room.roomId);
|
||||
await page.getByRole("button", { name: "Accept" }).click();
|
||||
await expect(page.getByText("Show image")).toBeVisible();
|
||||
for (const joinRule of [JoinRule.Invite, JoinRule.Knock, JoinRule.Restricted]) {
|
||||
await bot.sendStateEvent(room.roomId, "m.room.join_rules", {
|
||||
join_rule: joinRule,
|
||||
});
|
||||
await expect(page.getByText("Show image")).not.toBeVisible();
|
||||
}
|
||||
});
|
||||
test("should be able to show media in rooms globally", async ({ page, app, room, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always show" }).click();
|
||||
await app.closeDialog();
|
||||
await app.viewRoomById(room.roomId);
|
||||
await page.getByRole("button", { name: "Accept" }).click();
|
||||
await expect(page.getByText("Show image")).not.toBeVisible();
|
||||
});
|
||||
test("should be able to hide media in an individual room", async ({ page, app, room, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always show" }).click();
|
||||
await app.closeDialog();
|
||||
|
||||
await app.viewRoomById(room.roomId);
|
||||
await page.getByRole("button", { name: "Accept" }).click();
|
||||
|
||||
const roomSettings = await app.settings.openRoomSettings("General");
|
||||
await roomSettings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always hide" }).click();
|
||||
await app.closeDialog();
|
||||
|
||||
await expect(page.getByText("Show image")).toBeVisible();
|
||||
});
|
||||
test("should be able to show media in an individual room", async ({ page, app, room, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Preferences");
|
||||
await settings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always hide" }).click();
|
||||
await app.closeDialog();
|
||||
|
||||
await app.viewRoomById(room.roomId);
|
||||
await page.getByRole("button", { name: "Accept" }).click();
|
||||
|
||||
const roomSettings = await app.settings.openRoomSettings("General");
|
||||
await roomSettings.getByLabel("Show media in timeline").getByRole("radio", { name: "Always show" }).click();
|
||||
await app.closeDialog();
|
||||
|
||||
await expect(page.getByText("Show image")).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -22,6 +22,7 @@ import { SettingsSubsection } from "../../shared/SettingsSubsection";
|
||||
import SettingsTab from "../SettingsTab";
|
||||
import { SettingsSection } from "../../shared/SettingsSection";
|
||||
import { UrlPreviewSettings } from "../../../room_settings/UrlPreviewSettings";
|
||||
import { MediaPreviewAccountSettings } from "../user/MediaPreviewSetting";
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
@@ -92,6 +93,7 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
||||
|
||||
<SettingsSection heading={_t("room_settings|general|other_section")}>
|
||||
{urlPreviewSettings}
|
||||
<MediaPreviewAccountSettings roomId={room.roomId} />
|
||||
{leaveSection}
|
||||
</SettingsSection>
|
||||
</SettingsTab>
|
||||
|
||||
@@ -15,19 +15,30 @@ import { useSettingValue } from "../../../../../hooks/useSettings";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||
|
||||
export const MediaPreviewAccountSettings: React.FC = () => {
|
||||
const currentMediaPreview = useSettingValue("mediaPreviewConfig");
|
||||
export const MediaPreviewAccountSettings: React.FC<{ roomId?: string }> = ({ roomId }) => {
|
||||
const currentMediaPreview = useSettingValue("mediaPreviewConfig", roomId);
|
||||
|
||||
const changeSetting = useCallback(
|
||||
(newValue: MediaPreviewConfig) => {
|
||||
SettingsStore.setValue(
|
||||
"mediaPreviewConfig",
|
||||
roomId ?? null,
|
||||
roomId ? SettingLevel.ROOM_ACCOUNT : SettingLevel.ACCOUNT,
|
||||
newValue,
|
||||
);
|
||||
},
|
||||
[roomId],
|
||||
);
|
||||
|
||||
const avatarOnChange = useCallback(
|
||||
(c: boolean) => {
|
||||
const newValue = {
|
||||
changeSetting({
|
||||
...currentMediaPreview,
|
||||
// Switch is inverted. "Hide avatars..."
|
||||
invite_avatars: c ? MediaPreviewValue.Off : MediaPreviewValue.On,
|
||||
} satisfies MediaPreviewConfig;
|
||||
SettingsStore.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, newValue);
|
||||
});
|
||||
},
|
||||
[currentMediaPreview],
|
||||
[changeSetting, currentMediaPreview],
|
||||
);
|
||||
|
||||
const mediaPreviewOnChangeOff = useCallback<ChangeEventHandler<HTMLInputElement>>(
|
||||
@@ -35,12 +46,12 @@ export const MediaPreviewAccountSettings: React.FC = () => {
|
||||
if (!event.target.checked) {
|
||||
return;
|
||||
}
|
||||
SettingsStore.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, {
|
||||
changeSetting({
|
||||
...currentMediaPreview,
|
||||
media_previews: MediaPreviewValue.Off,
|
||||
} satisfies MediaPreviewConfig);
|
||||
});
|
||||
},
|
||||
[currentMediaPreview],
|
||||
[changeSetting, currentMediaPreview],
|
||||
);
|
||||
|
||||
const mediaPreviewOnChangePrivate = useCallback<ChangeEventHandler<HTMLInputElement>>(
|
||||
@@ -48,12 +59,12 @@ export const MediaPreviewAccountSettings: React.FC = () => {
|
||||
if (!event.target.checked) {
|
||||
return;
|
||||
}
|
||||
SettingsStore.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, {
|
||||
changeSetting({
|
||||
...currentMediaPreview,
|
||||
media_previews: MediaPreviewValue.Private,
|
||||
} satisfies MediaPreviewConfig);
|
||||
});
|
||||
},
|
||||
[currentMediaPreview],
|
||||
[changeSetting, currentMediaPreview],
|
||||
);
|
||||
|
||||
const mediaPreviewOnChangeOn = useCallback<ChangeEventHandler<HTMLInputElement>>(
|
||||
@@ -61,56 +72,71 @@ export const MediaPreviewAccountSettings: React.FC = () => {
|
||||
if (!event.target.checked) {
|
||||
return;
|
||||
}
|
||||
SettingsStore.setValue("mediaPreviewConfig", null, SettingLevel.ACCOUNT, {
|
||||
changeSetting({
|
||||
...currentMediaPreview,
|
||||
media_previews: MediaPreviewValue.On,
|
||||
} satisfies MediaPreviewConfig);
|
||||
});
|
||||
},
|
||||
[currentMediaPreview],
|
||||
[changeSetting, currentMediaPreview],
|
||||
);
|
||||
|
||||
return (
|
||||
<Root>
|
||||
{!roomId && (
|
||||
<LabelledToggleSwitch
|
||||
label={_t("settings|media_preview|hide_avatars")}
|
||||
value={currentMediaPreview.invite_avatars === MediaPreviewValue.Off}
|
||||
onChange={avatarOnChange}
|
||||
/>
|
||||
<Field role="radiogroup" name="media_previews">
|
||||
)}
|
||||
{/* Explict label here because htmlFor is not supported for linking to radiogroups */}
|
||||
<Field
|
||||
id="mx_media_previews"
|
||||
role="radiogroup"
|
||||
name="media_previews"
|
||||
aria-label={_t("settings|media_preview|media_preview_label")}
|
||||
>
|
||||
<Label>{_t("settings|media_preview|media_preview_label")}</Label>
|
||||
<HelpMessage>{_t("settings|media_preview|media_preview_description")}</HelpMessage>
|
||||
<InlineField
|
||||
name="media_preview_off"
|
||||
control={
|
||||
<RadioInput
|
||||
id="mx_media_previews_off"
|
||||
checked={currentMediaPreview.media_previews === MediaPreviewValue.Off}
|
||||
onChange={mediaPreviewOnChangeOff}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Label>{_t("settings|media_preview|hide_media")}</Label>
|
||||
<Label htmlFor="mx_media_previews_off">{_t("settings|media_preview|hide_media")}</Label>
|
||||
</InlineField>
|
||||
{!roomId && (
|
||||
<InlineField
|
||||
name="media_preview_private"
|
||||
name="mx_media_previews_private"
|
||||
control={
|
||||
<RadioInput
|
||||
id="mx_media_previews_private"
|
||||
checked={currentMediaPreview.media_previews === MediaPreviewValue.Private}
|
||||
onChange={mediaPreviewOnChangePrivate}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Label>{_t("settings|media_preview|show_in_private")}</Label>
|
||||
<Label htmlFor="mx_media_previews_private">
|
||||
{_t("settings|media_preview|show_in_private")}
|
||||
</Label>
|
||||
</InlineField>
|
||||
)}
|
||||
<InlineField
|
||||
name="media_preview_on"
|
||||
control={
|
||||
<RadioInput
|
||||
id="mx_media_previews_on"
|
||||
checked={currentMediaPreview.media_previews === MediaPreviewValue.On}
|
||||
onChange={mediaPreviewOnChangeOn}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Label>{_t("settings|media_preview|show_media")}</Label>
|
||||
<Label htmlFor="mx_media_previews_on">{_t("settings|media_preview|show_media")}</Label>
|
||||
</InlineField>
|
||||
</Field>
|
||||
</Root>
|
||||
|
||||
30
src/hooks/room/useJoinRule.ts
Normal file
30
src/hooks/room/useJoinRule.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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 { useEffect, useState } from "react";
|
||||
import { EventType, type MatrixEvent, type Room, RoomStateEvent, type JoinRule } from "matrix-js-sdk/src/matrix";
|
||||
import { type Optional } from "matrix-events-sdk";
|
||||
|
||||
import { useTypedEventEmitter } from "../useEventEmitter";
|
||||
|
||||
/**
|
||||
* Helper to retrieve the join rules for given room
|
||||
* @param room
|
||||
* @returns the current join rule
|
||||
*/
|
||||
export function useJoinRule(room?: Room): Optional<JoinRule> {
|
||||
const [topic, setJoinRule] = useState(room?.getJoinRule());
|
||||
useTypedEventEmitter(room?.currentState, RoomStateEvent.Events, (ev: MatrixEvent) => {
|
||||
if (ev.getType() !== EventType.RoomJoinRules) return;
|
||||
setJoinRule(room?.getJoinRule());
|
||||
});
|
||||
useEffect(() => {
|
||||
setJoinRule(room?.getJoinRule());
|
||||
}, [room]);
|
||||
|
||||
return topic;
|
||||
}
|
||||
30
src/hooks/room/useRoomAvatar.ts
Normal file
30
src/hooks/room/useRoomAvatar.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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 { useEffect, useState } from "react";
|
||||
import { EventType, type MatrixEvent, type Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { type Optional } from "matrix-events-sdk";
|
||||
|
||||
import { useTypedEventEmitter } from "../useEventEmitter";
|
||||
|
||||
/**
|
||||
* Helper to retrieve the avatar for given room
|
||||
* @param room
|
||||
* @returns the current avatar
|
||||
*/
|
||||
export function useRoomAvatar(room?: Room): Optional<string> {
|
||||
const [topic, setAvatar] = useState(room?.getMxcAvatarUrl());
|
||||
useTypedEventEmitter(room?.currentState, RoomStateEvent.Events, (ev: MatrixEvent) => {
|
||||
if (ev.getType() !== EventType.RoomAvatar) return;
|
||||
setAvatar(room?.getMxcAvatarUrl());
|
||||
});
|
||||
useEffect(() => {
|
||||
setAvatar(room?.getMxcAvatarUrl());
|
||||
}, [room]);
|
||||
|
||||
return topic;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useCallback } from "react";
|
||||
import { JoinRule } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { SettingLevel } from "../settings/SettingLevel";
|
||||
@@ -13,6 +13,7 @@ import { useSettingValue } from "./useSettings";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { useMatrixClientContext } from "../contexts/MatrixClientContext";
|
||||
import { MediaPreviewValue } from "../@types/media_preview";
|
||||
import { useJoinRule } from "./room/useJoinRule";
|
||||
|
||||
const PRIVATE_JOIN_RULES: JoinRule[] = [JoinRule.Invite, JoinRule.Knock, JoinRule.Restricted];
|
||||
|
||||
@@ -25,6 +26,7 @@ export function useMediaVisible(eventId: string, roomId: string): [boolean, (vis
|
||||
const mediaPreviewSetting = useSettingValue("mediaPreviewConfig", roomId);
|
||||
const client = useMatrixClientContext();
|
||||
const eventVisibility = useSettingValue("showMediaEventIds");
|
||||
const joinRule = useJoinRule(client.getRoom(roomId) ?? undefined);
|
||||
const setMediaVisible = useCallback(
|
||||
(visible: boolean) => {
|
||||
SettingsStore.setValue("showMediaEventIds", null, SettingLevel.DEVICE, {
|
||||
@@ -35,15 +37,7 @@ export function useMediaVisible(eventId: string, roomId: string): [boolean, (vis
|
||||
[eventId, eventVisibility],
|
||||
);
|
||||
|
||||
const roomIsPrivate = useMemo(() => {
|
||||
const joinRule = client?.getRoom(roomId)?.getJoinRule();
|
||||
if (PRIVATE_JOIN_RULES.includes(joinRule as JoinRule)) {
|
||||
return true;
|
||||
} else {
|
||||
// All other join rules, and unknown will default to hiding.
|
||||
return false;
|
||||
}
|
||||
}, [client, roomId]);
|
||||
const roomIsPrivate = joinRule ? PRIVATE_JOIN_RULES.includes(joinRule) : false;
|
||||
|
||||
const explicitEventVisiblity = eventVisibility[eventId];
|
||||
// Always prefer the explicit per-event user preference here.
|
||||
|
||||
@@ -374,10 +374,6 @@ export default class SettingsStore {
|
||||
roomId: string | null = null,
|
||||
excludeDefault = false,
|
||||
): Settings[S]["default"] | undefined {
|
||||
if (settingName === "mediaPreviewConfig") {
|
||||
console.log("GET VALUE", SETTINGS[settingName]);
|
||||
}
|
||||
|
||||
// Verify that the setting is actually a setting
|
||||
if (!SETTINGS[settingName]) {
|
||||
throw new Error("Setting '" + settingName + "' does not appear to be a setting.");
|
||||
|
||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { ClientEvent, type MatrixEvent, type MatrixClient, IContent } from "matrix-js-sdk/src/matrix";
|
||||
import { type IContent } from "matrix-js-sdk/src/matrix";
|
||||
import { type AccountDataEvents } from "matrix-js-sdk/src/types";
|
||||
|
||||
import {
|
||||
@@ -31,16 +31,22 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
|
||||
const inviteAvatars: MediaPreviewValue = content.invite_avatars;
|
||||
const validValues = Object.values(MediaPreviewValue);
|
||||
return {
|
||||
invite_avatars: validValues.includes(inviteAvatars) ? inviteAvatars : MediaPreviewConfigController.default.invite_avatars,
|
||||
media_previews: validValues.includes(mediaPreviews) ? mediaPreviews : MediaPreviewConfigController.default.media_previews,
|
||||
invite_avatars: validValues.includes(inviteAvatars)
|
||||
? inviteAvatars
|
||||
: MediaPreviewConfigController.default.invite_avatars,
|
||||
media_previews: validValues.includes(mediaPreviews)
|
||||
? mediaPreviews
|
||||
: MediaPreviewConfigController.default.media_previews,
|
||||
};
|
||||
}
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
private getValue = (roomId?: string): MediaPreviewConfig | null => {
|
||||
const source = roomId ? this.client?.getRoom(roomId) : this.client;
|
||||
const value = source
|
||||
?.getAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE)
|
||||
?.getContent<MediaPreviewConfig>();
|
||||
const value = source?.getAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE)?.getContent<MediaPreviewConfig>();
|
||||
|
||||
if (!value) {
|
||||
return null;
|
||||
@@ -49,20 +55,17 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected async initMatrixClient(newClient: MatrixClient, oldClient?: MatrixClient): Promise<void> {
|
||||
|
||||
protected async initMatrixClient(): Promise<void> {
|
||||
// Unused
|
||||
}
|
||||
|
||||
public getValueOverride(_level: SettingLevel, roomId: string | null): MediaPreviewConfig {
|
||||
if (roomId) {
|
||||
// Use globals for any undefined setting
|
||||
return {
|
||||
...this.getRoomValue(roomId),
|
||||
...this.globalSetting,
|
||||
};
|
||||
const roomConfig = roomId && this.getValue(roomId);
|
||||
if (roomConfig) {
|
||||
return roomConfig;
|
||||
}
|
||||
return this.globalSetting;
|
||||
// If no room config, or global settings request then return global.
|
||||
return this.getValue() ?? MediaPreviewConfigController.default;
|
||||
}
|
||||
|
||||
public get settingDisabled(): false {
|
||||
@@ -79,9 +82,7 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
|
||||
return false;
|
||||
}
|
||||
if (roomId) {
|
||||
await this.client.setRoomAccountData(roomId, MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, {
|
||||
value: newValue,
|
||||
});
|
||||
await this.client.setRoomAccountData(roomId, MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
|
||||
return true;
|
||||
}
|
||||
await this.client.setAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import MatrixClientBackedController from "../../../../src/settings/controllers/MatrixClientBackedController";
|
||||
import MediaPreviewConfigController from "../../../../src/settings/controllers/MediaPreviewConfigController";
|
||||
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
||||
import { getMockClientWithEventEmitter, mockClientMethodsServer } from "../../../test-utils";
|
||||
import { MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, MediaPreviewValue } from "../../../../src/@types/media_preview";
|
||||
|
||||
describe("MediaPreviewConfigController", () => {
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const ROOM_ID = "!room:example.org";
|
||||
|
||||
it("gets the default settings when none are specified.", () => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest.fn().mockReturnValue(null),
|
||||
});
|
||||
|
||||
const value = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(value).toEqual(MediaPreviewConfigController.default);
|
||||
});
|
||||
|
||||
it("gets the default settings when the setting is empty.", () => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest
|
||||
.fn()
|
||||
.mockReturnValue(new MatrixEvent({ type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, content: {} })),
|
||||
});
|
||||
|
||||
const value = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(value).toEqual(MediaPreviewConfigController.default);
|
||||
});
|
||||
|
||||
it.each([["media_previews"], ["invite_avatars"]])("gets the correct value for %s at the global level", (key) => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest.fn().mockReturnValue(
|
||||
new MatrixEvent({
|
||||
type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
content: {
|
||||
[key]: MediaPreviewValue.Private,
|
||||
},
|
||||
}),
|
||||
),
|
||||
getRoom: jest.fn().mockReturnValue({
|
||||
getAccountData: jest.fn().mockReturnValue(null),
|
||||
}),
|
||||
});
|
||||
|
||||
const globalValue = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(globalValue[key]).toEqual(MediaPreviewValue.Private);
|
||||
|
||||
// Should follow the global value.
|
||||
const roomValue = controller.getValueOverride(SettingLevel.ROOM_ACCOUNT, ROOM_ID);
|
||||
expect(roomValue[key]).toEqual(MediaPreviewValue.Private);
|
||||
});
|
||||
|
||||
it.each([["media_previews"], ["invite_avatars"]])("gets the correct value for %s at the room level", (key) => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest.fn().mockReturnValue(null),
|
||||
getRoom: jest.fn().mockReturnValue({
|
||||
getAccountData: jest.fn().mockReturnValue(
|
||||
new MatrixEvent({
|
||||
type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
content: {
|
||||
[key]: MediaPreviewValue.Private,
|
||||
},
|
||||
}),
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const globalValue = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(globalValue[key]).toEqual(MediaPreviewValue.On);
|
||||
|
||||
// Should follow the global value.
|
||||
const roomValue = controller.getValueOverride(SettingLevel.ROOM_ACCOUNT, ROOM_ID);
|
||||
expect(roomValue[key]).toEqual(MediaPreviewValue.Private);
|
||||
});
|
||||
|
||||
it.each([["media_previews"], ["invite_avatars"]])(
|
||||
"uses defaults when an invalid value is set on the global level",
|
||||
(key) => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest.fn().mockReturnValue(
|
||||
new MatrixEvent({
|
||||
type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
content: {
|
||||
[key]: "bibble",
|
||||
},
|
||||
}),
|
||||
),
|
||||
getRoom: jest.fn().mockReturnValue({
|
||||
getAccountData: jest.fn().mockReturnValue(null),
|
||||
}),
|
||||
});
|
||||
|
||||
const globalValue = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(globalValue[key]).toEqual(MediaPreviewValue.On);
|
||||
|
||||
// Should follow the global value.
|
||||
const roomValue = controller.getValueOverride(SettingLevel.ROOM_ACCOUNT, ROOM_ID);
|
||||
expect(roomValue[key]).toEqual(MediaPreviewValue.On);
|
||||
},
|
||||
);
|
||||
it.each([["media_previews"], ["invite_avatars"]])(
|
||||
"uses global value when an invalid value is set on the room level",
|
||||
(key) => {
|
||||
const controller = new MediaPreviewConfigController();
|
||||
|
||||
MatrixClientBackedController.matrixClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
getAccountData: jest.fn().mockReturnValue(
|
||||
new MatrixEvent({
|
||||
type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
content: {
|
||||
[key]: MediaPreviewValue.Private,
|
||||
},
|
||||
}),
|
||||
),
|
||||
getRoom: jest.fn().mockReturnValue({
|
||||
getAccountData: jest.fn().mockReturnValue(
|
||||
new MatrixEvent({
|
||||
type: MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
content: {
|
||||
[key]: "bibble",
|
||||
},
|
||||
}),
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const globalValue = controller.getValueOverride(SettingLevel.ACCOUNT, null);
|
||||
expect(globalValue[key]).toEqual(MediaPreviewValue.Private);
|
||||
|
||||
// Should follow the global value.
|
||||
const roomValue = controller.getValueOverride(SettingLevel.ROOM_ACCOUNT, ROOM_ID);
|
||||
expect(roomValue[key]).toEqual(MediaPreviewValue.On);
|
||||
},
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user