Fix room list often showing the wrong icons for calls (#32881)

* Give rooms with calls a proper accessible description

Besides improving accessibility, this makes it possible to check for the presence of a call indicator in the room list in Playwright tests.

* Make room list react to calls in a room, even when not connected to them

To use the results of CallStore.getRoom reactively, you need to listen for Call events, not ConnectedCalls events.

* Don't assume that every call starts off as a video call

If a Call object is created by way of someone starting a voice call, then of course the call's initial type needs to be 'voice'.

* Make room list items react to changes in call type

The type of a call may change over time; therefore room list items explicitly need to react to the changes.

* Update a call's type before notifying listeners of the change

If we notify listeners of a change in a call's type before actually making that change, the listeners will be working with glitched state. This would cause the room list to show the wrong call type in certain situations.

* Ignore the Vitest attachments directory
This commit is contained in:
Robin
2026-03-26 11:28:48 +01:00
committed by GitHub
parent 441b292353
commit 5a074e637a
15 changed files with 468 additions and 44 deletions
@@ -189,25 +189,31 @@ test.describe("Element Call", () => {
expect(hash.get("skipLobby")).toEqual("true");
});
test("should be able to join a call in progress", async ({ page, user, bot, room, app }) => {
await app.viewRoomById(room.roomId);
// Allow bob to create a call
await expect(page.getByText("Bob and one other were invited and joined")).toBeVisible();
await app.client.setPowerLevel(room.roomId, bot.credentials.userId, 50);
// Fake a start of a call
await sendRTCState(bot, room.roomId);
const button = page.getByTestId("join-call-button");
await expect(button).toBeInViewport({ timeout: 5000 });
// And test joining
await button.click();
const frameUrlStr = await page.locator("iframe").getAttribute("src");
await expect(frameUrlStr).toBeDefined();
const url = new URL(frameUrlStr);
const hash = new URLSearchParams(url.hash.slice(1));
assertCommonCallParameters(url.searchParams, hash, user, room);
["voice", "video"].forEach((callType) => {
test(`should be able to join a ${callType} call in progress`, async ({ page, user, bot, room, app }) => {
await app.viewRoomById(room.roomId);
// Allow bob to create a call
await expect(page.getByText("Bob and one other were invited and joined")).toBeVisible();
await app.client.setPowerLevel(room.roomId, bot.credentials.userId, 50);
// Fake a start of a call
await sendRTCState(bot, room.roomId, undefined, callType === "voice" ? "audio" : "video");
const button = page.getByTestId("join-call-button");
await expect(button).toBeInViewport({ timeout: 5000 });
// Room list should show that a call is ongoing
await expect(
page.getByRole("option", { name: `Open room TestRoom with a ${callType} call.` }),
).toBeVisible();
// And test joining
await button.click();
const frameUrlStr = await page.locator("iframe").getAttribute("src");
await expect(frameUrlStr).toBeDefined();
const url = new URL(frameUrlStr);
const hash = new URLSearchParams(url.hash.slice(1));
assertCommonCallParameters(url.searchParams, hash, user, room);
expect(hash.get("intent")).toEqual("join_existing");
expect(hash.get("skipLobby")).toEqual(null);
expect(hash.get("intent")).toEqual("join_existing");
expect(hash.get("skipLobby")).toEqual(null);
});
});
[true, false].forEach((skipLobbyToggle) => {