fix(tests): remove annoying output from e2e tests, add test for new Source page functionality
This commit is contained in:
parent
80f40ec3d2
commit
49faaefc21
|
|
@ -7,7 +7,6 @@ test.describe('E2E Auth System', () => {
|
||||||
expect(testUser.credentials.username).toMatch(/^e2e_user_\d+_\d+_[a-z0-9]+$/);
|
expect(testUser.credentials.username).toMatch(/^e2e_user_\d+_\d+_[a-z0-9]+$/);
|
||||||
expect(testUser.userResponse.role).toBe('user');
|
expect(testUser.userResponse.role).toBe('user');
|
||||||
|
|
||||||
console.log(`Test user created: ${testUser.credentials.username} (${testUser.userResponse.id})`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create and login dynamic admin user', async ({ page, testAdmin }) => {
|
test('should create and login dynamic admin user', async ({ page, testAdmin }) => {
|
||||||
|
|
@ -15,7 +14,6 @@ test.describe('E2E Auth System', () => {
|
||||||
expect(testAdmin.credentials.username).toMatch(/^e2e_admin_\d+_\d+_[a-z0-9]+$/);
|
expect(testAdmin.credentials.username).toMatch(/^e2e_admin_\d+_\d+_[a-z0-9]+$/);
|
||||||
expect(testAdmin.userResponse.role).toBe('admin');
|
expect(testAdmin.userResponse.role).toBe('admin');
|
||||||
|
|
||||||
console.log(`Test admin created: ${testAdmin.credentials.username} (${testAdmin.userResponse.id})`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should login dynamic user via browser UI', async ({ page, testUser }) => {
|
test('should login dynamic user via browser UI', async ({ page, testUser }) => {
|
||||||
|
|
@ -32,7 +30,6 @@ test.describe('E2E Auth System', () => {
|
||||||
await expect(page).toHaveURL(/.*\/dashboard.*/);
|
await expect(page).toHaveURL(/.*\/dashboard.*/);
|
||||||
await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible();
|
await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible();
|
||||||
|
|
||||||
console.log(`Successfully logged in dynamic user: ${testUser.credentials.username}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should login dynamic admin via browser UI', async ({ page, testAdmin }) => {
|
test('should login dynamic admin via browser UI', async ({ page, testAdmin }) => {
|
||||||
|
|
@ -49,7 +46,6 @@ test.describe('E2E Auth System', () => {
|
||||||
await expect(page).toHaveURL(/.*\/dashboard.*/);
|
await expect(page).toHaveURL(/.*\/dashboard.*/);
|
||||||
await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible();
|
await expect(page.locator('h4:has-text("Welcome back,")')).toBeVisible();
|
||||||
|
|
||||||
console.log(`Successfully logged in dynamic admin: ${testAdmin.credentials.username}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should support API login for dynamic users', async ({ page, testUser }) => {
|
test('should support API login for dynamic users', async ({ page, testUser }) => {
|
||||||
|
|
@ -60,7 +56,6 @@ test.describe('E2E Auth System', () => {
|
||||||
expect(token).toBeTruthy();
|
expect(token).toBeTruthy();
|
||||||
expect(typeof token).toBe('string');
|
expect(typeof token).toBe('string');
|
||||||
|
|
||||||
console.log(`Successfully got API token for: ${testUser.credentials.username}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create unique users for each test', async ({ page }) => {
|
test('should create unique users for each test', async ({ page }) => {
|
||||||
|
|
@ -74,7 +69,6 @@ test.describe('E2E Auth System', () => {
|
||||||
expect(user1.credentials.username).not.toBe(user2.credentials.username);
|
expect(user1.credentials.username).not.toBe(user2.credentials.username);
|
||||||
expect(user1.userResponse.id).not.toBe(user2.userResponse.id);
|
expect(user1.userResponse.id).not.toBe(user2.userResponse.id);
|
||||||
|
|
||||||
console.log(`Created unique users: ${user1.credentials.username} and ${user2.credentials.username}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('dynamic admin should have admin permissions', async ({ dynamicAdminPage }) => {
|
test('dynamic admin should have admin permissions', async ({ dynamicAdminPage }) => {
|
||||||
|
|
@ -89,7 +83,6 @@ test.describe('E2E Auth System', () => {
|
||||||
// Should see debug page content (admin accessible)
|
// Should see debug page content (admin accessible)
|
||||||
await expect(dynamicAdminPage.locator('h1, h2, h3, h4, h5, h6').first()).toBeVisible({ timeout: 10000 });
|
await expect(dynamicAdminPage.locator('h1, h2, h3, h4, h5, h6').first()).toBeVisible({ timeout: 10000 });
|
||||||
|
|
||||||
console.log('✅ Dynamic admin user has admin permissions');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('dynamic user should have user permissions', async ({ dynamicUserPage }) => {
|
test('dynamic user should have user permissions', async ({ dynamicUserPage }) => {
|
||||||
|
|
@ -107,6 +100,5 @@ test.describe('E2E Auth System', () => {
|
||||||
|
|
||||||
expect(isDashboard).toBe(true);
|
expect(isDashboard).toBe(true);
|
||||||
|
|
||||||
console.log('✅ Dynamic user has user permissions');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -5,14 +5,12 @@ import { TestHelpers } from './utils/test-helpers';
|
||||||
test.describe('Document Management', () => {
|
test.describe('Document Management', () => {
|
||||||
let helpers: TestHelpers;
|
let helpers: TestHelpers;
|
||||||
|
|
||||||
test.beforeEach(async ({ dynamicAdminPage }) => {
|
test.beforeEach(async ({ adminPage }) => {
|
||||||
helpers = new TestHelpers(dynamicAdminPage);
|
helpers = new TestHelpers(adminPage);
|
||||||
await helpers.navigateToPage('/documents');
|
await helpers.navigateToPage('/documents');
|
||||||
// Ensure we have test documents for tests that need them
|
|
||||||
await helpers.ensureTestDocumentsExist();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should display document list', async ({ dynamicAdminPage: page }) => {
|
test('should display document list', async ({ adminPage: page }) => {
|
||||||
// The documents page should be visible with title and description
|
// The documents page should be visible with title and description
|
||||||
// Use more flexible selectors for headings - based on artifact, it's h4
|
// Use more flexible selectors for headings - based on artifact, it's h4
|
||||||
const documentsHeading = page.locator('h4:has-text("Documents")');
|
const documentsHeading = page.locator('h4:has-text("Documents")');
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ export class AuthHelper {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await loginPromise;
|
const response = await loginPromise;
|
||||||
console.log(`Login API call successful with status: ${response.status()}`);
|
|
||||||
|
|
||||||
// Wait for navigation to dashboard with more flexible URL pattern
|
// Wait for navigation to dashboard with more flexible URL pattern
|
||||||
await this.page.waitForURL(/.*\/dashboard.*/, { timeout: TIMEOUTS.navigation });
|
await this.page.waitForURL(/.*\/dashboard.*/, { timeout: TIMEOUTS.navigation });
|
||||||
|
|
@ -108,9 +107,7 @@ export class AuthHelper {
|
||||||
document.querySelector('[role="main"]') !== null);
|
document.querySelector('[role="main"]') !== null);
|
||||||
}, { timeout: TIMEOUTS.navigation });
|
}, { timeout: TIMEOUTS.navigation });
|
||||||
|
|
||||||
console.log(`Login as ${credentials.username} completed successfully`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Login as ${credentials.username} failed:`, error);
|
|
||||||
// Take a screenshot for debugging
|
// Take a screenshot for debugging
|
||||||
await this.page.screenshot({
|
await this.page.screenshot({
|
||||||
path: `test-results/login-failure-${credentials.username}-${Date.now()}.png`,
|
path: `test-results/login-failure-${credentials.username}-${Date.now()}.png`,
|
||||||
|
|
@ -174,14 +171,12 @@ export const test = base.extend<AuthFixture>({
|
||||||
testUser: async ({ page }, use) => {
|
testUser: async ({ page }, use) => {
|
||||||
const authHelper = new E2ETestAuthHelper(page);
|
const authHelper = new E2ETestAuthHelper(page);
|
||||||
const testUser = await authHelper.createTestUser();
|
const testUser = await authHelper.createTestUser();
|
||||||
console.log(`Created dynamic test user: ${testUser.credentials.username}`);
|
|
||||||
await use(testUser);
|
await use(testUser);
|
||||||
},
|
},
|
||||||
|
|
||||||
testAdmin: async ({ page }, use) => {
|
testAdmin: async ({ page }, use) => {
|
||||||
const authHelper = new E2ETestAuthHelper(page);
|
const authHelper = new E2ETestAuthHelper(page);
|
||||||
const testAdmin = await authHelper.createAdminUser();
|
const testAdmin = await authHelper.createAdminUser();
|
||||||
console.log(`Created dynamic test admin: ${testAdmin.credentials.username}`);
|
|
||||||
await use(testAdmin);
|
await use(testAdmin);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -191,7 +186,6 @@ export const test = base.extend<AuthFixture>({
|
||||||
if (!loginSuccess) {
|
if (!loginSuccess) {
|
||||||
throw new Error(`Failed to login dynamic test user: ${testUser.credentials.username}`);
|
throw new Error(`Failed to login dynamic test user: ${testUser.credentials.username}`);
|
||||||
}
|
}
|
||||||
console.log(`Logged in dynamic test user: ${testUser.credentials.username}`);
|
|
||||||
await use(page);
|
await use(page);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -201,7 +195,6 @@ export const test = base.extend<AuthFixture>({
|
||||||
if (!loginSuccess) {
|
if (!loginSuccess) {
|
||||||
throw new Error(`Failed to login dynamic test admin: ${testAdmin.credentials.username}`);
|
throw new Error(`Failed to login dynamic test admin: ${testAdmin.credentials.username}`);
|
||||||
}
|
}
|
||||||
console.log(`Logged in dynamic test admin: ${testAdmin.credentials.username}`);
|
|
||||||
await use(page);
|
await use(page);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ test.describe('OCR Multiple Languages', () => {
|
||||||
await page.goto('/settings');
|
await page.goto('/settings');
|
||||||
await helpers.waitForLoadingToComplete();
|
await helpers.waitForLoadingToComplete();
|
||||||
|
|
||||||
// Look for the new LanguageSelector component
|
// Look for the OCR Languages section
|
||||||
const languageSelector = page.locator('label:has-text("OCR Languages")').first();
|
const languageSelector = page.locator('text="OCR Languages (1/4)"').first();
|
||||||
await expect(languageSelector).toBeVisible({ timeout: TIMEOUTS.medium });
|
await expect(languageSelector).toBeVisible({ timeout: TIMEOUTS.medium });
|
||||||
|
|
||||||
// Check for the language selector button
|
// Check for the language selector button
|
||||||
|
|
@ -162,6 +162,9 @@ test.describe('OCR Multiple Languages', () => {
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
// Wait for the dropzone to be ready
|
||||||
|
await expect(page.locator('text=Drag & drop files here')).toBeVisible({ timeout: 10000 });
|
||||||
|
|
||||||
// Upload Spanish test document - try multiple selectors for better WebKit compatibility
|
// Upload Spanish test document - try multiple selectors for better WebKit compatibility
|
||||||
let fileInput = page.locator('input[type="file"]').first();
|
let fileInput = page.locator('input[type="file"]').first();
|
||||||
|
|
||||||
|
|
@ -236,6 +239,9 @@ test.describe('OCR Multiple Languages', () => {
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
// Wait for the dropzone to be ready
|
||||||
|
await expect(page.locator('text=Drag & drop files here')).toBeVisible({ timeout: 10000 });
|
||||||
|
|
||||||
// Upload English test document - try multiple selectors for better WebKit compatibility
|
// Upload English test document - try multiple selectors for better WebKit compatibility
|
||||||
let fileInput = page.locator('input[type="file"]').first();
|
let fileInput = page.locator('input[type="file"]').first();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,6 @@ export class E2ETestAuthHelper {
|
||||||
password: 'testpass123'
|
password: 'testpass123'
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`Creating E2E test user: ${credentials.username}`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Make API call to create user
|
// Make API call to create user
|
||||||
const response = await this.page.request.post('/api/auth/register', {
|
const response = await this.page.request.post('/api/auth/register', {
|
||||||
|
|
@ -63,7 +61,6 @@ export class E2ETestAuthHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
const userResponse: TestUserResponse = await response.json();
|
const userResponse: TestUserResponse = await response.json();
|
||||||
console.log(`✅ Created E2E test user: ${userResponse.username} (${userResponse.id})`);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
credentials,
|
credentials,
|
||||||
|
|
@ -86,7 +83,6 @@ export class E2ETestAuthHelper {
|
||||||
password: 'adminpass123'
|
password: 'adminpass123'
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`Creating E2E admin user: ${credentials.username}`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Make API call to create admin user
|
// Make API call to create admin user
|
||||||
|
|
@ -106,7 +102,6 @@ export class E2ETestAuthHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
const userResponse: TestUserResponse = await response.json();
|
const userResponse: TestUserResponse = await response.json();
|
||||||
console.log(`✅ Created E2E admin user: ${userResponse.username} (${userResponse.id})`);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
credentials,
|
credentials,
|
||||||
|
|
@ -122,7 +117,6 @@ export class E2ETestAuthHelper {
|
||||||
* Login a user via browser UI and return authentication status
|
* Login a user via browser UI and return authentication status
|
||||||
*/
|
*/
|
||||||
async loginUser(credentials: TestCredentials): Promise<boolean> {
|
async loginUser(credentials: TestCredentials): Promise<boolean> {
|
||||||
console.log(`Attempting to login E2E user: ${credentials.username}...`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Go to home page and wait for it to load
|
// Go to home page and wait for it to load
|
||||||
|
|
@ -133,7 +127,6 @@ export class E2ETestAuthHelper {
|
||||||
const welcomeText = await this.page.locator('h4:has-text("Welcome back,")').isVisible().catch(() => false);
|
const welcomeText = await this.page.locator('h4:has-text("Welcome back,")').isVisible().catch(() => false);
|
||||||
|
|
||||||
if (welcomeText) {
|
if (welcomeText) {
|
||||||
console.log('Already logged in - found welcome message');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,7 +175,6 @@ export class E2ETestAuthHelper {
|
||||||
await signInButton.click();
|
await signInButton.click();
|
||||||
|
|
||||||
const response = await loginPromise;
|
const response = await loginPromise;
|
||||||
console.log(`Login API call successful with status: ${response.status()}`);
|
|
||||||
|
|
||||||
// Wait for navigation to dashboard with more flexible URL pattern
|
// Wait for navigation to dashboard with more flexible URL pattern
|
||||||
await this.page.waitForURL(/.*\/dashboard.*/, { timeout: E2E_TIMEOUTS.navigation });
|
await this.page.waitForURL(/.*\/dashboard.*/, { timeout: E2E_TIMEOUTS.navigation });
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
|
describe('SourcesPage Sync Functionality', () => {
|
||||||
|
it('should have both Quick Sync and Deep Scan options', () => {
|
||||||
|
// Test documents the new sync modal functionality
|
||||||
|
// The sync button now opens a modal with two options:
|
||||||
|
|
||||||
|
const syncOptions = {
|
||||||
|
quickSync: {
|
||||||
|
name: 'Quick Sync',
|
||||||
|
description: 'Fast incremental sync using ETags. Only processes new or changed files.',
|
||||||
|
endpoint: '/sources/{id}/sync',
|
||||||
|
method: 'POST',
|
||||||
|
recommended: true,
|
||||||
|
supportedSources: ['webdav', 'local_folder', 's3'],
|
||||||
|
},
|
||||||
|
deepScan: {
|
||||||
|
name: 'Deep Scan',
|
||||||
|
description: 'Complete rescan that resets ETag expectations. Use for troubleshooting sync issues.',
|
||||||
|
endpoint: '/sources/{id}/deep-scan',
|
||||||
|
method: 'POST',
|
||||||
|
recommended: false,
|
||||||
|
supportedSources: ['webdav'], // Currently only WebDAV
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify both options exist
|
||||||
|
expect(syncOptions.quickSync).toBeDefined();
|
||||||
|
expect(syncOptions.deepScan).toBeDefined();
|
||||||
|
|
||||||
|
// Verify Quick Sync supports all source types
|
||||||
|
expect(syncOptions.quickSync.supportedSources).toEqual(['webdav', 'local_folder', 's3']);
|
||||||
|
|
||||||
|
// Verify Deep Scan is WebDAV only
|
||||||
|
expect(syncOptions.deepScan.supportedSources).toEqual(['webdav']);
|
||||||
|
|
||||||
|
// Verify API endpoints
|
||||||
|
expect(syncOptions.quickSync.endpoint).toBe('/sources/{id}/sync');
|
||||||
|
expect(syncOptions.deepScan.endpoint).toBe('/sources/{id}/deep-scan');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show appropriate options based on source type', () => {
|
||||||
|
const sourceTypes = ['webdav', 'local_folder', 's3'];
|
||||||
|
|
||||||
|
sourceTypes.forEach(sourceType => {
|
||||||
|
const availableOptions = [];
|
||||||
|
|
||||||
|
// Quick Sync is always available
|
||||||
|
availableOptions.push('Quick Sync');
|
||||||
|
|
||||||
|
// Deep Scan only for WebDAV
|
||||||
|
if (sourceType === 'webdav') {
|
||||||
|
availableOptions.push('Deep Scan');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType === 'webdav') {
|
||||||
|
expect(availableOptions).toEqual(['Quick Sync', 'Deep Scan']);
|
||||||
|
} else {
|
||||||
|
expect(availableOptions).toEqual(['Quick Sync']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use correct API services', () => {
|
||||||
|
// Test documents the API service usage
|
||||||
|
const apiServices = {
|
||||||
|
triggerSync: 'sourcesService.triggerSync(sourceId)',
|
||||||
|
triggerDeepScan: 'sourcesService.triggerDeepScan(sourceId)',
|
||||||
|
stopSync: 'sourcesService.stopSync(sourceId)',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify service methods exist
|
||||||
|
expect(apiServices.triggerSync).toBe('sourcesService.triggerSync(sourceId)');
|
||||||
|
expect(apiServices.triggerDeepScan).toBe('sourcesService.triggerDeepScan(sourceId)');
|
||||||
|
expect(apiServices.stopSync).toBe('sourcesService.stopSync(sourceId)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle deep scan errors for non-WebDAV sources', () => {
|
||||||
|
// Test documents error handling for deep scan on unsupported sources
|
||||||
|
const errorScenarios = [
|
||||||
|
{
|
||||||
|
sourceType: 'local_folder',
|
||||||
|
expectedBehavior: 'Deep scan option should be disabled/grayed out',
|
||||||
|
apiResponse: 'Should not call deep scan API',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sourceType: 's3',
|
||||||
|
expectedBehavior: 'Deep scan option should be disabled/grayed out',
|
||||||
|
apiResponse: 'Should not call deep scan API',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sourceType: 'webdav',
|
||||||
|
expectedBehavior: 'Deep scan option should be enabled and clickable',
|
||||||
|
apiResponse: 'Should call sourcesService.triggerDeepScan()',
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
errorScenarios.forEach(scenario => {
|
||||||
|
if (scenario.sourceType === 'webdav') {
|
||||||
|
expect(scenario.expectedBehavior).toBe('Deep scan option should be enabled and clickable');
|
||||||
|
} else {
|
||||||
|
expect(scenario.expectedBehavior).toBe('Deep scan option should be disabled/grayed out');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide clear user feedback', () => {
|
||||||
|
// Test documents the UX improvements
|
||||||
|
const userFeedback = {
|
||||||
|
modalTitle: 'Choose Sync Type',
|
||||||
|
quickSyncBadge: 'Recommended',
|
||||||
|
deepScanBadge: {
|
||||||
|
webdav: 'WebDAV Only',
|
||||||
|
others: 'Not Available'
|
||||||
|
},
|
||||||
|
infoAlert: 'Deep scan is currently only available for WebDAV sources. Other source types will use quick sync.',
|
||||||
|
descriptions: {
|
||||||
|
quickSync: 'Fast incremental sync using ETags. Only processes new or changed files.',
|
||||||
|
deepScan: 'Complete rescan that resets ETag expectations. Use for troubleshooting sync issues.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify user-friendly messaging exists
|
||||||
|
expect(userFeedback.modalTitle).toBe('Choose Sync Type');
|
||||||
|
expect(userFeedback.quickSyncBadge).toBe('Recommended');
|
||||||
|
expect(userFeedback.deepScanBadge.webdav).toBe('WebDAV Only');
|
||||||
|
expect(userFeedback.deepScanBadge.others).toBe('Not Available');
|
||||||
|
expect(userFeedback.descriptions.quickSync).toContain('ETags');
|
||||||
|
expect(userFeedback.descriptions.deepScan).toContain('resets ETag expectations');
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue