mirror of
https://github.com/vector-im/element-call.git
synced 2026-01-18 02:32:27 +00:00
162 lines
5.3 KiB
TypeScript
162 lines
5.3 KiB
TypeScript
/*
|
|
Copyright 2026 Element Creations Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { expect, test } from "@playwright/test";
|
|
|
|
import { widgetTest } from "../fixtures/widget-user.ts";
|
|
import { TestHelpers } from "./test-helpers.ts";
|
|
|
|
widgetTest("Create and join a group call", async ({ addUser, browserName }) => {
|
|
test.skip(
|
|
browserName === "firefox",
|
|
"The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled",
|
|
);
|
|
|
|
test.slow(); // We are registering multiple users here, give it more time
|
|
|
|
const valere = await addUser("Valere");
|
|
const timo = await addUser("Timo");
|
|
const robin = await addUser("Robin");
|
|
const halfshot = await addUser("Halfshot");
|
|
const florian = await addUser("florian");
|
|
|
|
const roomName = "Group Call Room";
|
|
await TestHelpers.createRoom(roomName, valere.page, [
|
|
timo.mxId,
|
|
robin.mxId,
|
|
halfshot.mxId,
|
|
florian.mxId,
|
|
]);
|
|
|
|
for (const user of [timo, robin, halfshot, florian]) {
|
|
// Accept the invite
|
|
// This doesn't super stable to get this as this super generic locator,
|
|
// but it works for now.
|
|
await expect(
|
|
user.page.getByRole("option", { name: roomName }),
|
|
).toBeVisible();
|
|
await user.page.getByRole("option", { name: roomName }).click();
|
|
await user.page.getByRole("button", { name: "Accept" }).click();
|
|
|
|
await expect(
|
|
user.page.getByRole("main").getByRole("heading", { name: roomName }),
|
|
).toBeVisible();
|
|
}
|
|
|
|
// Start the call as Valere
|
|
await TestHelpers.startCallInCurrentRoom(valere.page, false);
|
|
await expect(
|
|
valere.page.locator('iframe[title="Element Call"]'),
|
|
).toBeVisible();
|
|
|
|
await expect(
|
|
valere.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame()
|
|
.getByTestId("lobby_joinCall"),
|
|
).toBeVisible();
|
|
|
|
await valere.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame()
|
|
.getByTestId("lobby_joinCall")
|
|
.click();
|
|
|
|
for (const user of [timo, robin, halfshot, florian]) {
|
|
// THis is the header button that notifies about an ongoing call
|
|
await expect(user.page.getByText("Video call started")).toBeVisible();
|
|
await expect(user.page.getByRole("button", { name: "Join" })).toBeVisible();
|
|
await user.page.getByRole("button", { name: "Join" }).click();
|
|
}
|
|
|
|
for (const user of [timo, robin, halfshot, florian]) {
|
|
const frame = user.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame();
|
|
|
|
// No lobby, should start with video on
|
|
// The only way to know if it is muted or not is to look at the data-kind attribute..
|
|
const videoButton = frame.getByTestId("incall_videomute");
|
|
await expect(videoButton).toBeVisible();
|
|
// video should be off by default in a voice call
|
|
await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/);
|
|
}
|
|
|
|
// We should see 5 video tiles everywhere now
|
|
for (const user of [valere, timo, robin, halfshot, florian]) {
|
|
const frame = user.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame();
|
|
await expect(frame.getByTestId("videoTile")).toHaveCount(5);
|
|
for (const participant of [valere, timo, robin, halfshot, florian]) {
|
|
// Check the names are correct
|
|
await expect(frame.getByText(participant.displayName)).toBeVisible();
|
|
}
|
|
|
|
// There is no other options than to wait for all media to be ready?
|
|
// Or it is too flaky :/
|
|
await user.page.waitForTimeout(5000);
|
|
// No one should be waiting for media
|
|
await expect(frame.getByText("Waiting for media...")).not.toBeVisible();
|
|
|
|
// There should be 5 video elements, visible and autoplaying
|
|
const videoElements = await frame.locator("video").all();
|
|
expect(videoElements.length).toBe(5);
|
|
await expect(frame.locator("video[autoplay]")).toHaveCount(5);
|
|
|
|
const blockDisplayCount = await frame
|
|
.locator("video")
|
|
.evaluateAll(
|
|
(videos: Element[]) =>
|
|
videos.filter(
|
|
(v: Element) => window.getComputedStyle(v).display === "block",
|
|
).length,
|
|
);
|
|
expect(blockDisplayCount).toBe(5);
|
|
}
|
|
|
|
// Quickly test muting one participant to see it reflects and that our asserts works
|
|
const florianFrame = florian.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame();
|
|
const florianMuteButton = florianFrame.getByTestId("incall_videomute");
|
|
await florianMuteButton.click();
|
|
// Now the button should indicate we can start video
|
|
await expect(florianMuteButton).toHaveAttribute(
|
|
"aria-label",
|
|
/^Start video$/,
|
|
);
|
|
|
|
// wait a bit for the state to propagate
|
|
await valere.page.waitForTimeout(3000);
|
|
{
|
|
const frame = valere.page
|
|
.locator('iframe[title="Element Call"]')
|
|
.contentFrame();
|
|
|
|
const videoElements = await frame.locator("video").all();
|
|
expect(videoElements.length).toBe(5);
|
|
//
|
|
// // ONLY 4 !!!!!
|
|
// await expect(frame.locator('video[autoplay]')).toHaveCount(4);
|
|
|
|
const blockDisplayCount = await frame
|
|
.locator("video")
|
|
.evaluateAll(
|
|
(videos: Element[]) =>
|
|
videos.filter(
|
|
(v: Element) => window.getComputedStyle(v).display === "block",
|
|
).length,
|
|
);
|
|
|
|
// ONLY 4!!
|
|
expect(blockDisplayCount).toBe(4);
|
|
}
|
|
|
|
await valere.page.pause();
|
|
});
|