Add frontend testing - Playwright
This commit is contained in:
157
frontend/tests/onboarding/wizard-navigation.spec.ts
Normal file
157
frontend/tests/onboarding/wizard-navigation.spec.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Onboarding Wizard Navigation', () => {
|
||||
// Use authenticated state
|
||||
test.use({ storageState: 'tests/.auth/user.json' });
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to onboarding
|
||||
await page.goto('/app/onboarding');
|
||||
});
|
||||
|
||||
test('should display first step of onboarding wizard', async ({ page }) => {
|
||||
// Should show onboarding content
|
||||
await expect(page.locator('body')).toContainText(/onboarding|bienvenido|welcome/i);
|
||||
|
||||
// Should have navigation buttons
|
||||
const nextButton = page.getByRole('button', { name: /next|siguiente|continuar/i });
|
||||
await expect(nextButton).toBeVisible();
|
||||
});
|
||||
|
||||
test('should navigate through wizard steps', async ({ page }) => {
|
||||
// Click through wizard steps
|
||||
let currentStep = 1;
|
||||
const maxSteps = 5; // Adjust based on your actual wizard steps
|
||||
|
||||
for (let step = 0; step < maxSteps; step++) {
|
||||
// Look for Next/Continue button
|
||||
const nextButton = page.getByRole('button', { name: /next|siguiente|continuar/i });
|
||||
|
||||
// If no next button, we might be at the end
|
||||
if (!(await nextButton.isVisible().catch(() => false))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Click next
|
||||
await nextButton.click();
|
||||
|
||||
// Wait for navigation/content change
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
currentStep++;
|
||||
}
|
||||
|
||||
// Should have navigated through at least 2 steps
|
||||
expect(currentStep).toBeGreaterThan(1);
|
||||
});
|
||||
|
||||
test('should allow backward navigation', async ({ page }) => {
|
||||
// Navigate to second step
|
||||
const nextButton = page.getByRole('button', { name: /next|siguiente|continuar/i });
|
||||
await nextButton.click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Look for back button
|
||||
const backButton = page.getByRole('button', { name: /back|previous|atrás|anterior/i });
|
||||
|
||||
if (await backButton.isVisible().catch(() => false)) {
|
||||
await backButton.click();
|
||||
|
||||
// Should go back to first step
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Verify we're back at the beginning
|
||||
await expect(nextButton).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('should show progress indicator', async ({ page }) => {
|
||||
// Look for progress indicators (stepper, progress bar, etc.)
|
||||
const progressIndicators = [
|
||||
page.locator('[role="progressbar"]'),
|
||||
page.locator('.stepper'),
|
||||
page.locator('.progress'),
|
||||
page.locator('[data-testid*="progress"]'),
|
||||
page.locator('[data-testid*="step"]'),
|
||||
];
|
||||
|
||||
let foundProgress = false;
|
||||
for (const indicator of progressIndicators) {
|
||||
if (await indicator.isVisible().catch(() => false)) {
|
||||
foundProgress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Progress indicator should exist
|
||||
expect(foundProgress).toBe(true);
|
||||
});
|
||||
|
||||
test('should validate required fields before proceeding', async ({ page }) => {
|
||||
// Try to click next without filling required fields
|
||||
const nextButton = page.getByRole('button', { name: /next|siguiente|continuar/i });
|
||||
|
||||
// Get current URL
|
||||
const urlBefore = page.url();
|
||||
|
||||
await nextButton.click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Should either:
|
||||
// 1. Show validation error, OR
|
||||
// 2. Stay on the same step if validation prevents navigation
|
||||
|
||||
const urlAfter = page.url();
|
||||
|
||||
// If URL changed, we moved to next step (validation passed or not required)
|
||||
// If URL same, validation likely blocked navigation
|
||||
// Either way is valid, but let's check for validation messages if URL is same
|
||||
|
||||
if (urlBefore === urlAfter) {
|
||||
// Look for validation messages
|
||||
const bodyText = await page.locator('body').textContent();
|
||||
// This step might have required fields
|
||||
}
|
||||
});
|
||||
|
||||
test('should be able to skip onboarding if option exists', async ({ page }) => {
|
||||
// Look for skip button
|
||||
const skipButton = page.getByRole('button', { name: /skip|omitir|later/i });
|
||||
|
||||
if (await skipButton.isVisible().catch(() => false)) {
|
||||
await skipButton.click();
|
||||
|
||||
// Should redirect to main app
|
||||
await expect(page).toHaveURL(/\/app\/(dashboard|operations)/, { timeout: 5000 });
|
||||
}
|
||||
});
|
||||
|
||||
test('should complete onboarding and redirect to dashboard', async ({ page }) => {
|
||||
// Navigate through all steps quickly
|
||||
const maxSteps = 10;
|
||||
|
||||
for (let i = 0; i < maxSteps; i++) {
|
||||
// Look for Next button
|
||||
const nextButton = page.getByRole('button', { name: /next|siguiente|continuar/i });
|
||||
|
||||
if (!(await nextButton.isVisible().catch(() => false))) {
|
||||
// Might be at final step, look for Finish button
|
||||
const finishButton = page.getByRole('button', { name: /finish|complete|finalizar|completar/i });
|
||||
|
||||
if (await finishButton.isVisible().catch(() => false)) {
|
||||
await finishButton.click();
|
||||
break;
|
||||
} else {
|
||||
// No more steps
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await nextButton.click();
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
// After completing, should redirect to dashboard
|
||||
await expect(page).toHaveURL(/\/app/, { timeout: 10000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user