import { test, expect } from './fixtures/auth'; import { TIMEOUTS, API_ENDPOINTS } from './utils/test-data'; import { TestHelpers } from './utils/test-helpers'; test.describe('WebDAV Workflow (Dynamic Auth)', () => { let helpers: TestHelpers; test.beforeEach(async ({ dynamicAdminPage }) => { helpers = new TestHelpers(dynamicAdminPage); await helpers.navigateToPage('/sources'); }); 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); console.log('Running WebDAV test with authenticated admin'); // Navigate to sources page await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // Check if we can see the sources page (not stuck on login) const isOnLoginPage = await page.locator('h3:has-text("Welcome to Readur")').isVisible({ timeout: 2000 }); if (isOnLoginPage) { console.log('WARNING: Still on login page after navigation to sources'); // Try to wait for dashboard to appear or navigation to complete await page.waitForURL((url) => !url.pathname.includes('login'), { timeout: 10000 }).catch(() => { console.log('Failed to navigate away from login page'); }); // Check again const stillOnLogin = await page.locator('h3:has-text("Welcome to Readur")').isVisible({ timeout: 1000 }); if (stillOnLogin) { throw new Error('Test is stuck on login page - authentication failed'); } } // Wait for loading to complete and sources to be displayed // The Add Source button only appears after the loading state finishes await page.waitForLoadState('networkidle'); // Wait for the loading spinner to disappear const loadingSpinner = page.locator('[role="progressbar"], .MuiCircularProgress-root'); if (await loadingSpinner.isVisible({ timeout: 2000 })) { await expect(loadingSpinner).not.toBeVisible({ timeout: TIMEOUTS.long }); } // Wait a bit more for the page to fully render await page.waitForTimeout(2000); // Look for add source button using flexible selectors const addSourceSelectors = [ '[data-testid="add-source"]', 'button:has-text("Add Source")', 'button:has-text("Create Source")', 'button:has-text("New Source")', '.add-source-button' ]; let addSourceButton = null; for (const selector of addSourceSelectors) { const button = page.locator(selector); if (await button.isVisible({ timeout: TIMEOUTS.medium })) { addSourceButton = button; console.log(`Found add source button using: ${selector}`); break; } } if (!addSourceButton) { // Debug: log what's actually visible on the page const pageContent = await page.textContent('body'); console.log('Page content:', pageContent?.substring(0, 500)); throw new Error('Could not find add source button'); } await addSourceButton.click(); // Wait for source creation form/modal to appear await page.waitForTimeout(1000); // Debug: log what's currently visible await page.waitForLoadState('networkidle'); console.log('Waiting for source creation form to load...'); // Select WebDAV source type if source type selection exists try { // First, look for any select/dropdown elements - focusing on Material-UI patterns const selectTrigger = page.locator([ '[role="combobox"]', '.MuiSelect-select:not([aria-hidden="true"])', 'div[aria-haspopup="listbox"]', '.MuiOutlinedInput-input[role="combobox"]', 'select[name*="type"]', 'select[name*="source"]' ].join(', ')).first(); if (await selectTrigger.isVisible({ timeout: 5000 })) { console.log('Found select trigger, attempting to click...'); await selectTrigger.click({ timeout: 10000 }); // Wait for dropdown menu to appear await page.waitForTimeout(1000); // Look for WebDAV option in the dropdown const webdavOption = page.locator([ '[role="option"]:has-text("webdav")', '[role="option"]:has-text("WebDAV")', 'li:has-text("WebDAV")', 'li:has-text("webdav")', '[data-value="webdav"]', 'option[value="webdav"]' ].join(', ')).first(); if (await webdavOption.isVisible({ timeout: 5000 })) { console.log('Found WebDAV option, selecting it...'); await webdavOption.click(); } else { console.log('WebDAV option not found in dropdown, checking if already selected'); } } else { console.log('No source type selector found, continuing with form...'); } } catch (error) { console.log('Error selecting WebDAV source type:', error); } // Fill WebDAV configuration form console.log('Filling WebDAV configuration form...'); // Wait for form to be ready await page.waitForTimeout(1000); // Fill name field with multiple selector attempts const nameSelectors = [ 'input[name="name"]', 'input[placeholder*="name" i]', 'input[label*="Name"]', 'input[aria-label*="name" i]' ]; let nameInput = null; for (const selector of nameSelectors) { const input = page.locator(selector).first(); if (await input.isVisible({ timeout: 5000 })) { nameInput = input; break; } } if (nameInput) { await nameInput.clear(); await nameInput.fill('Test WebDAV Source - admin'); console.log('Filled name input'); } else { console.log('Warning: Could not find name input field'); } // Fill URL field const urlSelectors = [ 'input[name="url"]', 'input[placeholder*="url" i]', 'input[type="url"]', 'input[aria-label*="url" i]' ]; let urlInput = null; for (const selector of urlSelectors) { const input = page.locator(selector).first(); if (await input.isVisible({ timeout: 5000 })) { urlInput = input; break; } } if (urlInput) { await urlInput.clear(); await urlInput.fill('https://demo.webdav.server/'); console.log('Filled URL input'); } else { console.log('Warning: Could not find URL input field'); } // Fill username field - scope to form/dialog context to avoid login form confusion const formContext = page.locator('[role="dialog"], form, .modal, .form-container').first(); const usernameSelectors = [ 'input[name="username"]', 'input[placeholder*="username" i]', 'input[aria-label*="username" i]' ]; let usernameInput = null; for (const selector of usernameSelectors) { // Try within form context first, then fall back to page-wide const input = formContext.locator(selector).first(); if (await input.isVisible({ timeout: 2000 })) { usernameInput = input; break; } else { // Only use page-wide selector if we're not on a login page const onLoginPage = await page.locator('h3:has-text("Welcome to Readur")').isVisible({ timeout: 1000 }); if (!onLoginPage) { const pageInput = page.locator(selector).first(); if (await pageInput.isVisible({ timeout: 2000 })) { usernameInput = pageInput; break; } } } } if (usernameInput) { await usernameInput.clear(); await usernameInput.fill('webdav_user'); console.log('Filled username input'); } else { console.log('Warning: Could not find username input field'); } // Fill password field - scope to form/dialog context to avoid login form confusion const passwordSelectors = [ 'input[name="password"]', 'input[type="password"]', 'input[aria-label*="password" i]' ]; let passwordInput = null; for (const selector of passwordSelectors) { // Try within form context first, then fall back to page-wide const input = formContext.locator(selector).first(); if (await input.isVisible({ timeout: 2000 })) { passwordInput = input; break; } else { // Only use page-wide selector if we're not on a login page const onLoginPage = await page.locator('h3:has-text("Welcome to Readur")').isVisible({ timeout: 1000 }); if (!onLoginPage) { const pageInput = page.locator(selector).first(); if (await pageInput.isVisible({ timeout: 2000 })) { passwordInput = pageInput; break; } } } } if (passwordInput) { await passwordInput.clear(); await passwordInput.fill('webdav_pass'); console.log('Filled password input'); } else { console.log('Warning: Could not find password input field'); } // Save the source configuration console.log('Looking for save button...'); const saveButtonSelectors = [ 'button:has-text("Save")', 'button:has-text("Create")', 'button[type="submit"]', 'button:has-text("Add")', '[data-testid="save-source"]', '[data-testid="create-source"]' ]; let saveButton = null; for (const selector of saveButtonSelectors) { const button = page.locator(selector).first(); if (await button.isVisible({ timeout: 5000 })) { saveButton = button; console.log(`Found save button using: ${selector}`); break; } } if (saveButton) { console.log('Found save button, clicking...'); // Wait for save API call const savePromise = page.waitForResponse(response => response.url().includes('/sources') && (response.status() === 200 || response.status() === 201), { timeout: TIMEOUTS.medium } ); await saveButton.click(); console.log('Clicked save button, waiting for response...'); try { const response = await savePromise; console.log('WebDAV source created successfully with status:', response.status()); } catch (error) { console.log('Source creation may have failed or timed out:', error); // Don't fail the test immediately - continue to check the results } } else { console.log('Save button not found - form may auto-save or be incomplete'); } // Verify source appears in the list await helpers.waitForLoadingToComplete(); // Use flexible selectors for source list verification const sourceListSelectors = [ '[data-testid="sources-list"]', '.sources-list', '.sources-container', '[role="main"]' // Fallback to main content area ]; let sourceList = null; for (const selector of sourceListSelectors) { const list = page.locator(selector); if (await list.isVisible({ timeout: TIMEOUTS.medium })) { sourceList = list; console.log(`Found source list using: ${selector}`); break; } } if (sourceList) { await expect(sourceList).toBeVisible({ timeout: TIMEOUTS.medium }); } else { console.log('Warning: Could not find source list container'); } // Verify individual source items with flexible selectors const sourceItemSelectors = [ '[data-testid="source-item"]', '.source-item', '.source-card', '.MuiCard-root' ]; let foundSourceItem = false; for (const selector of sourceItemSelectors) { const items = page.locator(selector); if (await items.count() > 0) { await expect(items.first()).toBeVisible({ timeout: TIMEOUTS.medium }); console.log(`Found source items using: ${selector}`); foundSourceItem = true; break; } } if (!foundSourceItem) { console.log('Warning: Could not find source items - list may be empty or using different selectors'); } console.log('✅ WebDAV source creation test completed by authenticated admin'); }); 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 await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // Find WebDAV source and test connection const testConnectionButton = page.locator('button:has-text("Test"), [data-testid="test-connection"]').first(); if (await testConnectionButton.isVisible()) { // Wait for connection test API call const testPromise = page.waitForResponse(response => response.url().includes('/test') || response.url().includes('/connection'), { timeout: TIMEOUTS.medium } ); await testConnectionButton.click(); try { const response = await testPromise; console.log('Connection test completed with status:', response.status()); } catch (error) { console.log('Connection test may have failed:', error); } } // Look for connection status indicator const statusIndicator = page.locator('.status, [data-testid="connection-status"], .connection-result'); if (await statusIndicator.isVisible()) { const statusText = await statusIndicator.textContent(); console.log('Connection status:', statusText); } console.log('✅ WebDAV connection test completed by authenticated admin'); }); });