Readur/frontend/e2e/webdav-workflow-dynamic.spe...

391 lines
13 KiB
TypeScript

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 ({ authenticatedPage }) => {
helpers = new TestHelpers(authenticatedPage);
await helpers.navigateToPage('/sources');
});
test.skip('should create and configure WebDAV source with dynamic admin', async ({ authenticatedPage: 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 ({ authenticatedPage: 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');
});
});