Don't assume that widget IDs are unique (#8052)
* Don't assume that widget IDs are unique Signed-off-by: Robin Townsend <robin@robin.town> * Don't remove live tiles that don't exist Signed-off-by: Robin Townsend <robin@robin.town> * Add unit test for AppTile's live tile tracking Signed-off-by: Robin Townsend <robin@robin.town>
This commit is contained in:
parent
bc8fdac491
commit
744eeb53fe
13 changed files with 276 additions and 159 deletions
|
@ -44,7 +44,20 @@ describe("AppTile", () => {
|
|||
let r1;
|
||||
let r2;
|
||||
const resizeNotifier = new ResizeNotifier();
|
||||
let app: IApp;
|
||||
let app1: IApp;
|
||||
let app2: IApp;
|
||||
|
||||
const waitForRps = (roomId: string) => new Promise<void>(resolve => {
|
||||
const update = () => {
|
||||
if (
|
||||
RightPanelStore.instance.currentCardForRoom(roomId).phase !==
|
||||
RightPanelPhases.Widget
|
||||
) return;
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, update);
|
||||
resolve();
|
||||
};
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, update);
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
stubClient();
|
||||
|
@ -66,18 +79,31 @@ describe("AppTile", () => {
|
|||
return [r1, r2];
|
||||
});
|
||||
|
||||
// Adjust various widget stores to add a mock app
|
||||
app = {
|
||||
// Adjust various widget stores to add mock apps
|
||||
app1 = {
|
||||
id: "1",
|
||||
eventId: "1",
|
||||
roomId: "r1",
|
||||
type: MatrixWidgetType.Custom,
|
||||
url: "https://example.com",
|
||||
name: "Example",
|
||||
name: "Example 1",
|
||||
creatorUserId: cli.getUserId(),
|
||||
avatar_url: null,
|
||||
};
|
||||
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([app]);
|
||||
app2 = {
|
||||
id: "1",
|
||||
eventId: "2",
|
||||
roomId: "r2",
|
||||
type: MatrixWidgetType.Custom,
|
||||
url: "https://example.com",
|
||||
name: "Example 2",
|
||||
creatorUserId: cli.getUserId(),
|
||||
avatar_url: null,
|
||||
};
|
||||
jest.spyOn(WidgetStore.instance, "getApps").mockImplementation(roomId => {
|
||||
if (roomId === "r1") return [app1];
|
||||
if (roomId === "r2") return [app2];
|
||||
});
|
||||
|
||||
// Wake up various stores we rely on
|
||||
WidgetLayoutStore.instance.useUnitTestClient(cli);
|
||||
|
@ -88,6 +114,26 @@ describe("AppTile", () => {
|
|||
await RightPanelStore.instance.onReady();
|
||||
});
|
||||
|
||||
it("tracks live tiles correctly", () => {
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(false);
|
||||
|
||||
// Try removing the tile before it gets added
|
||||
AppTile.removeLiveTile("1", "r1");
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(false);
|
||||
|
||||
AppTile.addLiveTile("1", "r1");
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(true);
|
||||
|
||||
AppTile.addLiveTile("1", "r1");
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(true);
|
||||
|
||||
AppTile.removeLiveTile("1", "r1");
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(true);
|
||||
|
||||
AppTile.removeLiveTile("1", "r1");
|
||||
expect(AppTile.isLive("1", "r1")).toEqual(false);
|
||||
});
|
||||
|
||||
it("destroys non-persisted right panel widget on room change", async () => {
|
||||
// Set up right panel state
|
||||
const realGetValue = SettingsStore.getValue;
|
||||
|
@ -115,24 +161,14 @@ describe("AppTile", () => {
|
|||
/>
|
||||
</MatrixClientContext.Provider>);
|
||||
// Wait for RPS room 1 updates to fire
|
||||
const rpsUpdated = new Promise<void>(resolve => {
|
||||
const update = () => {
|
||||
if (
|
||||
RightPanelStore.instance.currentCardForRoom("r1").phase !==
|
||||
RightPanelPhases.Widget
|
||||
) return;
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, update);
|
||||
resolve();
|
||||
};
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, update);
|
||||
});
|
||||
const rpsUpdated = waitForRps("r1");
|
||||
dis.dispatch({
|
||||
action: Action.ViewRoom,
|
||||
room_id: "r1",
|
||||
});
|
||||
await rpsUpdated;
|
||||
|
||||
expect(AppTile.isLive("1")).toBe(true);
|
||||
expect(AppTile.isLive("1", "r1")).toBe(true);
|
||||
|
||||
// We want to verify that as we change to room 2, we should close the
|
||||
// right panel and destroy the widget.
|
||||
|
@ -152,11 +188,88 @@ describe("AppTile", () => {
|
|||
</MatrixClientContext.Provider>);
|
||||
|
||||
expect(endWidgetActions.mock.calls.length).toBe(1);
|
||||
expect(AppTile.isLive("1")).toBe(false);
|
||||
expect(AppTile.isLive("1", "r1")).toBe(false);
|
||||
|
||||
mockSettings.mockRestore();
|
||||
});
|
||||
|
||||
it("distinguishes widgets with the same ID in different rooms", async () => {
|
||||
// Set up right panel state
|
||||
const realGetValue = SettingsStore.getValue;
|
||||
SettingsStore.getValue = (name, roomId) => {
|
||||
if (name === "RightPanel.phases") {
|
||||
if (roomId === "r1") {
|
||||
return {
|
||||
history: [{
|
||||
phase: RightPanelPhases.Widget,
|
||||
state: {
|
||||
widgetId: "1",
|
||||
},
|
||||
}],
|
||||
isOpen: true,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return realGetValue(name, roomId);
|
||||
};
|
||||
|
||||
// Run initial render with room 1, and also running lifecycle methods
|
||||
const renderer = TestRenderer.create(<MatrixClientContext.Provider value={cli}>
|
||||
<RightPanel
|
||||
room={r1}
|
||||
resizeNotifier={resizeNotifier}
|
||||
/>
|
||||
</MatrixClientContext.Provider>);
|
||||
// Wait for RPS room 1 updates to fire
|
||||
const rpsUpdated1 = waitForRps("r1");
|
||||
dis.dispatch({
|
||||
action: Action.ViewRoom,
|
||||
room_id: "r1",
|
||||
});
|
||||
await rpsUpdated1;
|
||||
|
||||
expect(AppTile.isLive("1", "r1")).toBe(true);
|
||||
expect(AppTile.isLive("1", "r2")).toBe(false);
|
||||
|
||||
SettingsStore.getValue = (name, roomId) => {
|
||||
if (name === "RightPanel.phases") {
|
||||
if (roomId === "r2") {
|
||||
return {
|
||||
history: [{
|
||||
phase: RightPanelPhases.Widget,
|
||||
state: {
|
||||
widgetId: "1",
|
||||
},
|
||||
}],
|
||||
isOpen: true,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return realGetValue(name, roomId);
|
||||
};
|
||||
// Wait for RPS room 2 updates to fire
|
||||
const rpsUpdated2 = waitForRps("r2");
|
||||
// Switch to room 2
|
||||
dis.dispatch({
|
||||
action: Action.ViewRoom,
|
||||
room_id: "r2",
|
||||
});
|
||||
renderer.update(<MatrixClientContext.Provider value={cli}>
|
||||
<RightPanel
|
||||
room={r2}
|
||||
resizeNotifier={resizeNotifier}
|
||||
/>
|
||||
</MatrixClientContext.Provider>);
|
||||
await rpsUpdated2;
|
||||
|
||||
expect(AppTile.isLive("1", "r1")).toBe(false);
|
||||
expect(AppTile.isLive("1", "r2")).toBe(true);
|
||||
|
||||
SettingsStore.getValue = realGetValue;
|
||||
});
|
||||
|
||||
it("preserves non-persisted widget on container move", async () => {
|
||||
// Set up widget in top container
|
||||
const realGetValue = SettingsStore.getValue;
|
||||
|
@ -187,7 +300,7 @@ describe("AppTile", () => {
|
|||
/>
|
||||
</MatrixClientContext.Provider>);
|
||||
|
||||
expect(AppTile.isLive("1")).toBe(true);
|
||||
expect(AppTile.isLive("1", "r1")).toBe(true);
|
||||
|
||||
// We want to verify that as we move the widget to the center container,
|
||||
// the widget frame remains running.
|
||||
|
@ -199,11 +312,11 @@ describe("AppTile", () => {
|
|||
// Stop mocking settings so that the widget move can take effect
|
||||
mockSettings.mockRestore();
|
||||
TestRenderer.act(() => {
|
||||
WidgetLayoutStore.instance.moveToContainer(r1, app, Container.Center);
|
||||
WidgetLayoutStore.instance.moveToContainer(r1, app1, Container.Center);
|
||||
});
|
||||
|
||||
expect(endWidgetActions.mock.calls.length).toBe(0);
|
||||
expect(AppTile.isLive("1")).toBe(true);
|
||||
expect(AppTile.isLive("1", "r1")).toBe(true);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue