/** * Moderation Queue Page Object Model * * Encapsulates interactions with the moderation queue. */ import { Page, expect } from '@playwright/test'; export class ModerationQueuePage { constructor(private page: Page) {} async goto() { await this.page.goto('/moderation/queue'); await this.page.waitForLoadState('networkidle'); } async claimSubmission(index: number = 0) { const claimButtons = this.page.locator('button:has-text("Claim")'); await claimButtons.nth(index).click(); // Wait for lock to be acquired await expect(this.page.getByText(/claimed by you/i)).toBeVisible({ timeout: 5000 }); } async approveSubmission(reason?: string) { // Click approve button await this.page.click('button:has-text("Approve")'); // Fill optional reason if provided if (reason) { await this.page.fill('textarea[placeholder*="reason"]', reason); } // Confirm in dialog await this.page.click('button:has-text("Confirm")'); // Wait for success toast await expect(this.page.getByText(/approved/i)).toBeVisible({ timeout: 10000 }); } async rejectSubmission(reason: string) { // Click reject button await this.page.click('button:has-text("Reject")'); // Fill required reason await this.page.fill('textarea[placeholder*="reason"]', reason); // Confirm in dialog await this.page.click('button:has-text("Confirm")'); // Wait for success toast await expect(this.page.getByText(/rejected/i)).toBeVisible({ timeout: 10000 }); } async extendLock() { await this.page.click('button:has-text("Extend")'); await expect(this.page.getByText(/extended/i)).toBeVisible({ timeout: 5000 }); } async releaseLock() { await this.page.click('button:has-text("Release")'); await expect(this.page.getByText(/released/i)).toBeVisible({ timeout: 5000 }); } async filterByType(type: string) { await this.page.selectOption('select[name="entity_type"]', type); await this.page.waitForLoadState('networkidle'); } async filterByStatus(status: string) { await this.page.selectOption('select[name="status"]', status); await this.page.waitForLoadState('networkidle'); } async searchBySubmitter(name: string) { await this.page.fill('input[placeholder*="submitter"]', name); await this.page.waitForTimeout(500); // Debounce await this.page.waitForLoadState('networkidle'); } async expectSubmissionVisible(submissionName: string) { await expect(this.page.getByText(submissionName)).toBeVisible(); } async expectSubmissionNotVisible(submissionName: string) { await expect(this.page.getByText(submissionName)).not.toBeVisible(); } async expectLockTimer() { // Check that lock timer is visible (e.g., "14:59 remaining") await expect(this.page.locator('[data-testid="lock-timer"]').or( this.page.getByText(/\d{1,2}:\d{2}.*remaining/i) )).toBeVisible(); } async expectLockWarning() { // Warning should appear at 2 minutes remaining await expect(this.page.getByText(/lock.*expir/i)).toBeVisible(); } }