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 { 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 }); } } }