snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
139
tests/pageobjects/VirtualBackgroundDialog.ts
Normal file
139
tests/pageobjects/VirtualBackgroundDialog.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import BaseDialog from './BaseDialog';
|
||||
|
||||
const VB_DIALOG_CONTAINER = '#virtual-background-dialog';
|
||||
const NONE_THUMBNAIL = '[aria-label="Remove background"]';
|
||||
const SLIGHT_BLUR_THUMBNAIL = '[aria-label="Half Blur"]';
|
||||
const BLUR_THUMBNAIL = '[aria-label="Blur"]';
|
||||
|
||||
/**
|
||||
* Page object for the Virtual Background tab inside the settings dialog.
|
||||
*/
|
||||
export default class VirtualBackgroundDialog extends BaseDialog {
|
||||
/**
|
||||
* Waits for the virtual background dialog container to be displayed.
|
||||
*/
|
||||
async waitForDisplay(): Promise<void> {
|
||||
await this.participant.driver.$(VB_DIALOG_CONTAINER).waitForDisplayed({
|
||||
timeout: 5000,
|
||||
timeoutMsg: 'Virtual background dialog not displayed'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the dialog container is currently displayed.
|
||||
*/
|
||||
isDisplayed(): Promise<boolean> {
|
||||
return this.participant.driver.$(VB_DIALOG_CONTAINER).isDisplayed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks a thumbnail and waits for it to become aria-checked.
|
||||
* Ensures React has finished re-rendering before the next click, preventing
|
||||
* rapid clicks from being swallowed during reconciliation.
|
||||
*
|
||||
* @param {string} selector - CSS selector for the thumbnail.
|
||||
* @param {string} label - Human-readable label for logging.
|
||||
*/
|
||||
private async clickAndWaitChecked(selector: string, label: string): Promise<void> {
|
||||
await this.participant.log(`VirtualBackgroundDialog: clicking ${label} thumbnail`);
|
||||
const el = this.participant.driver.$(selector);
|
||||
|
||||
await el.waitForClickable({ timeout: 3000, timeoutMsg: `${label} thumbnail not clickable` });
|
||||
|
||||
// Selecting an effect makes the preview (re)load the segmentation model/wasm, which
|
||||
// saturates the main thread. Two flaky failure modes follow from that:
|
||||
// 1. A click issued while React is mid-reconciliation (e.g. during rapid switching) is
|
||||
// dropped — the onClick handler never fires and the thumbnail never becomes checked.
|
||||
// 2. The first selection of a blur effect triggers a cold model/worker init that blocks
|
||||
// the main thread for several seconds, delaying the aria-checked re-render (and the
|
||||
// attribute reads themselves) well past a short timeout.
|
||||
// Re-issue the click on every poll until aria-checked confirms it landed (covers 1), and
|
||||
// allow a generous timeout for the cold-start re-render under load (covers 2). The poll
|
||||
// interval is kept large so a still-pending selection is not needlessly re-triggered.
|
||||
await this.participant.driver.waitUntil(
|
||||
async () => {
|
||||
if (await el.getAttribute('aria-checked') === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
await el.click();
|
||||
|
||||
return false;
|
||||
},
|
||||
{
|
||||
timeout: 15000,
|
||||
interval: 1500,
|
||||
timeoutMsg: `${label} thumbnail did not become checked after click`
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the "Remove background" (None) thumbnail.
|
||||
*/
|
||||
clickNone(): Promise<void> {
|
||||
return this.clickAndWaitChecked(NONE_THUMBNAIL, 'None');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the "Half Blur" (slight blur) thumbnail.
|
||||
*/
|
||||
clickSlightBlur(): Promise<void> {
|
||||
return this.clickAndWaitChecked(SLIGHT_BLUR_THUMBNAIL, 'Slight Blur');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the "Blur" (full blur) thumbnail.
|
||||
*/
|
||||
clickBlur(): Promise<void> {
|
||||
return this.clickAndWaitChecked(BLUR_THUMBNAIL, 'Blur');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given thumbnail element has aria-checked="true" (selected in the dialog).
|
||||
*
|
||||
* @param {string} selector - CSS selector for the thumbnail element.
|
||||
*/
|
||||
async isThumbnailChecked(selector: string): Promise<boolean> {
|
||||
const el = this.participant.driver.$(selector);
|
||||
|
||||
await el.waitForExist({ timeout: 2000 });
|
||||
|
||||
return (await el.getAttribute('aria-checked')) === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the None thumbnail is currently selected in the dialog.
|
||||
*/
|
||||
isNoneChecked(): Promise<boolean> {
|
||||
return this.isThumbnailChecked(NONE_THUMBNAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Slight Blur thumbnail is currently selected in the dialog.
|
||||
*/
|
||||
isSlightBlurChecked(): Promise<boolean> {
|
||||
return this.isThumbnailChecked(SLIGHT_BLUR_THUMBNAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Blur thumbnail is currently selected in the dialog.
|
||||
*/
|
||||
isBlurChecked(): Promise<boolean> {
|
||||
return this.isThumbnailChecked(BLUR_THUMBNAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks OK to apply the selected background and close the dialog.
|
||||
*/
|
||||
confirm(): Promise<void> {
|
||||
return this.clickOkButton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the X button to cancel without applying any changes.
|
||||
*/
|
||||
cancel(): Promise<void> {
|
||||
return this.clickCloseButton();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user