mirror of https://github.com/OpenVidu/openvidu.git
164 lines
6.4 KiB
TypeScript
164 lines
6.4 KiB
TypeScript
import { expect, type Page, test } from '../fixtures/api.js';
|
|
import { expectNoViolations } from '../fixtures/axe.js';
|
|
import { activeOverview, activeStatus, freshOverview, freshStatus } from '../fixtures/overview.js';
|
|
|
|
function card(page: Page, title: string) {
|
|
return page.locator('ovd-section-card').filter({ has: page.getByRole('heading', { level: 2, name: title }) });
|
|
}
|
|
|
|
test('the overview shows the live tiles with links, the hint, the status card and the recent rooms', async ({
|
|
page
|
|
}) => {
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
const tiles = page.getByRole('region', { name: 'Live' });
|
|
|
|
await expect(tiles).toContainText('Active rooms 12');
|
|
await expect(tiles).toContainText('Agents 2');
|
|
await expect(tiles).not.toContainText('Services');
|
|
await expect(page.locator('.page-header ovd-live-chip')).toHaveText('LIVE');
|
|
// The notice needs two responses in a row reporting stale entities.
|
|
await expect(page.getByText('may be stale')).toHaveCount(0);
|
|
await page.getByRole('button', { name: 'Refresh now' }).click();
|
|
await expect(page.getByRole('alert').filter({ hasText: 'may be stale' })).toContainText(
|
|
'1 active room and 4 participants have had no stats for over 90 s and may be stale'
|
|
);
|
|
await expect(card(page, 'Data pipeline')).toContainText(/Last batch at \d\d:\d\d:\d\d/);
|
|
await expect(card(page, 'Data pipeline')).toContainText(/\d+ of \d+ nodes? reporting/);
|
|
await expect(card(page, 'Data pipeline')).not.toContainText('schema');
|
|
await expect(card(page, 'Data pipeline')).not.toContainText('retention:');
|
|
await expect(card(page, 'Data pipeline').getByRole('link', { name: 'Storage and retention' })).toBeVisible();
|
|
await expect(card(page, 'Today (UTC, since 00:00)')).toContainText('143');
|
|
await expect(card(page, 'By node')).toContainText('Per-node breakdown is available in OpenVidu PRO');
|
|
|
|
const recent = card(page, 'Recent rooms');
|
|
|
|
await expect(recent.getByRole('link', { name: 'RM_ab12cd' })).toHaveAttribute('href', '/rooms/RM_ab12cd');
|
|
await expect(recent.getByRole('columnheader')).toHaveText([
|
|
'SID',
|
|
'Name',
|
|
'Status',
|
|
'Started',
|
|
'Duration',
|
|
'Unique identities'
|
|
]);
|
|
await expect(recent.locator('ovd-live-chip')).toHaveCount(0);
|
|
await expect(recent.locator('ovd-status-badge mat-icon.stale')).toHaveCount(1);
|
|
await expect(page.locator('main [title]')).toHaveCount(0);
|
|
expect(
|
|
await recent.getByRole('link', { name: 'RM_ab12cd' }).evaluate((link) => {
|
|
const titled: string[] = [];
|
|
|
|
for (let node: Element | null = link; node !== null; node = node.parentElement) {
|
|
if (node.hasAttribute('title')) {
|
|
titled.push(node.tagName);
|
|
}
|
|
}
|
|
|
|
return titled;
|
|
})
|
|
).toEqual([]);
|
|
await expectNoViolations(page);
|
|
|
|
await tiles.getByRole('link', { name: /Active rooms/ }).click();
|
|
await expect(page).toHaveURL(/\/rooms\?.*status=active/);
|
|
});
|
|
|
|
test.describe('a fresh deployment', () => {
|
|
test.use({ apiOptions: { overview: () => freshOverview(), status: () => freshStatus() } });
|
|
|
|
test('waits for the first events with every tile at zero and no error', async ({ page }) => {
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
await expect(page.getByText('Waiting for the first events')).toBeVisible();
|
|
await expect(page.getByRole('region', { name: 'Live' }).locator('ovd-kpi-tile .value')).toHaveText([
|
|
'0',
|
|
'0',
|
|
'0',
|
|
'0',
|
|
'0',
|
|
'0'
|
|
]);
|
|
await expect(card(page, 'Data pipeline')).toContainText('Last batch: never');
|
|
await expect(page.locator('ovd-error-banner')).toHaveCount(0);
|
|
});
|
|
});
|
|
|
|
test.describe('a silent writer', () => {
|
|
test.use({ apiOptions: { status: () => activeStatus(Date.now(), 3 * 60_000) } });
|
|
|
|
test('raises one dismissible banner on any page and turns the overview chip stale', async ({ page }) => {
|
|
await page.clock.install();
|
|
await page.goto('/rooms?tz=UTC');
|
|
|
|
// The banner needs two silent statuses in a row; the status is polled every 30 s.
|
|
await expect(page.getByRole('table', { name: 'Rooms' })).toBeVisible();
|
|
await expect(page.getByText(/No analytics data received/)).toHaveCount(0);
|
|
await page.clock.fastForward('00:31');
|
|
await expect(page.getByText(/No analytics data received for 3 min/)).toHaveCount(1);
|
|
await page
|
|
.getByRole('alert')
|
|
.filter({ hasText: 'No analytics data' })
|
|
.getByRole('button', { name: 'Dismiss' })
|
|
.click();
|
|
await expect(page.getByText('No analytics data received for 3 min')).toHaveCount(0);
|
|
|
|
await page.getByRole('navigation', { name: 'Main' }).getByRole('link', { name: 'Overview' }).click();
|
|
await expect(page.locator('.page-header ovd-live-chip')).toHaveText('stale');
|
|
await expect(card(page, 'Data pipeline')).toContainText('0 of 2 nodes reporting');
|
|
});
|
|
});
|
|
|
|
test.describe('a running migration', () => {
|
|
test.use({
|
|
apiOptions: {
|
|
status: () =>
|
|
activeStatus(Date.now(), 3 * 60_000, {
|
|
state: 'running',
|
|
progress: { processed: 400_000, total: 1_200_000 }
|
|
})
|
|
}
|
|
});
|
|
|
|
test('shows its progress in the banner and the card, without a writer banner', async ({ page }) => {
|
|
await page.goto('/overview?tz=UTC');
|
|
|
|
await expect(page.getByText(/Migration in progress: 400,000 \/ 1,200,000 records/)).toHaveCount(1);
|
|
await expect(card(page, 'Data pipeline')).toContainText('400,000 / 1,200,000 (33 %)');
|
|
await expect(page.getByText(/No analytics data received/)).toHaveCount(0);
|
|
});
|
|
});
|
|
|
|
test('the live chip reads paused once the auto-refresh is off, while the status poll goes on', async ({
|
|
page,
|
|
api
|
|
}) => {
|
|
await page.goto('/overview?tz=UTC');
|
|
await expect(page.locator('.page-header ovd-live-chip')).toHaveText('LIVE');
|
|
|
|
await page.getByRole('button', { name: /^Auto-refresh:/ }).click();
|
|
await page.getByRole('menuitemradio', { name: 'Off' }).click();
|
|
await expect(page.locator('.page-header ovd-live-chip')).toHaveText('paused');
|
|
expect(api.calls()).toContain('GET status');
|
|
await expectNoViolations(page);
|
|
});
|
|
|
|
test.describe('a quiet deployment', () => {
|
|
const body = activeOverview();
|
|
|
|
test.use({ apiOptions: { overview: () => body } });
|
|
|
|
test('keeps the values on 304 while the refresh advances', async ({ page, api }) => {
|
|
await page.goto('/overview?tz=UTC');
|
|
await expect(page.getByRole('region', { name: 'Live' })).toContainText('Active rooms 12');
|
|
|
|
const polls = () => api.requests.filter((request) => request.path === 'overview').length;
|
|
const before = polls();
|
|
|
|
await page.getByRole('button', { name: 'Refresh now' }).click();
|
|
await expect.poll(polls).toBeGreaterThan(before);
|
|
await expect(page.getByRole('region', { name: 'Live' })).toContainText('Active rooms 12');
|
|
await expect(page.locator('.highlight')).toHaveCount(0);
|
|
});
|
|
});
|