prettier format

This commit is contained in:
Valere
2026-01-09 12:35:25 +01:00
parent 231a80d9de
commit d2907f51d3
8 changed files with 156 additions and 130 deletions

View File

@@ -176,7 +176,6 @@ export const widgetTest = test.extend<MyFixtures>({
.click();
if (callType === "room") {
await ewPage1.getByRole("menuitem", { name: "New Room" }).click();
await ewPage1.getByRole("textbox", { name: "Name" }).fill("Welcome Room");
await ewPage1.getByRole("button", { name: "Create room" }).click();
@@ -206,28 +205,35 @@ export const widgetTest = test.extend<MyFixtures>({
await ewPage2.getByRole("option", { name: "Welcome Room" }).click();
await ewPage2.getByRole("button", { name: "Accept" }).click();
await expect(
ewPage2.getByRole("main").getByRole("heading", { name: "Welcome Room" }),
ewPage2
.getByRole("main")
.getByRole("heading", { name: "Welcome Room" }),
).toBeVisible();
} else if (callType === "dm") {
await ewPage1.getByRole("menuitem", { name: "Start chat" }).click();
await ewPage1.getByRole('textbox', { name: 'Search' }).click();
await ewPage1.getByRole('textbox', { name: 'Search' }).fill(whistlerMxId);
await ewPage1.getByRole("textbox", { name: "Search" }).click();
await ewPage1.getByRole("textbox", { name: "Search" }).fill(whistlerMxId);
await ewPage1.getByRole("button", { name: "Go" }).click();
// Wait and send the first message to create the DM
await expect(ewPage1.getByText(/Send your first message to invite/)).toBeVisible();
await expect(
ewPage1.getByText(/Send your first message to invite/),
).toBeVisible();
await ewPage1.locator('.mx_BasicMessageComposer_input > div').click();
await ewPage1.getByRole('textbox', { name: 'Send a message…' }).fill('Hello!');
await ewPage1.locator(".mx_BasicMessageComposer_input > div").click();
await ewPage1
.getByRole("textbox", { name: "Send a message…" })
.fill("Hello!");
await ewPage1.getByRole("button", { name: "Send message" }).click();
await expect(ewPage1.getByText('This is the beginning of your')).toBeVisible();
await expect(
ewPage1.getByText("This is the beginning of your"),
).toBeVisible();
// Accept the DM invite from brooks
// This how playwright record selects the DM invite in the room list
await ewPage2.getByRole('option', { name: 'Open room' }).click();
await ewPage2.getByRole('button', { name: 'Start chatting' }).click();
await ewPage2.getByRole("option", { name: "Open room" }).click();
await ewPage2.getByRole("button", { name: "Start chatting" }).click();
}
// Renamed use to pUse, as a workaround for eslint error that was thinking this use was a react use.
@@ -236,13 +242,13 @@ export const widgetTest = test.extend<MyFixtures>({
mxId: brooksMxId,
page: ewPage1,
clientHandle: brooksClientHandle,
displayName: brooksDisplayName
displayName: brooksDisplayName,
},
whistler: {
mxId: whistlerMxId,
page: ewPage2,
clientHandle: whistlerClientHandle,
displayName: whistlerDisplayName
displayName: whistlerDisplayName,
},
});
},

View File

@@ -9,7 +9,7 @@ import { expect, test } from "@playwright/test";
import { widgetTest } from "../fixtures/widget-user.ts";
widgetTest.use({callType: "dm"});
widgetTest.use({ callType: "dm" });
widgetTest("Start a new voice call in DM as widget", async ({ asWidget }) => {
test.slow(); // Triples the timeout
@@ -28,8 +28,7 @@ widgetTest("Start a new voice call in DM as widget", async ({ asWidget }) => {
await brooks.page.getByRole("menuitem", { name: "Element Call" }).click();
await expect(
brooks.page
.locator('iframe[title="Element Call"]')
brooks.page.locator('iframe[title="Element Call"]'),
).toBeVisible();
const brooksFrame = brooks.page
@@ -37,15 +36,15 @@ widgetTest("Start a new voice call in DM as widget", async ({ asWidget }) => {
.contentFrame();
// We should show a ringing overlay, let's check for that
await expect(brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`)).toBeVisible();
await expect(
brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`),
).toBeVisible();
await expect(whistler.page.getByText('Incoming voice call')).toBeVisible();
await whistler.page.getByRole('button', { name: 'Accept' }).click();
await expect(whistler.page.getByText("Incoming voice call")).toBeVisible();
await whistler.page.getByRole("button", { name: "Accept" }).click();
await expect(
whistler.page
.locator('iframe[title="Element Call"]')
whistler.page.locator('iframe[title="Element Call"]'),
).toBeVisible();
const whistlerFrame = whistler.page
@@ -55,129 +54,144 @@ widgetTest("Start a new voice call in DM as widget", async ({ asWidget }) => {
// ASSERT the button states for whistler (the callee)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = whistlerFrame.getByTestId('incall_videomute');
const videoButton = whistlerFrame.getByTestId("incall_videomute");
// video should be off by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Start video$/);
const audioButton = whistlerFrame.getByTestId('incall_mute');
const audioButton = whistlerFrame.getByTestId("incall_mute");
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/);
await expect(audioButton).toHaveAttribute(
"aria-label",
/^Mute microphone$/,
);
}
// ASSERT the button states for brools (the caller)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = brooksFrame.getByTestId('incall_videomute');
const videoButton = brooksFrame.getByTestId("incall_videomute");
// video should be off by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Start video$/);
const audioButton = brooksFrame.getByTestId('incall_mute');
const audioButton = brooksFrame.getByTestId("incall_mute");
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/);
await expect(audioButton).toHaveAttribute(
"aria-label",
/^Mute microphone$/,
);
}
// In order to confirm that the call is disconnected we will check that the message composer is shown again.
// So first we need to confirm that it is hidden when in the call.
await expect(whistler.page.locator(".mx_BasicMessageComposer")).not.toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).not.toBeVisible();
await expect(
whistler.page.locator(".mx_BasicMessageComposer"),
).not.toBeVisible();
await expect(
brooks.page.locator(".mx_BasicMessageComposer"),
).not.toBeVisible();
// ASSERT hanging up on one side ends the call for both
{
const hangupButton = brooksFrame.getByTestId('incall_leave');
const hangupButton = brooksFrame.getByTestId("incall_leave");
await hangupButton.click();
}
// The widget should be closed on both sides and the timeline should be back on screen
await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible();
});
widgetTest(
"Start a new video call in DM as widget",
async ({ asWidget, browserName }) => {
test.slow(); // Triples the timeout
const { brooks, whistler } = asWidget;
widgetTest("Start a new video call in DM as widget", async ({ asWidget, browserName }) => {
test.slow(); // Triples the timeout
await expect(
brooks.page.getByRole("button", { name: "Video call" }),
).toBeVisible();
await brooks.page.getByRole("button", { name: "Video call" }).click();
const { brooks, whistler } = asWidget;
await expect(
brooks.page.getByRole("menuitem", { name: "Element Call" }),
).toBeVisible();
await expect(
brooks.page.getByRole("button", { name: "Video call" }),
).toBeVisible();
await brooks.page.getByRole("button", { name: "Video call" }).click();
await brooks.page.getByRole("menuitem", { name: "Element Call" }).click();
await expect(
brooks.page.getByRole("menuitem", { name: "Element Call" }),
).toBeVisible();
await expect(
brooks.page.locator('iframe[title="Element Call"]'),
).toBeVisible();
await brooks.page.getByRole("menuitem", { name: "Element Call" }).click();
await expect(
brooks.page
const brooksFrame = brooks.page
.locator('iframe[title="Element Call"]')
).toBeVisible();
.contentFrame();
const brooksFrame = brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame();
// We should show a ringing overlay, let's check for that
await expect(
brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`),
).toBeVisible();
// We should show a ringing overlay, let's check for that
await expect(brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`)).toBeVisible();
await expect(whistler.page.getByText("Incoming video call")).toBeVisible();
await whistler.page.getByRole("button", { name: "Accept" }).click();
await expect(
whistler.page.locator('iframe[title="Element Call"]'),
).toBeVisible();
await expect(whistler.page.getByText('Incoming video call')).toBeVisible();
await whistler.page.getByRole('button', { name: 'Accept' }).click();
await expect(
whistler.page
const whistlerFrame = whistler.page
.locator('iframe[title="Element Call"]')
).toBeVisible();
.contentFrame();
const whistlerFrame = whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame();
// ASSERT the button states for whistler (the callee)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = whistlerFrame.getByTestId("incall_videomute");
// video should be on by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/);
// ASSERT the button states for whistler (the callee)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = whistlerFrame.getByTestId('incall_videomute');
// video should be on by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/);
const audioButton = whistlerFrame.getByTestId("incall_mute");
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute(
"aria-label",
/^Mute microphone$/,
);
}
// ASSERT the button states for brools (the caller)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = brooksFrame.getByTestId("incall_videomute");
// video should be on by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/);
const audioButton = whistlerFrame.getByTestId('incall_mute');
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/);
}
const audioButton = brooksFrame.getByTestId("incall_mute");
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute(
"aria-label",
/^Mute microphone$/,
);
}
// ASSERT the button states for brools (the caller)
{
// The only way to know if it is muted or not is to look at the data-kind attribute..
const videoButton = brooksFrame.getByTestId('incall_videomute');
// video should be on by default in a voice call
await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/);
// In order to confirm that the call is disconnected we will check that the message composer is shown again.
// So first we need to confirm that it is hidden when in the call.
await expect(
whistler.page.locator(".mx_BasicMessageComposer"),
).not.toBeVisible();
await expect(
brooks.page.locator(".mx_BasicMessageComposer"),
).not.toBeVisible();
// ASSERT hanging up on one side ends the call for both
{
const hangupButton = brooksFrame.getByTestId("incall_leave");
await hangupButton.click();
}
const audioButton = brooksFrame.getByTestId('incall_mute');
// audio should be on for the voice call
await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/);
}
// In order to confirm that the call is disconnected we will check that the message composer is shown again.
// So first we need to confirm that it is hidden when in the call.
await expect(whistler.page.locator(".mx_BasicMessageComposer")).not.toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).not.toBeVisible();
// ASSERT hanging up on one side ends the call for both
{
const hangupButton = brooksFrame.getByTestId('incall_leave');
await hangupButton.click();
}
// The widget should be closed on both sides and the timeline should be back on screen
await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible();
});
// The widget should be closed on both sides and the timeline should be back on screen
await expect(
whistler.page.locator(".mx_BasicMessageComposer"),
).toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible();
},
);

