Wire viewer-frontend Vitest into Gitea Actions, centralize DEV base URLs in env-defaults.json, expand playkit API catalog specs, and land auth/mail flows plus verify-email public-host redirect and idle-logout e2e hooks.
39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
import { type Page } from '@playwright/test';
|
|
import { BasePage } from '@levkin/playkit';
|
|
|
|
export class LoginPage extends BasePage {
|
|
constructor(page: Page, baseUrl: string) {
|
|
super(page, baseUrl);
|
|
}
|
|
|
|
async openLogin(): Promise<void> {
|
|
await this.open('/login');
|
|
await this.page.waitForLoadState('domcontentloaded');
|
|
await this.page.locator('#email').waitFor({ state: 'visible' });
|
|
// Wait for client bundle / React hydration (native GET submit otherwise)
|
|
await this.page.waitForFunction(() => {
|
|
const form = document.querySelector('form');
|
|
const btn = document.querySelector('button[type="submit"]');
|
|
return !!form && !!btn && !!(window as unknown as { next?: unknown }).next;
|
|
}).catch(() => undefined);
|
|
await this.page.waitForTimeout(600);
|
|
}
|
|
|
|
async signIn(email: string, password: string): Promise<void> {
|
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
await this.fill(this.page.locator('#email'), email);
|
|
await this.fill(this.page.locator('#password'), password);
|
|
await this.page.waitForTimeout(250 * (attempt + 1));
|
|
await this.click(this.page.getByRole('button', { name: /Sign in/i }));
|
|
await this.page.waitForTimeout(400);
|
|
// Native GET fallback leaks credentials into the query string — retry.
|
|
if (!this.page.url().includes('password=')) {
|
|
return;
|
|
}
|
|
this.log.warn('login GET fallback detected; retrying after re-open', { attempt });
|
|
await this.openLogin();
|
|
}
|
|
throw new Error('Login form submitted as GET (page not hydrated)');
|
|
}
|
|
}
|