diff --git a/frontend/e2e/auth.spec.ts b/frontend/e2e/auth.spec.ts index dbb0e67..1c62eb5 100644 --- a/frontend/e2e/auth.spec.ts +++ b/frontend/e2e/auth.spec.ts @@ -1,15 +1,10 @@ -import { test, expect, AuthHelper, TEST_CREDENTIALS, TIMEOUTS } from './fixtures/auth'; -import { TestHelpers } from './utils/test-helpers'; +import { test, expect, TIMEOUTS } from './fixtures/auth'; +import { E2ETestAuthHelper } from './utils/test-auth-helper'; test.describe('Authentication', () => { - test.beforeEach(async ({ page }) => { - const authHelper = new AuthHelper(page); - await authHelper.ensureLoggedOut(); - }); - test('should display login form on initial visit', async ({ page }) => { await page.goto('/'); - + // Check for login form elements using Material-UI structure await expect(page.locator('input[type="text"]').first()).toBeVisible(); await expect(page.locator('input[type="password"]').first()).toBeVisible(); @@ -17,67 +12,71 @@ test.describe('Authentication', () => { }); test('should login with valid credentials', async ({ page }) => { - const authHelper = new AuthHelper(page); - - await authHelper.loginAs(TEST_CREDENTIALS.admin); - + // Create a dynamic test user via API + const authHelper = new E2ETestAuthHelper(page); + const testUser = await authHelper.createTestUser(); + + // Login with the dynamically created user + const loginSuccess = await authHelper.loginUser(testUser.credentials); + expect(loginSuccess).toBe(true); + // Should redirect to dashboard await page.waitForURL(/.*\/dashboard.*/, { timeout: TIMEOUTS.navigation }); - + // Verify we're logged in by checking for welcome message await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible(); }); test('should show error with invalid credentials', async ({ page }) => { await page.goto('/'); - + await page.fill('input[type="text"]', 'invaliduser'); await page.fill('input[type="password"]', 'wrongpassword'); - + await page.click('button[type="submit"]'); - + // Should show error message (Material-UI Alert) await expect(page.locator('.MuiAlert-root, [role="alert"]')).toBeVisible({ timeout: TIMEOUTS.api }); - + // Should remain on login page await expect(page.locator('input[type="text"]')).toBeVisible(); }); test.skip('should logout successfully', async ({ page }) => { - const authHelper = new AuthHelper(page); - - // First login - await authHelper.loginAs(TEST_CREDENTIALS.admin); - + // Create and login with a dynamic test user + const authHelper = new E2ETestAuthHelper(page); + const testUser = await authHelper.createTestUser(); + await authHelper.loginUser(testUser.credentials); + await page.waitForURL(/\/dashboard|\//, { timeout: TIMEOUTS.navigation }); - + // Find and click profile/account button in the top app bar (has AccountIcon) const profileButton = page.locator('button:has([data-testid="AccountCircleIcon"])'); await profileButton.click(); - + // Wait for profile menu to open and click logout const logoutMenuItem = page.locator('li[role="menuitem"]:has-text("Logout")'); await logoutMenuItem.click(); - + // Should redirect back to login await page.waitForURL(/\/login|\//, { timeout: TIMEOUTS.navigation }); await expect(page.locator('input[name="username"]')).toBeVisible(); }); test.skip('should persist session on page reload', async ({ page }) => { - const authHelper = new AuthHelper(page); - - // Login first - await authHelper.loginAs(TEST_CREDENTIALS.admin); - + // Create and login with a dynamic test user + const authHelper = new E2ETestAuthHelper(page); + const testUser = await authHelper.createTestUser(); + await authHelper.loginUser(testUser.credentials); + await page.waitForURL(/\/dashboard|\//, { timeout: TIMEOUTS.navigation }); - + // Reload the page await page.reload(); - + // Wait for page to load after reload await page.waitForLoadState('networkidle'); - + // Should still be logged in (either on dashboard or main page, but not login) await page.waitForURL(/\/dashboard|\/(?!login)/, { timeout: TIMEOUTS.navigation }); await expect(page.locator('input[name="username"]')).not.toBeVisible(); @@ -85,16 +84,16 @@ test.describe('Authentication', () => { test('should validate required fields', async ({ page }) => { await page.goto('/'); - + // Try to submit without filling fields await page.click('button[type="submit"]'); - + // Should show validation errors or prevent submission const usernameInput = page.locator('input[type="text"]'); const passwordInput = page.locator('input[type="password"]'); - + // Check for HTML5 validation or custom validation messages await expect(usernameInput).toBeVisible(); await expect(passwordInput).toBeVisible(); }); -}); \ No newline at end of file +}); diff --git a/frontend/e2e/dashboard.spec.ts b/frontend/e2e/dashboard.spec.ts index caf19d3..d0f7dc0 100644 --- a/frontend/e2e/dashboard.spec.ts +++ b/frontend/e2e/dashboard.spec.ts @@ -1,23 +1,22 @@ import { test, expect } from './fixtures/auth'; -import { TEST_CREDENTIALS } from './fixtures/auth'; test.describe('Dashboard', () => { - test('should display welcome back message after login', async ({ authenticatedPage: page }) => { + test('should display welcome back message after login', async ({ dynamicAdminPage: page, testAdmin }) => { // Navigate to dashboard await page.goto('/dashboard'); await page.waitForLoadState('networkidle'); - + // Check for welcome message await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible(); - + // Check for username in welcome message - await expect(page.locator(`h4:has-text("Welcome back, ${TEST_CREDENTIALS.admin.username}!")`)).toBeVisible(); + await expect(page.locator(`h4:has-text("Welcome back, ${testAdmin.credentials.username}!")`)).toBeVisible(); }); - test('should display dashboard stats', async ({ authenticatedPage: page }) => { + test('should display dashboard stats', async ({ dynamicAdminPage: page }) => { await page.goto('/dashboard'); await page.waitForLoadState('networkidle'); - + // Check for stats cards await expect(page.locator('text="Total Documents"')).toBeVisible(); await expect(page.locator('text="Storage Used"')).toBeVisible(); @@ -25,17 +24,17 @@ test.describe('Dashboard', () => { await expect(page.locator('text="Searchable"')).toBeVisible(); }); - test('should display quick actions', async ({ authenticatedPage: page }) => { + test('should display quick actions', async ({ dynamicAdminPage: page }) => { await page.goto('/dashboard'); await page.waitForLoadState('networkidle'); - + // Check for quick action buttons await expect(page.locator('text="Upload Documents"')).toBeVisible(); await expect(page.locator('text="Search Library"')).toBeVisible(); await expect(page.locator('text="Browse Documents"')).toBeVisible(); }); - test('should have working navigation', async ({ authenticatedPage: page }) => { + test('should have working navigation', async ({ dynamicAdminPage: page }) => { await page.goto('/dashboard'); await page.waitForLoadState('networkidle'); diff --git a/frontend/e2e/debug-upload.spec.ts b/frontend/e2e/debug-upload.spec.ts index ecc378e..432d9c8 100644 --- a/frontend/e2e/debug-upload.spec.ts +++ b/frontend/e2e/debug-upload.spec.ts @@ -5,13 +5,13 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Debug Upload', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); - await authenticatedPage.goto('/upload'); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); + await dynamicAdminPage.goto('/upload'); await helpers.waitForLoadingToComplete(); }); - test('should debug upload workflow', async ({ authenticatedPage: page }) => { + test('should debug upload workflow', async ({ dynamicAdminPage: page }) => { console.log('Starting upload debug test...'); // Find file input diff --git a/frontend/e2e/document-management.spec.ts b/frontend/e2e/document-management.spec.ts index 33ba328..828d9f9 100644 --- a/frontend/e2e/document-management.spec.ts +++ b/frontend/e2e/document-management.spec.ts @@ -5,12 +5,12 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Document Management', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/documents'); }); - test('should display document list', async ({ authenticatedPage: page }) => { + test('should display document list', async ({ dynamicAdminPage: page }) => { // The documents page should be visible with title and description // Use more flexible selectors for headings - based on artifact, it's h4 const documentsHeading = page.locator('h4:has-text("Documents")'); @@ -86,7 +86,7 @@ test.describe('Document Management', () => { console.log('Document list page test completed successfully'); }); - test.skip('should navigate to document details', async ({ authenticatedPage: page }) => { + test.skip('should navigate to document details', async ({ dynamicAdminPage: page }) => { // Click on first document if available const firstDocument = page.locator('.MuiCard-root').first(); @@ -103,7 +103,7 @@ test.describe('Document Management', () => { } }); - test.skip('should display document metadata', async ({ authenticatedPage: page }) => { + test.skip('should display document metadata', async ({ dynamicAdminPage: page }) => { const firstDocument = page.locator('.MuiCard-root').first(); if (await firstDocument.isVisible()) { @@ -117,7 +117,7 @@ test.describe('Document Management', () => { } }); - test.skip('should allow document download', async ({ authenticatedPage: page }) => { + test.skip('should allow document download', async ({ dynamicAdminPage: page }) => { const firstDocument = page.locator('[data-testid="document-item"], .document-item, .document-card').first(); if (await firstDocument.isVisible()) { @@ -139,7 +139,7 @@ test.describe('Document Management', () => { } }); - test.skip('should allow document deletion', async ({ authenticatedPage: page }) => { + test.skip('should allow document deletion', async ({ dynamicAdminPage: page }) => { const firstDocument = page.locator('[data-testid="document-item"], .document-item, .document-card').first(); if (await firstDocument.isVisible()) { @@ -163,7 +163,7 @@ test.describe('Document Management', () => { } }); - test.skip('should filter documents by type', async ({ authenticatedPage: page }) => { + test.skip('should filter documents by type', async ({ dynamicAdminPage: page }) => { // Look for filter controls const filterDropdown = page.locator('[data-testid="type-filter"], select[name="type"], .type-filter'); if (await filterDropdown.isVisible()) { @@ -180,7 +180,7 @@ test.describe('Document Management', () => { } }); - test.skip('should sort documents', async ({ authenticatedPage: page }) => { + test.skip('should sort documents', async ({ dynamicAdminPage: page }) => { const sortDropdown = page.locator('[data-testid="sort"], select[name="sort"], .sort-dropdown'); if (await sortDropdown.isVisible()) { await sortDropdown.selectOption('date-desc'); @@ -192,7 +192,7 @@ test.describe('Document Management', () => { } }); - test.skip('should display OCR status', async ({ authenticatedPage: page }) => { + test.skip('should display OCR status', async ({ dynamicAdminPage: page }) => { const firstDocument = page.locator('.MuiCard-root').first(); if (await firstDocument.isVisible()) { @@ -207,7 +207,7 @@ test.describe('Document Management', () => { } }); - test.skip('should search within document content', async ({ authenticatedPage: page }) => { + test.skip('should search within document content', async ({ dynamicAdminPage: page }) => { const firstDocument = page.locator('.MuiCard-root').first(); if (await firstDocument.isVisible()) { @@ -230,7 +230,7 @@ test.describe('Document Management', () => { } }); - test.skip('should paginate document list', async ({ authenticatedPage: page }) => { + test.skip('should paginate document list', async ({ dynamicAdminPage: page }) => { // Look for pagination controls const nextPageButton = page.locator('[data-testid="next-page"], button:has-text("Next"), .pagination-next'); if (await nextPageButton.isVisible()) { @@ -246,7 +246,7 @@ test.describe('Document Management', () => { } }); - test('should show document thumbnails'.skip, async ({ authenticatedPage: page }) => { + test('should show document thumbnails'.skip, async ({ dynamicAdminPage: page }) => { // Check for document thumbnails in list view const documentThumbnails = page.locator('[data-testid="document-thumbnail"], .thumbnail, .document-preview'); if (await documentThumbnails.first().isVisible()) { diff --git a/frontend/e2e/fixtures/auth.ts b/frontend/e2e/fixtures/auth.ts index 718fedd..b21ce8b 100644 --- a/frontend/e2e/fixtures/auth.ts +++ b/frontend/e2e/fixtures/auth.ts @@ -2,18 +2,6 @@ import { test as base, expect } from '@playwright/test'; import type { Page } from '@playwright/test'; import { E2ETestAuthHelper, type E2ETestUser, type TestCredentials } from '../utils/test-auth-helper'; -// Legacy credentials for backward compatibility (still available for seeded admin user) -export const TEST_CREDENTIALS = { - admin: { - username: 'admin', - password: 'readur2024' - }, - user: { - username: 'user', - password: 'userpass123' - } -} as const; - export const TIMEOUTS = { login: 15000, navigation: 15000, @@ -21,174 +9,14 @@ export const TIMEOUTS = { } as const; export interface AuthFixture { - authenticatedPage: Page; - adminPage: Page; - userPage: Page; dynamicAdminPage: Page; dynamicUserPage: Page; testUser: E2ETestUser; testAdmin: E2ETestUser; } -// Shared authentication helper functions -export class AuthHelper { - constructor(private page: Page) {} - - async loginAs(credentials: typeof TEST_CREDENTIALS.admin | typeof TEST_CREDENTIALS.user) { - console.log(`Attempting to login as ${credentials.username}...`); - - // Go to home page and wait for it to load - await this.page.goto('/'); - await this.page.waitForLoadState('networkidle'); - - // Check if already logged in by looking for dashboard content - const welcomeText = await this.page.locator('h4:has-text("Welcome back,")').isVisible().catch(() => false); - - if (welcomeText) { - console.log('Already logged in - found welcome message'); - return; - } - - // Wait for login page to be ready - look for the distinctive login page content - await this.page.waitForSelector('h3:has-text("Welcome to Readur")', { timeout: TIMEOUTS.login }); - await this.page.waitForSelector('h5:has-text("Sign in to your account")', { timeout: TIMEOUTS.login }); - - // Material-UI creates input elements inside TextFields, but we need to wait for them to be ready - // The inputs have the name attributes from react-hook-form register - const usernameField = this.page.locator('input[name="username"]'); - const passwordField = this.page.locator('input[name="password"]'); - - // Wait for both fields to be attached and visible - await usernameField.waitFor({ state: 'attached', timeout: TIMEOUTS.login }); - await passwordField.waitFor({ state: 'attached', timeout: TIMEOUTS.login }); - - // WebKit can be slower - add extra wait time - const browserName = await this.page.evaluate(() => navigator.userAgent); - const isWebKit = browserName.includes('WebKit') && !browserName.includes('Chrome'); - if (isWebKit) { - console.log('WebKit browser detected - adding extra wait time'); - await this.page.waitForTimeout(5000); - } - - // Clear any existing content and fill the fields - await usernameField.clear(); - await usernameField.fill(credentials.username); - - await passwordField.clear(); - await passwordField.fill(credentials.password); - - // WebKit needs extra time for form validation - if (isWebKit) { - await this.page.waitForTimeout(3000); - } - - // Click submit button - look for the sign in button specifically - const signInButton = this.page.locator('button[type="submit"]:has-text("Sign in")'); - await signInButton.waitFor({ state: 'visible', timeout: TIMEOUTS.login }); - - if (isWebKit) { - // WebKit-specific approach: don't wait for API response, just click and wait for navigation - await signInButton.click(); - - // WebKit needs more time before checking navigation - await this.page.waitForTimeout(2000); - - // Wait for navigation with longer timeout for WebKit - await this.page.waitForURL(/.*\/dashboard.*/, { timeout: 25000 }); - console.log(`Successfully navigated to: ${this.page.url()}`); - - // Wait for dashboard content to load with extra time for WebKit - await this.page.waitForFunction(() => { - return document.querySelector('h4') !== null && - (document.querySelector('h4')?.textContent?.includes('Welcome') || - document.querySelector('[role="main"]') !== null); - }, { timeout: 20000 }); - - } else { - // Standard approach for other browsers - const loginPromise = this.page.waitForResponse(response => - response.url().includes('/auth/login') && response.status() === 200, - { timeout: TIMEOUTS.login } - ); - - await signInButton.click(); - - try { - const response = await loginPromise; - - // Wait for navigation to dashboard with more flexible URL pattern - await this.page.waitForURL(/.*\/dashboard.*/, { timeout: TIMEOUTS.navigation }); - console.log(`Successfully navigated to: ${this.page.url()}`); - - // Wait for dashboard content to load - be more flexible about the welcome message - await this.page.waitForFunction(() => { - return document.querySelector('h4') !== null && - (document.querySelector('h4')?.textContent?.includes('Welcome') || - document.querySelector('[role="main"]') !== null); - }, { timeout: TIMEOUTS.navigation }); - - } catch (error) { - // Take a screenshot for debugging - await this.page.screenshot({ - path: `test-results/login-failure-${credentials.username}-${Date.now()}.png`, - fullPage: true - }); - throw error; - } - } - } - - async logout() { - // Look for logout button/link and click it - const logoutButton = this.page.locator('[data-testid="logout"], button:has-text("Logout"), a:has-text("Logout")').first(); - - if (await logoutButton.isVisible()) { - await logoutButton.click(); - - // Wait for redirect to login page - await this.page.waitForFunction(() => - window.location.pathname.includes('/login') || window.location.pathname === '/', - { timeout: TIMEOUTS.navigation } - ); - } - } - - async ensureLoggedOut() { - await this.page.goto('/'); - await this.page.waitForLoadState('networkidle'); - - // If we see a login form, we're already logged out - const usernameInput = await this.page.locator('input[name="username"]').isVisible().catch(() => false); - if (usernameInput) { - return; - } - - // Otherwise, try to logout - await this.logout(); - } -} - export const test = base.extend({ - // Legacy fixtures using seeded users (for backward compatibility) - authenticatedPage: async ({ page }, use) => { - const auth = new AuthHelper(page); - await auth.loginAs(TEST_CREDENTIALS.admin); - await use(page); - }, - - adminPage: async ({ page }, use) => { - const auth = new AuthHelper(page); - await auth.loginAs(TEST_CREDENTIALS.admin); - await use(page); - }, - - userPage: async ({ page }, use) => { - const auth = new AuthHelper(page); - await auth.loginAs(TEST_CREDENTIALS.admin); // Use admin since 'user' doesn't exist - await use(page); - }, - - // New dynamic fixtures using API-created users + // Dynamic fixtures using API-created users testUser: async ({ page }, use) => { const authHelper = new E2ETestAuthHelper(page); const testUser = await authHelper.createTestUser(); diff --git a/frontend/e2e/navigation.spec.ts b/frontend/e2e/navigation.spec.ts index b899ff1..9ff6b77 100644 --- a/frontend/e2e/navigation.spec.ts +++ b/frontend/e2e/navigation.spec.ts @@ -4,11 +4,11 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Navigation', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); }); - test('should check available routes after login', async ({ authenticatedPage: page }) => { + test('should check available routes after login', async ({ dynamicAdminPage: page }) => { // Check current URL after login console.log('Current URL after login:', page.url()); @@ -50,7 +50,7 @@ test.describe('Navigation', () => { } }); - test('should check what elements are on dashboard', async ({ authenticatedPage: page }) => { + test('should check what elements are on dashboard', async ({ dynamicAdminPage: page }) => { await page.goto('/dashboard'); await page.waitForLoadState('networkidle', { timeout: 5000 }); diff --git a/frontend/e2e/ocr-retry-workflow.spec.ts b/frontend/e2e/ocr-retry-workflow.spec.ts index 43cd144..5a3e598 100644 --- a/frontend/e2e/ocr-retry-workflow.spec.ts +++ b/frontend/e2e/ocr-retry-workflow.spec.ts @@ -5,12 +5,12 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('OCR Retry Workflow', () => { let helpers: TestHelpers; - test.beforeEach(async ({ adminPage }) => { - helpers = new TestHelpers(adminPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/documents'); }); - test('should display failed OCR documents', async ({ adminPage: page }) => { + test('should display failed OCR documents', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); @@ -38,7 +38,7 @@ test.describe('OCR Retry Workflow', () => { } }); - test('should retry individual failed OCR document', async ({ adminPage: page }) => { + test('should retry individual failed OCR document', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); @@ -76,7 +76,7 @@ test.describe('OCR Retry Workflow', () => { } }); - test('should bulk retry multiple failed OCR documents', async ({ adminPage: page }) => { + test('should bulk retry multiple failed OCR documents', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); @@ -130,7 +130,7 @@ test.describe('OCR Retry Workflow', () => { } }); - test('should show OCR retry history', async ({ adminPage: page }) => { + test('should show OCR retry history', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); @@ -153,7 +153,7 @@ test.describe('OCR Retry Workflow', () => { } }); - test('should display OCR failure reasons', async ({ adminPage: page }) => { + test('should display OCR failure reasons', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); @@ -185,7 +185,7 @@ test.describe('OCR Retry Workflow', () => { } }); - test('should filter failed documents by failure type', async ({ adminPage: page }) => { + test('should filter failed documents by failure type', async ({ dynamicAdminPage: page }) => { await page.goto('/documents'); await helpers.waitForLoadingToComplete(); diff --git a/frontend/e2e/search.spec.ts b/frontend/e2e/search.spec.ts index 9ecbc81..28ac53a 100644 --- a/frontend/e2e/search.spec.ts +++ b/frontend/e2e/search.spec.ts @@ -5,20 +5,20 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Search Functionality', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/search'); // Ensure we have test documents for search functionality await helpers.ensureTestDocumentsExist(); }); - test.skip('should display search interface', async ({ authenticatedPage: page }) => { + test.skip('should display search interface', async ({ dynamicAdminPage: page }) => { // Check for search components await expect(page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]')).toBeVisible(); await expect(page.locator('button:has-text("Search"), [data-testid="search-button"]')).toBeVisible(); }); - test.skip('should perform basic search', async ({ authenticatedPage: page }) => { + test.skip('should perform basic search', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Search for known OCR content from test images @@ -39,7 +39,7 @@ test.describe('Search Functionality', () => { }); }); - test.skip('should show search suggestions', async ({ authenticatedPage: page }) => { + test.skip('should show search suggestions', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Start typing "Test" to trigger suggestions based on OCR content @@ -51,7 +51,7 @@ test.describe('Search Functionality', () => { }); }); - test.skip('should filter search results', async ({ authenticatedPage: page }) => { + test.skip('should filter search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Search for content that should match multiple test images @@ -76,7 +76,7 @@ test.describe('Search Functionality', () => { } }); - test.skip('should perform advanced search', async ({ authenticatedPage: page }) => { + test.skip('should perform advanced search', async ({ dynamicAdminPage: page }) => { // Look for advanced search toggle const advancedToggle = page.locator('[data-testid="advanced-search"], button:has-text("Advanced"), .advanced-toggle'); @@ -103,7 +103,7 @@ test.describe('Search Functionality', () => { } }); - test.skip('should handle empty search results', async ({ authenticatedPage: page }) => { + test.skip('should handle empty search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Search for something that doesn't exist @@ -118,7 +118,7 @@ test.describe('Search Functionality', () => { }); }); - test.skip('should navigate to document from search results', async ({ authenticatedPage: page }) => { + test.skip('should navigate to document from search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search @@ -137,7 +137,7 @@ test.describe('Search Functionality', () => { } }); - test.skip('should preserve search state on page reload', async ({ authenticatedPage: page }) => { + test.skip('should preserve search state on page reload', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search @@ -156,7 +156,7 @@ test.describe('Search Functionality', () => { }); }); - test.skip('should sort search results', async ({ authenticatedPage: page }) => { + test.skip('should sort search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search @@ -175,7 +175,7 @@ test.describe('Search Functionality', () => { } }); - test.skip('should paginate search results', async ({ authenticatedPage: page }) => { + test.skip('should paginate search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search @@ -197,7 +197,7 @@ test.describe('Search Functionality', () => { } }); - test.skip('should highlight search terms in results', async ({ authenticatedPage: page }) => { + test.skip('should highlight search terms in results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search with specific term @@ -212,7 +212,7 @@ test.describe('Search Functionality', () => { }); }); - test.skip('should clear search results', async ({ authenticatedPage: page }) => { + test.skip('should clear search results', async ({ dynamicAdminPage: page }) => { const searchInput = page.locator('input[type="search"], input[placeholder*="search" i], [data-testid="search-input"]').first(); // Perform search diff --git a/frontend/e2e/settings.spec.ts b/frontend/e2e/settings.spec.ts index 506939b..4eb6910 100644 --- a/frontend/e2e/settings.spec.ts +++ b/frontend/e2e/settings.spec.ts @@ -5,17 +5,17 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Settings Management', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/settings'); }); - test.skip('should display settings interface', async ({ authenticatedPage: page }) => { + test.skip('should display settings interface', async ({ dynamicAdminPage: page }) => { // Check for settings page components await expect(page.locator('[data-testid="settings-container"], .settings-page, .settings-form')).toBeVisible(); }); - test('should update OCR settings', async ({ authenticatedPage: page }) => { + test('should update OCR settings', async ({ dynamicAdminPage: page }) => { // Look for OCR settings section const ocrSection = page.locator('[data-testid="ocr-settings"], .ocr-section, .settings-section:has-text("OCR")'); if (await ocrSection.isVisible()) { @@ -35,7 +35,7 @@ test.describe('Settings Management', () => { } }); - test('should update watch folder settings', async ({ authenticatedPage: page }) => { + test('should update watch folder settings', async ({ dynamicAdminPage: page }) => { // Navigate to watch folder section if it's a separate page const watchFolderNav = page.locator('a[href="/watch-folder"], [data-testid="watch-folder-nav"]'); if (await watchFolderNav.isVisible()) { @@ -67,7 +67,7 @@ test.describe('Settings Management', () => { } }); - test('should update notification settings', async ({ authenticatedPage: page }) => { + test('should update notification settings', async ({ dynamicAdminPage: page }) => { const notificationSection = page.locator('[data-testid="notification-settings"], .notification-section, .settings-section:has-text("Notification")'); if (await notificationSection.isVisible()) { // Enable notifications @@ -96,7 +96,7 @@ test.describe('Settings Management', () => { } }); - test('should update search settings', async ({ authenticatedPage: page }) => { + test('should update search settings', async ({ dynamicAdminPage: page }) => { const searchSection = page.locator('[data-testid="search-settings"], .search-section, .settings-section:has-text("Search")'); if (await searchSection.isVisible()) { // Configure search results per page @@ -120,7 +120,7 @@ test.describe('Settings Management', () => { } }); - test('should reset settings to defaults', async ({ authenticatedPage: page }) => { + test('should reset settings to defaults', async ({ dynamicAdminPage: page }) => { // Look for reset button const resetButton = page.locator('button:has-text("Reset"), button:has-text("Default"), [data-testid="reset-settings"]'); if (await resetButton.isVisible()) { @@ -142,7 +142,7 @@ test.describe('Settings Management', () => { } }); - test('should validate settings before saving', async ({ authenticatedPage: page }) => { + test('should validate settings before saving', async ({ dynamicAdminPage: page }) => { // Try to set invalid values const pathInput = page.locator('input[name="watchPath"], [data-testid="watch-path"]'); if (await pathInput.isVisible()) { @@ -159,7 +159,7 @@ test.describe('Settings Management', () => { } }); - test('should export settings', async ({ authenticatedPage: page }) => { + test('should export settings', async ({ dynamicAdminPage: page }) => { const exportButton = page.locator('button:has-text("Export"), [data-testid="export-settings"]'); if (await exportButton.isVisible()) { // Set up download listener @@ -173,7 +173,7 @@ test.describe('Settings Management', () => { } }); - test('should import settings', async ({ authenticatedPage: page }) => { + test('should import settings', async ({ dynamicAdminPage: page }) => { const importButton = page.locator('button:has-text("Import"), [data-testid="import-settings"]'); if (await importButton.isVisible()) { // Look for file input @@ -202,7 +202,7 @@ test.describe('Settings Management', () => { } }); - test('should display current system status', async ({ authenticatedPage: page }) => { + test('should display current system status', async ({ dynamicAdminPage: page }) => { // Look for system status section const statusSection = page.locator('[data-testid="system-status"], .status-section, .settings-section:has-text("Status")'); if (await statusSection.isVisible()) { @@ -211,7 +211,7 @@ test.describe('Settings Management', () => { } }); - test('should test OCR functionality', async ({ authenticatedPage: page }) => { + test('should test OCR functionality', async ({ dynamicAdminPage: page }) => { const ocrSection = page.locator('[data-testid="ocr-settings"], .ocr-section'); if (await ocrSection.isVisible()) { const testButton = page.locator('button:has-text("Test OCR"), [data-testid="test-ocr"]'); @@ -228,7 +228,7 @@ test.describe('Settings Management', () => { } }); - test('should clear cache', async ({ authenticatedPage: page }) => { + test('should clear cache', async ({ dynamicAdminPage: page }) => { const clearCacheButton = page.locator('button:has-text("Clear Cache"), [data-testid="clear-cache"]'); if (await clearCacheButton.isVisible()) { const clearResponse = helpers.waitForApiCall('/api/cache/clear'); @@ -240,7 +240,7 @@ test.describe('Settings Management', () => { } }); - test('should update user profile', async ({ authenticatedPage: page }) => { + test('should update user profile', async ({ dynamicAdminPage: page }) => { // Look for user profile section const profileSection = page.locator('[data-testid="profile-settings"], .profile-section, .settings-section:has-text("Profile")'); if (await profileSection.isVisible()) { @@ -265,7 +265,7 @@ test.describe('Settings Management', () => { } }); - test('should change password', async ({ authenticatedPage: page }) => { + test('should change password', async ({ dynamicAdminPage: page }) => { const passwordSection = page.locator('[data-testid="password-settings"], .password-section, .settings-section:has-text("Password")'); if (await passwordSection.isVisible()) { await page.fill('input[name="currentPassword"], [data-testid="current-password"]', 'currentpass'); diff --git a/frontend/e2e/sources.spec.ts b/frontend/e2e/sources.spec.ts index 2ec96d0..81faff4 100644 --- a/frontend/e2e/sources.spec.ts +++ b/frontend/e2e/sources.spec.ts @@ -5,18 +5,18 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('Source Management', () => { let helpers: TestHelpers; - test.beforeEach(async ({ adminPage }) => { - helpers = new TestHelpers(adminPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/sources'); }); - test.skip('should display sources interface', async ({ adminPage: page }) => { + test.skip('should display sources interface', async ({ dynamicAdminPage: page }) => { // Check for sources page components await expect(page.locator('[data-testid="sources-list"], .sources-list, .sources-container')).toBeVisible(); await expect(page.locator('button:has-text("Add Source"), [data-testid="add-source"]')).toBeVisible(); }); - test.skip('should create a new local folder source', async ({ adminPage: page }) => { + test.skip('should create a new local folder source', async ({ dynamicAdminPage: page }) => { // Click add source button await page.click('button:has-text("Add Source"), [data-testid="add-source"]'); @@ -51,7 +51,7 @@ test.describe('Source Management', () => { await expect(page.locator(':has-text("Test Local Folder")')).toBeVisible({ timeout: TIMEOUTS.medium }); }); - test.skip('should create a new WebDAV source', async ({ adminPage: page }) => { + test.skip('should create a new WebDAV source', async ({ dynamicAdminPage: page }) => { await page.click('button:has-text("Add Source"), [data-testid="add-source"]'); await expect(page.locator('[data-testid="add-source-form"], .add-source-modal, .source-form')).toBeVisible(); @@ -79,7 +79,7 @@ test.describe('Source Management', () => { await expect(page.locator(':has-text("Test WebDAV")')).toBeVisible({ timeout: TIMEOUTS.medium }); }); - test.skip('should create a new S3 source', async ({ adminPage: page }) => { + test.skip('should create a new S3 source', async ({ dynamicAdminPage: page }) => { await page.click('button:has-text("Add Source"), [data-testid="add-source"]'); await expect(page.locator('[data-testid="add-source-form"], .add-source-modal, .source-form')).toBeVisible(); @@ -108,7 +108,7 @@ test.describe('Source Management', () => { await expect(page.locator(':has-text("Test S3 Bucket")')).toBeVisible({ timeout: TIMEOUTS.medium }); }); - test('should edit existing source', async ({ adminPage: page }) => { + test('should edit existing source', async ({ dynamicAdminPage: page }) => { // Look for existing source to edit const firstSource = page.locator('[data-testid="source-item"], .source-item, .source-card').first(); @@ -138,7 +138,7 @@ test.describe('Source Management', () => { } }); - test('should delete source', async ({ adminPage: page }) => { + test('should delete source', async ({ dynamicAdminPage: page }) => { // First wait for sources list to load await helpers.waitForLoadingToComplete(); @@ -298,7 +298,7 @@ test.describe('Source Management', () => { } }); - test.skip('should start source sync', async ({ adminPage: page }) => { + test.skip('should start source sync', async ({ dynamicAdminPage: page }) => { const firstSource = page.locator('[data-testid="source-item"], .source-item, .source-card').first(); if (await firstSource.isVisible()) { @@ -319,7 +319,7 @@ test.describe('Source Management', () => { } }); - test('should stop source sync', async ({ adminPage: page }) => { + test('should stop source sync', async ({ dynamicAdminPage: page }) => { const firstSource = page.locator('[data-testid="source-item"], .source-item, .source-card').first(); if (await firstSource.isVisible()) { @@ -347,7 +347,7 @@ test.describe('Source Management', () => { } }); - test('should display source status and statistics', async ({ adminPage: page }) => { + test('should display source status and statistics', async ({ dynamicAdminPage: page }) => { // First wait for sources list to load await helpers.waitForLoadingToComplete(); @@ -420,7 +420,7 @@ test.describe('Source Management', () => { } }); - test.skip('should test source connection', async ({ adminPage: page }) => { + test.skip('should test source connection', async ({ dynamicAdminPage: page }) => { await page.click('button:has-text("Add Source"), [data-testid="add-source"]'); await expect(page.locator('[data-testid="add-source-form"], .add-source-modal')).toBeVisible(); @@ -451,7 +451,7 @@ test.describe('Source Management', () => { } }); - test('should filter sources by type', async ({ adminPage: page }) => { + test('should filter sources by type', async ({ dynamicAdminPage: page }) => { // Look for filter dropdown const filterDropdown = page.locator('[data-testid="source-filter"], select[name="filter"], .source-filter'); if (await filterDropdown.isVisible()) { @@ -467,7 +467,7 @@ test.describe('Source Management', () => { } }); - test('should display sync history', async ({ adminPage: page }) => { + test('should display sync history', async ({ dynamicAdminPage: page }) => { const firstSource = page.locator('[data-testid="source-item"], .source-item, .source-card').first(); if (await firstSource.isVisible()) { @@ -482,7 +482,7 @@ test.describe('Source Management', () => { } }); - test.skip('should validate required fields in source creation', async ({ adminPage: page }) => { + test.skip('should validate required fields in source creation', async ({ dynamicAdminPage: page }) => { await page.click('button:has-text("Add Source"), [data-testid="add-source"]'); await expect(page.locator('[data-testid="add-source-form"], .add-source-modal')).toBeVisible(); @@ -501,7 +501,7 @@ test.describe('Source Management', () => { } }); - test('should schedule automatic sync', async ({ adminPage: page }) => { + test('should schedule automatic sync', async ({ dynamicAdminPage: page }) => { // First wait for sources list to load await helpers.waitForLoadingToComplete(); diff --git a/frontend/e2e/utils/test-auth-helper.ts b/frontend/e2e/utils/test-auth-helper.ts index f1d10a0..2cf49b2 100644 --- a/frontend/e2e/utils/test-auth-helper.ts +++ b/frontend/e2e/utils/test-auth-helper.ts @@ -57,23 +57,7 @@ export class E2ETestAuthHelper { if (!response.ok()) { const errorText = await response.text(); - console.warn(`Warning: Failed to create dynamic test user. Status: ${response.status()}, Body: ${errorText}`); - - // Fallback to seeded admin user (since no regular user is seeded) - console.log('Falling back to seeded admin user...'); - return { - credentials: { - username: 'admin', - email: 'admin@test.com', - password: 'readur2024' - }, - userResponse: { - id: 'seeded-admin', - username: 'admin', - email: 'admin@test.com', - role: 'Admin' - } - }; + throw new Error(`Failed to create dynamic test user. Status: ${response.status()}, Body: ${errorText}`); } const userResponse: TestUserResponse = await response.json(); @@ -84,22 +68,7 @@ export class E2ETestAuthHelper { }; } catch (error) { console.error('❌ Failed to create E2E test user:', error); - - // Fallback to seeded admin user (since no regular user is seeded) - console.log('Falling back to seeded admin user due to error...'); - return { - credentials: { - username: 'admin', - email: 'admin@test.com', - password: 'readur2024' - }, - userResponse: { - id: 'seeded-admin', - username: 'admin', - email: 'admin@test.com', - role: 'Admin' - } - }; + throw error; } } @@ -129,23 +98,7 @@ export class E2ETestAuthHelper { if (!response.ok()) { const errorText = await response.text(); - console.warn(`Warning: Failed to create dynamic admin user. Status: ${response.status()}, Body: ${errorText}`); - - // Fallback to seeded admin user - console.log('Falling back to seeded admin user...'); - return { - credentials: { - username: 'admin', - email: 'admin@test.com', - password: 'readur2024' - }, - userResponse: { - id: 'seeded-admin', - username: 'admin', - email: 'admin@test.com', - role: 'Admin' - } - }; + throw new Error(`Failed to create dynamic admin user. Status: ${response.status()}, Body: ${errorText}`); } const userResponse: TestUserResponse = await response.json(); @@ -156,22 +109,7 @@ export class E2ETestAuthHelper { }; } catch (error) { console.error('❌ Failed to create E2E admin user:', error); - - // Fallback to seeded admin user - console.log('Falling back to seeded admin user due to error...'); - return { - credentials: { - username: 'admin', - email: 'admin@test.com', - password: 'readur2024' - }, - userResponse: { - id: 'seeded-admin', - username: 'admin', - email: 'admin@test.com', - role: 'Admin' - } - }; + throw error; } } diff --git a/frontend/e2e/utils/test-data.ts b/frontend/e2e/utils/test-data.ts index eaa362c..e958941 100644 --- a/frontend/e2e/utils/test-data.ts +++ b/frontend/e2e/utils/test-data.ts @@ -1,7 +1,6 @@ -import { TEST_CREDENTIALS } from '../fixtures/auth'; - +// Test users are now created dynamically via E2ETestAuthHelper +// Invalid credentials for testing error cases export const TEST_USERS = { - valid: TEST_CREDENTIALS.admin, invalid: { username: 'invaliduser', password: 'wrongpassword' diff --git a/frontend/e2e/webdav-workflow-dynamic.spec.ts b/frontend/e2e/webdav-workflow-dynamic.spec.ts index 35c0e21..8589bd3 100644 --- a/frontend/e2e/webdav-workflow-dynamic.spec.ts +++ b/frontend/e2e/webdav-workflow-dynamic.spec.ts @@ -5,12 +5,12 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('WebDAV Workflow (Dynamic Auth)', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/sources'); }); - test.skip('should create and configure WebDAV source with dynamic admin', async ({ authenticatedPage: page }) => { + test.skip('should create and configure WebDAV source with dynamic admin', async ({ dynamicAdminPage: page }) => { // Increase timeout for this test as WebDAV operations can be slow test.setTimeout(60000); @@ -352,7 +352,7 @@ test.describe('WebDAV Workflow (Dynamic Auth)', () => { console.log('✅ WebDAV source creation test completed by authenticated admin'); }); - test('should test WebDAV connection with dynamic admin', async ({ authenticatedPage: page }) => { + test('should test WebDAV connection with dynamic admin', async ({ dynamicAdminPage: page }) => { console.log('Testing WebDAV connection with authenticated admin'); // This test assumes a WebDAV source exists from the previous test or setup diff --git a/frontend/e2e/webdav-workflow.spec.ts b/frontend/e2e/webdav-workflow.spec.ts index fefb911..ca8d11e 100644 --- a/frontend/e2e/webdav-workflow.spec.ts +++ b/frontend/e2e/webdav-workflow.spec.ts @@ -5,12 +5,12 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('WebDAV Workflow', () => { let helpers: TestHelpers; - test.beforeEach(async ({ authenticatedPage }) => { - helpers = new TestHelpers(authenticatedPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/sources'); }); - test.skip('should create and configure WebDAV source', async ({ authenticatedPage: page }) => { + test.skip('should create and configure WebDAV source', async ({ dynamicAdminPage: page }) => { // Increase timeout for this test as WebDAV operations can be slow // This addresses the timeout issues with Material-UI Select components test.setTimeout(60000); @@ -223,7 +223,7 @@ test.describe('WebDAV Workflow', () => { } }); - test('should test WebDAV connection', async ({ authenticatedPage: page }) => { + test('should test WebDAV connection', async ({ dynamicAdminPage: page }) => { // This test assumes a WebDAV source exists from the previous test or setup await page.goto('/sources'); await helpers.waitForLoadingToComplete(); @@ -256,7 +256,7 @@ test.describe('WebDAV Workflow', () => { } }); - test('should initiate WebDAV sync', async ({ authenticatedPage: page }) => { + test('should initiate WebDAV sync', async ({ dynamicAdminPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); @@ -287,7 +287,7 @@ test.describe('WebDAV Workflow', () => { } }); - test('should show WebDAV sync history', async ({ authenticatedPage: page }) => { + test('should show WebDAV sync history', async ({ dynamicAdminPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); @@ -310,7 +310,7 @@ test.describe('WebDAV Workflow', () => { } }); - test('should handle WebDAV source deletion', async ({ authenticatedPage: page }) => { + test('should handle WebDAV source deletion', async ({ dynamicAdminPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); diff --git a/frontend/e2e/websocket-sync-progress.spec.ts b/frontend/e2e/websocket-sync-progress.spec.ts index 41d9ec9..ce6f882 100644 --- a/frontend/e2e/websocket-sync-progress.spec.ts +++ b/frontend/e2e/websocket-sync-progress.spec.ts @@ -5,8 +5,8 @@ import { TestHelpers } from './utils/test-helpers'; test.describe('WebSocket Sync Progress', () => { let helpers: TestHelpers; - test.beforeEach(async ({ adminPage }) => { - helpers = new TestHelpers(adminPage); + test.beforeEach(async ({ dynamicAdminPage }) => { + helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/sources'); }); @@ -99,7 +99,7 @@ test.describe('WebSocket Sync Progress', () => { return fallbackElement; } - test('should establish WebSocket connection for sync progress', async ({ adminPage: page }) => { + test('should establish WebSocket connection for sync progress', async ({ dynamicAdminPage: page }) => { // Add browser console logging to debug WebSocket connections const consoleLogs: string[] = []; page.on('console', msg => { @@ -177,7 +177,7 @@ test.describe('WebSocket Sync Progress', () => { await expect(progressIndicators).toBeVisible({ timeout: TIMEOUTS.short }); }); - test('should handle WebSocket connection errors gracefully', async ({ adminPage: page }) => { + test('should handle WebSocket connection errors gracefully', async ({ dynamicAdminPage: page }) => { // Mock WebSocket connection failure await page.route('**/sync/progress/ws**', route => { route.abort('connectionrefused'); @@ -215,7 +215,7 @@ test.describe('WebSocket Sync Progress', () => { } }); - test('should automatically reconnect on WebSocket disconnection', async ({ adminPage: page }) => { + test('should automatically reconnect on WebSocket disconnection', async ({ dynamicAdminPage: page }) => { // Create and sync a source const sourceName = await helpers.createTestSource('Reconnect Test Source', 'webdav'); @@ -266,7 +266,7 @@ test.describe('WebSocket Sync Progress', () => { await expect(finalStatus).toBeVisible({ timeout: TIMEOUTS.medium }); }); - test('should display real-time progress updates via WebSocket', async ({ adminPage: page }) => { + test('should display real-time progress updates via WebSocket', async ({ dynamicAdminPage: page }) => { // Create a source and start sync const sourceName = await helpers.createTestSource('Progress Updates Test', 'webdav'); @@ -303,7 +303,7 @@ test.describe('WebSocket Sync Progress', () => { await expect(statsLocator).toBeVisible({ timeout: TIMEOUTS.short }); }); - test('should handle multiple concurrent WebSocket connections', async ({ adminPage: page }) => { + test('should handle multiple concurrent WebSocket connections', async ({ dynamicAdminPage: page }) => { // Create multiple sources const sourceNames = []; const baseNames = ['Multi Source 1', 'Multi Source 2']; @@ -370,7 +370,7 @@ test.describe('WebSocket Sync Progress', () => { console.log('Multiple concurrent WebSocket test completed - infrastructure verified'); }); - test('should authenticate WebSocket connection with JWT token', async ({ adminPage: page }) => { + test('should authenticate WebSocket connection with JWT token', async ({ dynamicAdminPage: page }) => { // Check that user has a valid JWT token stored const tokenInfo = await page.evaluate(() => { const token = localStorage.getItem('token'); @@ -403,7 +403,7 @@ test.describe('WebSocket Sync Progress', () => { console.log('WebSocket authentication test passed - connection established successfully'); }); - test('should handle WebSocket authentication failures', async ({ adminPage: page }) => { + test('should handle WebSocket authentication failures', async ({ dynamicAdminPage: page }) => { // Mock authentication failure for WebSocket connections await page.route('**/sync/progress/ws**', route => { if (route.request().url().includes('token=')) { @@ -476,7 +476,7 @@ test.describe('WebSocket Sync Progress', () => { } }); - test('should properly clean up WebSocket connections on component unmount', async ({ adminPage: page }) => { + test('should properly clean up WebSocket connections on component unmount', async ({ dynamicAdminPage: page }) => { // Instead of creating a new source, just use existing sources to test component lifecycle // This avoids the hanging issue with source creation @@ -514,7 +514,7 @@ test.describe('WebSocket Sync Progress', () => { console.log('WebSocket cleanup test completed - component lifecycle verified via reload'); }); - test('should handle WebSocket message parsing errors', async ({ adminPage: page }) => { + test('should handle WebSocket message parsing errors', async ({ dynamicAdminPage: page }) => { // Mock WebSocket with malformed messages await page.addInitScript(() => { const originalWebSocket = window.WebSocket; @@ -561,7 +561,7 @@ test.describe('WebSocket Sync Progress', () => { await expect(page.locator('body')).toBeVisible(); }); - test('should display WebSocket connection status indicators', async ({ adminPage: page }) => { + test('should display WebSocket connection status indicators', async ({ dynamicAdminPage: page }) => { // Create and sync a source const sourceName = await helpers.createTestSource('Status Test Source', 'webdav'); @@ -586,7 +586,7 @@ test.describe('WebSocket Sync Progress', () => { await expect(statusChip).toHaveClass(/MuiChip-root/); }); - test('should support WebSocket connection health monitoring', async ({ adminPage: page }) => { + test('should support WebSocket connection health monitoring', async ({ dynamicAdminPage: page }) => { // This test verifies that the WebSocket connection monitors connection health let heartbeatReceived = false; @@ -651,7 +651,7 @@ test.describe('WebSocket Sync Progress - Cross-browser Compatibility', () => { await syncCard.click(); } - test('should work in different browser engines', async ({ adminPage: page }) => { + test('should work in different browser engines', async ({ dynamicAdminPage: page }) => { // This test would run across different browsers (Chrome, Firefox, Safari) // The test framework should handle this automatically