View File

@@ -99,7 +99,10 @@ export async function createMatrixRTCSdk(
if (room === null) throw Error("could not get room from client");
const mediaDevices = new MediaDevices(scope);
const muteStates = new MuteStates(scope, mediaDevices, { audioEnabled: true, videoEnabled: true });
const muteStates = new MuteStates(scope, mediaDevices, {
audioEnabled: true,
videoEnabled: true,
});
const slot = { application, id };
const rtcSession = new MatrixRTCSession(
client,

View File

@@ -252,10 +252,7 @@ export interface UrlConfiguration {
// the situations that call for this behavior ('isEmbedded'). This makes it
// clearer what each flag means, and helps us avoid coupling Element Call's
// behavior to the needs of specific consumers.
export interface UrlParams
extends
UrlProperties,
UrlConfiguration {}
export interface UrlParams extends UrlProperties, UrlConfiguration {}
// This is here as a stopgap, but what would be far nicer is a function that
// takes a UrlParams and returns a query string. That would enable us to

View File

@@ -71,7 +71,17 @@ export const RoomPage: FC = () => {
useEffect(() => {
const scope = new ObservableScope();
setMuteStates(new MuteStates(scope, devices, calculateInitialMuteState(urlParams, import.meta.env.VITE_PACKAGE, window.location.hostname)));
setMuteStates(
new MuteStates(
scope,
devices,
calculateInitialMuteState(
urlParams,
import.meta.env.VITE_PACKAGE,
window.location.hostname,
),
),
);
return (): void => scope.end();
}, [devices, urlParams]);

View File

@@ -48,12 +48,7 @@ describe("MuteState", () => {
select(): void {},
} as unknown as MediaDevice<DeviceLabel, SelectedDevice>;
const muteState = new MuteState(
testScope,
deviceStub,
true,
forceMute$,
);
const muteState = new MuteState(testScope, deviceStub, true, forceMute$);
let lastEnabled: boolean = false;
muteState.enabled$.subscribe((enabled) => {
lastEnabled = enabled;
@@ -162,14 +157,10 @@ describe("MuteStates", () => {
videoInput: aVideoInput(),
// other devices are not relevant for this test
});
const muteStates = new MuteStates(
testScope,
mediaDevices,
{
audioEnabled: false,
videoEnabled: false,
}
);
const muteStates = new MuteStates(testScope, mediaDevices, {
audioEnabled: false,
videoEnabled: false,
});
let latestSyncedState: boolean | null = null;
muteStates.video.setHandler(async (enabled: boolean): Promise<boolean> => {

View File

@@ -10,7 +10,6 @@ import { type RTCCallIntent } from "matrix-js-sdk/lib/matrixrtc";
import { calculateInitialMuteState } from "./initialMuteState";
test.each<{
callIntent: RTCCallIntent;
packageType: "full" | "embedded";
@@ -69,7 +68,6 @@ test.each<{
},
);
test.each<{
isDevBuild: boolean;
currentHost: string;
@@ -78,11 +76,14 @@ test.each<{
{ isDevBuild: true, currentHost: "localhost", expectedEnabled: true },
{ isDevBuild: false, currentHost: "localhost", expectedEnabled: false },
{ isDevBuild: true, currentHost: "call.example.com", expectedEnabled: false },
{ isDevBuild: false, currentHost: "call.example.com", expectedEnabled: false },
])
("Should trust localhost domain when in dev mode isDevBuild($isDevBuild) host($currentHost)", (
{isDevBuild, currentHost, expectedEnabled}
) => {
{
isDevBuild: false,
currentHost: "call.example.com",
expectedEnabled: false,
},
])(
"Should trust localhost domain when in dev mode isDevBuild($isDevBuild) host($currentHost)",
({ isDevBuild, currentHost, expectedEnabled }) => {
const { audioEnabled, videoEnabled } = calculateInitialMuteState(
{ skipLobby: true, callIntent: "video" },
"full",
@@ -92,4 +93,5 @@ test.each<{
expect(audioEnabled).toBe(expectedEnabled);
expect(videoEnabled).toBe(expectedEnabled);
});
},
);

View File

@@ -525,5 +525,8 @@ export function mockMuteStates(
joined$: Observable<boolean> = of(true),
): MuteStates {
const observableScope = new ObservableScope();
return new MuteStates(observableScope, mockMediaDevices({}), { audioEnabled: false, videoEnabled: false });
return new MuteStates(observableScope, mockMediaDevices({}), {
audioEnabled: false,
videoEnabled: false,
});
}