91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
import { Page, Locator, expect } from '@playwright/test';
|
|
|
|
/**
|
|
* Page Object Model for Challenge List page
|
|
* URL: /chal
|
|
*/
|
|
export class ChallengeListPage {
|
|
readonly page: Page;
|
|
readonly challengeRows: Locator;
|
|
readonly accountFilter: Locator;
|
|
readonly problemFilter: Locator;
|
|
readonly stateFilter: Locator;
|
|
readonly compilerFilter: Locator;
|
|
|
|
constructor(page: Page) {
|
|
this.page = page;
|
|
|
|
// Challenge list elements
|
|
this.challengeRows = page.locator('tr[data-challenge-id], .challenge-row, tbody tr');
|
|
|
|
// Filter elements
|
|
this.accountFilter = page.locator('input[name="account"], #account-filter');
|
|
this.problemFilter = page.locator('input[name="problem"], #problem-filter');
|
|
this.stateFilter = page.locator('select[name="state"], #state-filter');
|
|
this.compilerFilter = page.locator('select[name="compiler"], #compiler-filter');
|
|
}
|
|
|
|
/**
|
|
* Navigate to the challenge list page
|
|
*/
|
|
async goto() {
|
|
await this.page.goto('/chal');
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
/**
|
|
* Get the latest challenge ID from the list
|
|
*/
|
|
async getLatestChallengeId(): Promise<number | null> {
|
|
// Look for challenge links in the format /chal/{id}
|
|
const firstChallengeLink = this.page.locator('a[href^="/chal/"]').first();
|
|
|
|
if (await firstChallengeLink.count() === 0) {
|
|
return null;
|
|
}
|
|
|
|
const href = await firstChallengeLink.getAttribute('href');
|
|
if (!href) return null;
|
|
|
|
const match = href.match(/\/chal\/(\d+)/);
|
|
return match ? parseInt(match[1]) : null;
|
|
}
|
|
|
|
/**
|
|
* Click on a challenge to view details
|
|
*/
|
|
async clickChallenge(challengeId: number) {
|
|
await this.page.click(`a[href="/chal/${challengeId}"]`);
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
/**
|
|
* Filter challenges by account ID
|
|
*/
|
|
async filterByAccount(accountId: number) {
|
|
if (await this.accountFilter.isVisible()) {
|
|
await this.accountFilter.fill(accountId.toString());
|
|
await this.page.keyboard.press('Enter');
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter challenges by problem ID
|
|
*/
|
|
async filterByProblem(problemId: number) {
|
|
if (await this.problemFilter.isVisible()) {
|
|
await this.problemFilter.fill(problemId.toString());
|
|
await this.page.keyboard.press('Enter');
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify we are on the challenge list page
|
|
*/
|
|
async verifyOnPage() {
|
|
await expect(this.page).toHaveURL(/\/chal/);
|
|
}
|
|
}
|