Readur/frontend/e2e/upload.spec.ts

217 lines
8.5 KiB
TypeScript

import { test, expect } from './fixtures/auth';
import { TEST_FILES, TIMEOUTS, API_ENDPOINTS, EXPECTED_OCR_CONTENT } from './utils/test-data';
import { TestHelpers } from './utils/test-helpers';
test.describe('Document Upload', () => {
let helpers: TestHelpers;
test.beforeEach(async ({ authenticatedPage }) => {
helpers = new TestHelpers(authenticatedPage);
// Navigate to upload page after authentication
await authenticatedPage.goto('/upload');
await helpers.waitForLoadingToComplete();
});
test('should display upload interface', async ({ authenticatedPage: page }) => {
// Check for upload components - react-dropzone creates hidden file input
await expect(page.locator('input[type="file"]')).toBeAttached();
// Check for specific upload page content
await expect(page.locator(':has-text("Drag & drop files here")').first()).toBeVisible();
});
test('should upload single document successfully', async ({ authenticatedPage: page }) => {
// Find file input - react-dropzone creates hidden input
const fileInput = page.locator('input[type="file"]').first();
// Upload test1.png with known OCR content
await fileInput.setInputFiles(TEST_FILES.test1);
// Verify file is added to the list by looking for the filename in the text
await expect(page.getByText('test1.png')).toBeVisible({ timeout: TIMEOUTS.short });
// Look for the "Upload All" button which appears after files are selected
const uploadButton = page.locator('button:has-text("Upload All")');
await expect(uploadButton).toBeVisible({ timeout: TIMEOUTS.short });
// Wait for upload API call
const uploadResponse = helpers.waitForApiCall('/api/documents', TIMEOUTS.upload);
// Click upload button
await uploadButton.click();
// Verify upload was successful by waiting for API response
await uploadResponse;
// At this point the upload is complete - no need to check for specific text
console.log('Upload completed successfully');
});
test('should upload multiple documents', async ({ authenticatedPage: page }) => {
const fileInput = page.locator('input[type="file"]').first();
// Upload multiple test images with different formats
await fileInput.setInputFiles([TEST_FILES.test1, TEST_FILES.test2, TEST_FILES.test3]);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
// Wait for all uploads to complete
await helpers.waitForLoadingToComplete();
// Should show multiple uploaded documents
const uploadedFiles = page.locator('[data-testid="uploaded-files"] > *, .uploaded-file');
await expect(uploadedFiles).toHaveCount(3, { timeout: TIMEOUTS.medium });
});
test('should show upload progress', async ({ authenticatedPage: page }) => {
const fileInput = page.locator('input[type="file"]').first();
await fileInput.setInputFiles(TEST_FILES.test4);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
// Should show progress indicator
await expect(page.locator('[data-testid="upload-progress"], .progress, [role="progressbar"]')).toBeVisible({ timeout: TIMEOUTS.short });
});
test('should handle upload errors gracefully', async ({ authenticatedPage: page }) => {
// Mock a failed upload by using a non-existent file type or intercepting the request
await page.route('**/api/documents/upload', route => {
route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({ error: 'Upload failed' })
});
});
const fileInput = page.locator('input[type="file"]').first();
await fileInput.setInputFiles(TEST_FILES.image);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
// Should show error message
await helpers.waitForToast();
});
test('should validate file types', async ({ authenticatedPage: page }) => {
// Try to upload an unsupported file type
const fileInput = page.locator('input[type="file"]').first();
// Create a mock file with unsupported extension
const buffer = Buffer.from('fake content');
await fileInput.setInputFiles({
name: 'test.xyz',
mimeType: 'application/octet-stream',
buffer
});
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
// Should show validation error
await helpers.waitForToast();
});
test('should navigate to uploaded document after successful upload', async ({ authenticatedPage: page }) => {
const fileInput = page.locator('input[type="file"]').first();
await fileInput.setInputFiles(TEST_FILES.image);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
await helpers.waitForLoadingToComplete();
// Click on uploaded document to view details
const uploadedDocument = page.locator('[data-testid="uploaded-files"] > *, .uploaded-file').first();
if (await uploadedDocument.isVisible()) {
await uploadedDocument.click();
// Should navigate to document details page
await page.waitForURL(/\/documents\/[^\/]+/, { timeout: TIMEOUTS.medium });
}
});
test('should show OCR processing status', async ({ authenticatedPage: page }) => {
const fileInput = page.locator('input[type="file"]').first();
await fileInput.setInputFiles(TEST_FILES.test5);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
await helpers.waitForLoadingToComplete();
// Should show OCR processing status
await expect(page.locator(':has-text("OCR"), :has-text("Processing"), [data-testid="ocr-status"]')).toBeVisible({
timeout: TIMEOUTS.medium
});
});
test('should process OCR and extract correct text content', async ({ authenticatedPage: page }) => {
const fileInput = page.locator('input[type="file"]').first();
// Upload test6.jpeg with known content
await fileInput.setInputFiles(TEST_FILES.test6);
const uploadButton = page.locator('button:has-text("Upload"), [data-testid="upload-button"]');
if (await uploadButton.isVisible()) {
await uploadButton.click();
}
await helpers.waitForLoadingToComplete();
// Wait for OCR to complete
await expect(page.locator(':has-text("OCR Complete"), :has-text("Processed"), [data-testid="ocr-complete"]')).toBeVisible({
timeout: TIMEOUTS.ocr
});
// Navigate to document details to verify OCR content
const uploadedDocument = page.locator('[data-testid="uploaded-files"] > *, .uploaded-file').first();
if (await uploadedDocument.isVisible()) {
await uploadedDocument.click();
// Should navigate to document details page
await page.waitForURL(/\/documents\/[^\/]+/, { timeout: TIMEOUTS.medium });
// Check that OCR content is visible and contains expected text
const documentContent = page.locator('[data-testid="document-content"], .document-text, .ocr-content');
if (await documentContent.isVisible()) {
const content = await documentContent.textContent();
expect(content).toContain('Test 6');
expect(content).toContain('This is some text from text 6');
}
}
});
test('should allow drag and drop upload', async ({ authenticatedPage: page }) => {
// Look for dropzone
const dropzone = page.locator('[data-testid="dropzone"], .dropzone, .upload-area');
if (await dropzone.isVisible()) {
// Simulate drag and drop
await dropzone.dispatchEvent('dragover', { dataTransfer: { files: [] } });
await dropzone.dispatchEvent('drop', {
dataTransfer: {
files: [{ name: TEST_FILES.image, type: 'image/png' }]
}
});
// Should show uploaded file
await expect(page.locator('[data-testid="uploaded-files"], .uploaded-file')).toBeVisible({
timeout: TIMEOUTS.medium
});
}
});
});