121 lines
4.8 KiB
TypeScript
121 lines
4.8 KiB
TypeScript
|
/*
|
||
|
* 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
|
||
|
* Please see LICENSE files in the repository root for full details.
|
||
|
*/
|
||
|
|
||
|
import { mocked } from "jest-mock";
|
||
|
|
||
|
import SettingsStore, { CallbackFn } from "../../../src/settings/SettingsStore";
|
||
|
import { Feature, ReleaseAnnouncementStore } from "../../../src/stores/ReleaseAnnouncementStore";
|
||
|
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||
|
|
||
|
jest.mock("../../../src/settings/SettingsStore");
|
||
|
|
||
|
describe("ReleaseAnnouncementStore", () => {
|
||
|
let releaseAnnouncementStore: ReleaseAnnouncementStore;
|
||
|
// Local settings
|
||
|
// Instead of using the real SettingsStore, we use a local settings object
|
||
|
// to avoid side effects between tests
|
||
|
let settings: Record<string, any> = {};
|
||
|
|
||
|
beforeEach(() => {
|
||
|
// Default settings
|
||
|
settings = {
|
||
|
feature_release_announcement: true,
|
||
|
releaseAnnouncementData: {},
|
||
|
};
|
||
|
const watchCallbacks: Array<CallbackFn> = [];
|
||
|
|
||
|
mocked(SettingsStore.getValue).mockImplementation((setting: string) => {
|
||
|
return settings[setting];
|
||
|
});
|
||
|
mocked(SettingsStore.setValue).mockImplementation(
|
||
|
(settingName: string, roomId: string | null, level: SettingLevel, value: any): Promise<void> => {
|
||
|
settings[settingName] = value;
|
||
|
// we don't care about the parameters, just call the callbacks
|
||
|
// @ts-ignore
|
||
|
watchCallbacks.forEach((cb) => cb());
|
||
|
return Promise.resolve();
|
||
|
},
|
||
|
);
|
||
|
mocked(SettingsStore.isLevelSupported).mockReturnValue(true);
|
||
|
mocked(SettingsStore.canSetValue).mockReturnValue(true);
|
||
|
mocked(SettingsStore.watchSetting).mockImplementation((settingName: string, roomId: null, callback: any) => {
|
||
|
watchCallbacks.push(callback);
|
||
|
return "watcherId";
|
||
|
});
|
||
|
|
||
|
releaseAnnouncementStore = new ReleaseAnnouncementStore();
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Disables the release announcement feature.
|
||
|
*/
|
||
|
function disableReleaseAnnouncement() {
|
||
|
settings["feature_release_announcement"] = false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Listens to the next release announcement change event.
|
||
|
*/
|
||
|
function listenReleaseAnnouncementChanged() {
|
||
|
return new Promise<Feature | null>((resolve) =>
|
||
|
releaseAnnouncementStore.once("releaseAnnouncementChanged", resolve),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
it("should be a singleton", () => {
|
||
|
expect(ReleaseAnnouncementStore.instance).toBeDefined();
|
||
|
});
|
||
|
|
||
|
it("should return null when the release announcement is disabled", async () => {
|
||
|
disableReleaseAnnouncement();
|
||
|
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBeNull();
|
||
|
|
||
|
// Wait for the next release announcement change event
|
||
|
const promise = listenReleaseAnnouncementChanged();
|
||
|
// Call the next release announcement
|
||
|
// because the release announcement is disabled, the next release announcement should be null
|
||
|
await releaseAnnouncementStore.nextReleaseAnnouncement();
|
||
|
expect(await promise).toBeNull();
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBeNull();
|
||
|
});
|
||
|
|
||
|
it("should return the next feature when the next release announcement is called", async () => {
|
||
|
// Sanity check
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBe("threadsActivityCentre");
|
||
|
|
||
|
let promise = listenReleaseAnnouncementChanged();
|
||
|
await releaseAnnouncementStore.nextReleaseAnnouncement();
|
||
|
|
||
|
expect(await promise).toBe("pinningMessageList");
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBe("pinningMessageList");
|
||
|
|
||
|
promise = listenReleaseAnnouncementChanged();
|
||
|
await releaseAnnouncementStore.nextReleaseAnnouncement();
|
||
|
|
||
|
expect(await promise).toBeNull();
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBeNull();
|
||
|
|
||
|
const secondStore = new ReleaseAnnouncementStore();
|
||
|
// All the release announcements have been viewed, so it should be updated in the store account
|
||
|
// The release announcement viewing states should be share among all instances (devices in the same account)
|
||
|
expect(secondStore.getReleaseAnnouncement()).toBeNull();
|
||
|
});
|
||
|
|
||
|
it("should listen to release announcement data changes in the store", async () => {
|
||
|
const secondStore = new ReleaseAnnouncementStore();
|
||
|
expect(secondStore.getReleaseAnnouncement()).toBe("threadsActivityCentre");
|
||
|
|
||
|
const promise = listenReleaseAnnouncementChanged();
|
||
|
await secondStore.nextReleaseAnnouncement();
|
||
|
|
||
|
expect(await promise).toBe("pinningMessageList");
|
||
|
expect(releaseAnnouncementStore.getReleaseAnnouncement()).toBe("pinningMessageList");
|
||
|
});
|
||
|
});
|