Files
TOJE2E/pages/SubmitPage.ts
ChenKaiLiuG e139daa410 Initialize
2026-01-29 11:48:45 +08:00

111 lines
3.1 KiB
TypeScript

import { Page, Locator, expect } from '@playwright/test';
/**
* Page Object Model for Problem Submission page
* URL: /submit/{id}
*/
export class SubmitPage {
readonly page: Page;
readonly compilerSelect: Locator;
readonly codeTextarea: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
// Submit form elements
this.compilerSelect = page.locator('select[name="compiler"], #compiler-select, select').first();
this.codeTextarea = page.locator('textarea[name="code"], textarea#code, .CodeMirror textarea, textarea').first();
this.submitButton = page.locator('button:has-text("提交"), button:has-text("Submit"), input[type="submit"]').first();
this.errorMessage = page.locator('.error, .alert-danger, [class*="error"]');
}
/**
* Navigate to submit page for a specific problem
*/
async goto(problemId: number) {
await this.page.goto(`/submit/${problemId}`);
await this.page.waitForLoadState('networkidle');
}
/**
* Select a compiler
*/
async selectCompiler(compiler: string) {
await this.compilerSelect.selectOption({ label: compiler });
}
/**
* Fill in the code
* Note: This might need adjustment if the site uses CodeMirror or Monaco editor
*/
async fillCode(code: string) {
// Check if CodeMirror is being used
const codeMirror = this.page.locator('.CodeMirror');
if (await codeMirror.count() > 0) {
// CodeMirror editor - need to use execCommand
await codeMirror.click();
await this.page.evaluate((codeText) => {
const cm = (window as any).CodeMirror;
if (cm && cm.instances && cm.instances.length > 0) {
cm.instances[0].setValue(codeText);
}
}, code);
} else {
// Regular textarea
await this.codeTextarea.fill(code);
}
}
/**
* Submit the code
*/
async submit() {
await this.submitButton.click();
// Wait for navigation or response
try {
await this.page.waitForLoadState('networkidle', { timeout: 5000 });
} catch (e) {
// Ignore timeout if page doesn't navigate
}
}
/**
* Submit code with compiler selection
*/
async submitCode(compiler: string, code: string) {
await this.selectCompiler(compiler);
await this.fillCode(code);
await this.submit();
}
/**
* Verify we are on the submit page
*/
async verifyOnPage(problemId: number) {
await expect(this.page).toHaveURL(new RegExp(`/submit/${problemId}`));
}
/**
* Check if there's an error message
*/
async getErrorMessage(): Promise<string | null> {
if (await this.errorMessage.isVisible()) {
return await this.errorMessage.textContent();
}
return null;
}
/**
* Wait for submission cooldown message to disappear
*/
async waitForCooldown(timeoutMs: number = 31000) {
const cooldownMessage = this.page.locator('text=/冷卻|cooldown|請稍候/i');
if (await cooldownMessage.isVisible()) {
await cooldownMessage.waitFor({ state: 'hidden', timeout: timeoutMs });
}
}
}