mirror of https://github.com/OpenVidu/openvidu.git
114 lines
4.7 KiB
TypeScript
114 lines
4.7 KiB
TypeScript
|
|
import { expect, test } from '../fixtures/api.js';
|
||
|
|
|
||
|
|
test.describe('signed out', () => {
|
||
|
|
test.use({ apiOptions: { signedIn: false } });
|
||
|
|
|
||
|
|
test('a protected route sends to the login with the URL to return to', async ({ page, api }) => {
|
||
|
|
await page.goto('/settings?tab=about');
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/login?redirect=%2Fsettings%3Ftab%3Dabout');
|
||
|
|
await expect(page.getByText('CE', { exact: true })).toBeVisible();
|
||
|
|
await expect(page.getByText('3.10.0', { exact: true })).toBeVisible();
|
||
|
|
|
||
|
|
await page.getByLabel('Username').fill('admin');
|
||
|
|
await page.getByLabel('Password', { exact: true }).fill('secret');
|
||
|
|
await page.getByLabel('Password', { exact: true }).press('Enter');
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/settings?tab=about');
|
||
|
|
expect(api.calls()).toContain('POST auth/login');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('an unknown path while signed out returns to it after the login', async ({ page }) => {
|
||
|
|
await page.goto('/nowhere');
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/login?redirect=%2Fnowhere');
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('with wrong credentials', () => {
|
||
|
|
test.use({ apiOptions: { signedIn: false, login: 'invalid' } });
|
||
|
|
|
||
|
|
test('shows the error, clears the password and focuses the username', async ({ page }) => {
|
||
|
|
await page.goto('/login');
|
||
|
|
await page.getByLabel('Username').fill('admin');
|
||
|
|
await page.getByLabel('Password', { exact: true }).fill('wrong');
|
||
|
|
await page.getByRole('button', { name: 'Sign in' }).click();
|
||
|
|
|
||
|
|
await expect(page.getByRole('alert')).toHaveText('Invalid username or password');
|
||
|
|
await expect(page.getByLabel('Password', { exact: true })).toHaveValue('');
|
||
|
|
await expect(page.getByLabel('Username')).toBeFocused();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('when rate limited', () => {
|
||
|
|
test.use({ apiOptions: { signedIn: false, login: 'rate-limited', retryAfter: 2 } });
|
||
|
|
|
||
|
|
test('counts down and enables the form again', async ({ page }) => {
|
||
|
|
await page.goto('/login');
|
||
|
|
await page.getByLabel('Username').fill('admin');
|
||
|
|
await page.getByLabel('Password', { exact: true }).fill('secret');
|
||
|
|
await page.getByRole('button', { name: 'Sign in' }).click();
|
||
|
|
|
||
|
|
await expect(page.getByRole('alert')).toHaveText('Too many attempts, try again in 2 s');
|
||
|
|
await expect(page.getByRole('button', { name: 'Sign in' })).toBeDisabled();
|
||
|
|
await expect(page.getByRole('alert')).toHaveText('Too many attempts, try again in 1 s');
|
||
|
|
await expect(page.getByRole('button', { name: 'Sign in' })).toBeEnabled({ timeout: 5_000 });
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('when the server is unreachable', () => {
|
||
|
|
test.use({ apiOptions: { signedIn: false, login: 'unreachable' } });
|
||
|
|
|
||
|
|
test('shows a banner with retry', async ({ page }) => {
|
||
|
|
await page.goto('/login');
|
||
|
|
await page.getByLabel('Username').fill('admin');
|
||
|
|
await page.getByLabel('Password', { exact: true }).fill('secret');
|
||
|
|
await page.getByRole('button', { name: 'Sign in' }).click();
|
||
|
|
|
||
|
|
await expect(page.getByText('The server is unreachable.')).toBeVisible();
|
||
|
|
await expect(page.getByRole('button', { name: 'Retry' })).toBeVisible();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a reload restores the session silently', async ({ page, api }) => {
|
||
|
|
await page.goto('/settings');
|
||
|
|
await expect(page.getByRole('heading', { level: 1, name: 'Settings' })).toBeVisible();
|
||
|
|
|
||
|
|
await page.reload();
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/settings');
|
||
|
|
await expect(page.getByRole('heading', { level: 1, name: 'Settings' })).toBeVisible();
|
||
|
|
expect(api.calls().filter((call) => call === 'POST auth/refresh')).toHaveLength(2);
|
||
|
|
expect(api.calls()).not.toContain('POST auth/login');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('an expired token is refreshed once and the requests are replayed', async ({ page, api }) => {
|
||
|
|
await page.goto('/overview');
|
||
|
|
await expect(page.getByRole('heading', { level: 1, name: 'Overview' })).toBeVisible();
|
||
|
|
|
||
|
|
const refreshes = api.calls().filter((call) => call === 'POST auth/refresh').length;
|
||
|
|
|
||
|
|
api.expireToken();
|
||
|
|
await page.getByRole('combobox', { name: 'Search' }).fill('dem');
|
||
|
|
|
||
|
|
await expect.poll(() => api.calls().filter((call) => call === 'GET rooms').length).toBe(2);
|
||
|
|
expect(api.calls().filter((call) => call === 'POST auth/refresh')).toHaveLength(refreshes + 1);
|
||
|
|
expect(api.calls().filter((call) => call === 'GET participants')).toHaveLength(2);
|
||
|
|
await expect(page).toHaveURL('/overview?tz=Europe%2FMadrid');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('sign out ends the session and shows the login without redirect', async ({ page, api }) => {
|
||
|
|
await page.goto('/rooms');
|
||
|
|
await page.getByRole('button', { name: 'User menu' }).click();
|
||
|
|
await page.getByRole('menuitem', { name: 'Sign out' }).click();
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/login');
|
||
|
|
expect(api.calls()).toContain('POST auth/logout');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('an authenticated user opening the login goes to the redirect target', async ({ page }) => {
|
||
|
|
await page.goto('/login?redirect=%2Fsettings');
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/settings');
|
||
|
|
});
|