Build ErsatzTV Image / CI toolchain image resolves (push) Successful in 11s
Build ErsatzTV Image / Delimiter ban (release path) (push) Successful in 25s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 9m9s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 6m41s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 6m23s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m23s
Co-authored-by: Timothy <timothy@noreply.gitea.tblindustries.be>
53 lines
2.4 KiB
TypeScript
53 lines
2.4 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test';
|
|
import { PASSWORD, USERNAME } from './credentials';
|
|
|
|
|
|
async function claimAndSignIn(page: Page) {
|
|
await page.goto('/app');
|
|
const setupUser = page.getByPlaceholder('Choose a username');
|
|
if (await setupUser.isVisible().catch(() => false)) {
|
|
await setupUser.fill(USERNAME);
|
|
await page.getByPlaceholder('Choose a password').fill(PASSWORD);
|
|
await page.getByPlaceholder('Re-enter the password').fill(PASSWORD);
|
|
} else {
|
|
await page.getByPlaceholder('Username', { exact: true }).fill(USERNAME);
|
|
await page.getByPlaceholder('Password', { exact: true }).fill(PASSWORD);
|
|
}
|
|
await page.getByRole('button', { name: /Create|Sign in/ }).first().click();
|
|
await expect(page.getByRole('button', { name: new RegExp(USERNAME) })).toBeVisible({ timeout: 15000 });
|
|
}
|
|
|
|
test('the readrate pacing fields render, validate and save', async ({ page }) => {
|
|
await claimAndSignIn(page);
|
|
await page.goto('/app/ffmpeg-profiles/1');
|
|
|
|
const readRate = page.getByLabel('Read rate', { exact: true });
|
|
const catchup = page.getByLabel('Read rate catchup', { exact: true });
|
|
|
|
await expect(readRate).toBeVisible({ timeout: 15000 });
|
|
await expect(catchup).toBeVisible();
|
|
|
|
// unset renders as an empty box showing the built-in default as a placeholder
|
|
await expect(readRate).toHaveValue('');
|
|
await expect(readRate).toHaveAttribute('placeholder', '1.05');
|
|
await expect(catchup).toHaveAttribute('placeholder', '6.0');
|
|
|
|
// the cross-field bound is enforced before the request leaves the browser: the screen surfaces
|
|
// it as a badge and disables Save
|
|
const save = page.getByRole('button', { name: 'Save profile' });
|
|
await catchup.fill('1');
|
|
await expect(page.getByText('Read rate catchup must be greater than the read rate (1.05)')).toBeVisible();
|
|
await expect(save).toBeDisabled();
|
|
|
|
// a valid pair saves and survives a reload through the read path
|
|
await readRate.fill('1.2');
|
|
await catchup.fill('4');
|
|
await expect(save).toBeEnabled();
|
|
await save.click();
|
|
// saving returns to the list, so re-enter the editor: that reload is the READ path
|
|
await expect(page.getByRole('button', { name: 'Save profile' })).toHaveCount(0, { timeout: 15000 });
|
|
await page.goto('/app/ffmpeg-profiles/1');
|
|
await expect(page.getByLabel('Read rate', { exact: true })).toHaveValue('1.2', { timeout: 15000 });
|
|
await expect(page.getByLabel('Read rate catchup', { exact: true })).toHaveValue('4');
|
|
});
|