2026-10-25 16:35:47 +01:00
|
|
|
import { expect, type Page, test } from '../fixtures/api.js';
|
|
|
|
|
import { expectNoViolations } from '../fixtures/axe.js';
|
|
|
|
|
import { ROOM_SUMMARY, ROOMS } from '../fixtures/rooms.js';
|
|
|
|
|
|
|
|
|
|
test.use({ apiOptions: { rooms: ROOMS, roomSummary: ROOM_SUMMARY } });
|
|
|
|
|
|
|
|
|
|
const PARTICIPANTS_NOW = 'Regular participants connected now. Egress, ingress and agents are not counted.';
|
|
|
|
|
|
|
|
|
|
function tooltip(page: Page) {
|
|
|
|
|
return page.locator('.mat-mdc-tooltip');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test('an info tip shows on hover without opening the list its tile links to', async ({ page }) => {
|
|
|
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
|
|
|
|
|
|
const tiles = page.getByRole('region', { name: 'Live' });
|
|
|
|
|
const tip = tiles.getByRole('button', { name: 'About Participants' });
|
|
|
|
|
|
|
|
|
|
await tip.hover();
|
|
|
|
|
await expect(tooltip(page)).toHaveText(PARTICIPANTS_NOW);
|
|
|
|
|
await tip.click();
|
|
|
|
|
await expect(page).toHaveURL(/\/overview/);
|
|
|
|
|
|
|
|
|
|
await tiles.getByRole('link', { name: 'Participants' }).click();
|
|
|
|
|
await expect(page).toHaveURL(/\/participants\?.*status=active/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('an info tip shows on keyboard focus and hides on Escape', async ({ page }) => {
|
|
|
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
|
// The pointer rests at the top-left corner, where the overlay renders the tooltip before positioning it: the
|
openvidu-dashboard: media node labels, and nothing about nodes in CE
The contract gains mediaNode on nodes, rooms and participants, stoppedAt on nodes and the
partial mediaNode index that replaces the nodeId one; the scenario's two servers are
labelled. The status reports the writer without node counts and with stoppedAt when the
server stopped, the rooms list filters by mediaNode, list items carry it, the overview
groups by it for editions and a node scope's media statistics coverage follows it.
CE renders nothing about nodes without per-node-breakdown: no nodes line, By node card,
Node select, scope selector or Node columns, not even locked; the Overview reads "Server
stopped at" for a stopped server. The generator gains --media-nodes, which node rollups
now require.
2026-11-04 12:13:58 +01:00
|
|
|
// mouseleave that follows would close a tooltip still opening, as on a slow runner. The page title has no tooltip.
|
|
|
|
|
const title = await page.getByRole('heading', { level: 1, name: 'Overview' }).boundingBox();
|
|
|
|
|
|
|
|
|
|
await page.mouse.move((title?.x ?? 0) + 4, (title?.y ?? 0) + 4);
|
2026-10-25 16:35:47 +01:00
|
|
|
|
|
|
|
|
const tiles = page.getByRole('region', { name: 'Live' });
|
|
|
|
|
|
|
|
|
|
await tiles.getByRole('link', { name: 'Participants' }).focus();
|
|
|
|
|
await page.keyboard.press('Tab');
|
|
|
|
|
await expect(tiles.getByRole('button', { name: 'About Participants' })).toBeFocused();
|
|
|
|
|
await expect(tooltip(page)).toHaveText(PARTICIPANTS_NOW);
|
|
|
|
|
await page.keyboard.press('Escape');
|
|
|
|
|
await expect(tooltip(page)).toHaveCount(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('a column info tip never sorts the table', async ({ page }) => {
|
|
|
|
|
await page.goto('/rooms?from=now-24h&to=now&tz=UTC');
|
|
|
|
|
|
|
|
|
|
const header = page.getByRole('columnheader', { name: /Unique identities/ });
|
|
|
|
|
|
|
|
|
|
await header.getByRole('button', { name: 'About Unique identities' }).click();
|
|
|
|
|
await expect(tooltip(page)).toHaveText(
|
|
|
|
|
'Distinct participant identities among those sessions: someone who joined three times counts once.'
|
|
|
|
|
);
|
|
|
|
|
await expect(page).not.toHaveURL(/sort=/);
|
|
|
|
|
await page.mouse.move(0, 0);
|
|
|
|
|
await expectNoViolations(page);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('Analytics explains its terms and has no PRO divider', async ({ page }) => {
|
|
|
|
|
await page.goto('/analytics?from=now-7d&to=now&tz=UTC');
|
|
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
|
page.getByRole('region', { name: 'Summary' }).getByRole('button', { name: 'About Participant sessions' })
|
|
|
|
|
).toBeVisible();
|
|
|
|
|
await expect(page.getByRole('separator')).toHaveCount(0);
|
|
|
|
|
await expect(page.getByText('PRO', { exact: true })).toHaveCount(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.describe('touch', () => {
|
|
|
|
|
test.use({ viewport: { width: 375, height: 800 }, hasTouch: true, isMobile: true });
|
|
|
|
|
|
|
|
|
|
test('a tap toggles an info tip', async ({ page }) => {
|
|
|
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
|
|
|
|
|
|
const tip = page.getByRole('region', { name: 'Live' }).getByRole('button', { name: 'About Participants' });
|
|
|
|
|
|
|
|
|
|
await tip.tap();
|
|
|
|
|
await expect(tooltip(page)).toHaveText(PARTICIPANTS_NOW);
|
|
|
|
|
await tip.tap();
|
|
|
|
|
await expect(tooltip(page)).toHaveCount(0);
|
|
|
|
|
});
|
|
|
|
|
});
|