import { test, expect } from './fixtures/auth'; import { TIMEOUTS, API_ENDPOINTS } from './utils/test-data'; import { TestHelpers } from './utils/test-helpers'; test.describe('WebDAV Workflow', () => { let helpers: TestHelpers; test.beforeEach(async ({ authenticatedPage }) => { helpers = new TestHelpers(authenticatedPage); await helpers.navigateToPage('/sources'); }); test.skip('should create and configure WebDAV source', async ({ authenticatedPage: 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); // Navigate to sources page await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // 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 extra time for WebKit to fully render the page await page.waitForTimeout(5000); // For WebKit, try to wait for specific page elements to be loaded await page.waitForFunction(() => { return document.querySelector('[data-testid="add-source"]') !== null || document.querySelector('button:has-text("Add Source")') !== null || document.body.textContent?.includes('Add Source'); }, { timeout: TIMEOUTS.long }); // Look for add source button (try multiple selectors in order of preference) let addSourceButton = page.locator('[data-testid="add-source"]').first(); if (!(await addSourceButton.isVisible({ timeout: 5000 }))) { addSourceButton = page.locator('button:has-text("Add Source")').first(); } if (!(await addSourceButton.isVisible({ timeout: 5000 }))) { addSourceButton = page.locator('button:has-text("Add")').first(); } if (!(await addSourceButton.isVisible({ timeout: 5000 }))) { addSourceButton = page.locator('button[aria-label*="add"], button[title*="add"]').first(); } if (await addSourceButton.isVisible({ timeout: 5000 })) { console.log('Found add source button, clicking...'); await addSourceButton.click(); } else { // Enhanced debugging for WebKit const pageContent = await page.textContent('body'); console.log('Page content (first 500 chars):', pageContent?.substring(0, 500)); console.log('Page URL:', page.url()); // Check if we're actually on the sources page const pageTitle = await page.title(); console.log('Page title:', pageTitle); // Try to find any buttons on the page const allButtons = await page.locator('button').count(); console.log('Total buttons found:', allButtons); throw new Error('Could not find add source button'); } // 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...'); try { // Try normal click first await selectTrigger.click({ timeout: 10000 }); } catch (clickError) { console.log('Normal click failed, trying alternative methods:', clickError); try { // Try force click await selectTrigger.click({ force: true, timeout: 5000 }); } catch (forceClickError) { console.log('Force click also failed, trying keyboard navigation:', forceClickError); // As last resort, try keyboard navigation await selectTrigger.focus(); await page.keyboard.press('Enter'); } } // 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'); // Sometimes the form might default to WebDAV or not need selection } } else { console.log('No source type selector found, continuing with form...'); } } catch (error) { console.log('Error selecting WebDAV source type:', error); // Continue with the test - the form might not have a source type selector } // Fill WebDAV configuration form console.log('Filling WebDAV configuration form...'); // Wait for form to be ready await page.waitForTimeout(1000); const nameInput = page.locator('input[name="name"], input[placeholder*="name"], input[label*="Name"]').first(); if (await nameInput.isVisible({ timeout: 10000 })) { await nameInput.fill('Test WebDAV Source'); console.log('Filled name input'); } const urlInput = page.locator('input[name="url"], input[placeholder*="url"], input[type="url"]').first(); if (await urlInput.isVisible({ timeout: 5000 })) { await urlInput.fill('https://demo.webdav.server/'); console.log('Filled URL input'); } const usernameInput = page.locator('input[name="username"], input[placeholder*="username"]').first(); if (await usernameInput.isVisible({ timeout: 5000 })) { await usernameInput.fill('webdav_user'); console.log('Filled username input'); } const passwordInput = page.locator('input[name="password"], input[type="password"]').first(); if (await passwordInput.isVisible({ timeout: 5000 })) { await passwordInput.fill('webdav_pass'); console.log('Filled password input'); } // Save the source configuration console.log('Looking for save button...'); const saveButton = page.locator('button:has-text("Save"), button:has-text("Create"), button[type="submit"]').first(); if (await saveButton.isVisible({ timeout: 10000 })) { 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'); } // Verify source appears in the list await helpers.waitForLoadingToComplete(); // Wait for sources to load again after creation await page.waitForLoadState('networkidle'); // Wait for loading spinner to disappear const postCreateSpinner = page.locator('[role="progressbar"], .MuiCircularProgress-root'); if (await postCreateSpinner.isVisible({ timeout: 2000 })) { await expect(postCreateSpinner).not.toBeVisible({ timeout: TIMEOUTS.long }); } // Look for sources list or individual source items const sourcesList = page.locator('[data-testid="sources-list"]'); const sourceItems = page.locator('[data-testid="source-item"]'); // Check if either the sources list container or source items are visible const sourcesVisible = await sourcesList.isVisible({ timeout: TIMEOUTS.medium }).catch(() => false); const itemsVisible = await sourceItems.first().isVisible({ timeout: TIMEOUTS.medium }).catch(() => false); if (sourcesVisible || itemsVisible) { console.log('✅ Sources list or source items are visible'); } else { console.log('ℹ️ Sources list not immediately visible - source creation may be async'); } }); test('should test WebDAV connection', async ({ authenticatedPage: page }) => { // 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); } }); test('should initiate WebDAV sync', async ({ authenticatedPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // Find and click sync button const syncButton = page.locator('button:has-text("Sync"), [data-testid="sync-source"]').first(); if (await syncButton.isVisible()) { // Wait for sync API call const syncPromise = page.waitForResponse(response => response.url().includes('/sync') && response.status() === 200, { timeout: TIMEOUTS.medium } ); await syncButton.click(); try { await syncPromise; console.log('WebDAV sync initiated successfully'); // Look for sync progress indicators const progressIndicator = page.locator('.progress, [data-testid="sync-progress"], .syncing'); if (await progressIndicator.isVisible({ timeout: 5000 })) { console.log('Sync progress indicator visible'); } } catch (error) { console.log('Sync may have failed or timed out:', error); } } }); test('should show WebDAV sync history', async ({ authenticatedPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // Look for sync history or logs const historyButton = page.locator('button:has-text("History"), button:has-text("Logs"), [data-testid="sync-history"]').first(); if (await historyButton.isVisible()) { await historyButton.click(); // Check if history modal or page opens const historyContainer = page.locator('.history, [data-testid="sync-history"], .logs-container'); await expect(historyContainer.first()).toBeVisible({ timeout: TIMEOUTS.short }); // Check for history entries const historyEntries = page.locator('.history-item, .log-entry, tr'); if (await historyEntries.first().isVisible({ timeout: 5000 })) { const entryCount = await historyEntries.count(); console.log(`Found ${entryCount} sync history entries`); } } }); test('should handle WebDAV source deletion', async ({ authenticatedPage: page }) => { await page.goto('/sources'); await helpers.waitForLoadingToComplete(); // Find delete button for WebDAV source const deleteButton = page.locator('button:has-text("Delete"), [data-testid="delete-source"], .delete-button').first(); if (await deleteButton.isVisible()) { await deleteButton.click(); // Handle confirmation dialog if it appears const confirmButton = page.locator('button:has-text("Confirm"), button:has-text("Delete"), button:has-text("Yes")').first(); if (await confirmButton.isVisible({ timeout: 3000 })) { // Wait for delete API call const deletePromise = page.waitForResponse(response => response.url().includes('/sources') && response.status() === 200, { timeout: TIMEOUTS.medium } ); await confirmButton.click(); try { await deletePromise; console.log('WebDAV source deleted successfully'); } catch (error) { console.log('Source deletion may have failed:', error); } } } }); });