feat: implement v0.4.0 - Reports, Charts, Comparison, Dark Mode, E2E Testing
Backend (@backend-dev): - Add ReportService with PDF/CSV generation (reportlab, pandas) - Implement Report API endpoints (POST, GET, DELETE, download) - Add ReportRepository and schemas - Configure storage with auto-cleanup (30 days) - Rate limiting: 10 downloads/minute - Professional PDF templates with charts support Frontend (@frontend-dev): - Integrate Recharts for data visualization - Add CostBreakdown, TimeSeries, ComparisonBar charts - Implement scenario comparison page with multi-select - Add dark/light mode toggle with ThemeProvider - Create Reports page with generation form and list - Add new UI components: checkbox, dialog, tabs, label, skeleton - Implement useComparison and useReports hooks QA (@qa-engineer): - Setup Playwright E2E testing framework - Create 7 test spec files with 94 test cases - Add visual regression testing with baselines - Configure multi-browser testing (Chrome, Firefox, WebKit) - Add mobile responsive tests - Create test fixtures and helpers - Setup GitHub Actions CI workflow Documentation (@spec-architect): - Create detailed kanban-v0.4.0.md with 27 tasks - Update progress.md with v0.4.0 tracking - Create v0.4.0 planning prompt Features: ✅ PDF/CSV Report Generation ✅ Interactive Charts (Pie, Area, Bar) ✅ Scenario Comparison (2-4 scenarios) ✅ Dark/Light Mode Toggle ✅ E2E Test Suite (94 tests) Dependencies added: - Backend: reportlab, pandas, slowapi - Frontend: recharts, date-fns, @radix-ui/react-checkbox/dialog/tabs - Testing: @playwright/test 27 tasks completed, 100% v0.4.0 implementation
This commit is contained in:
129
frontend/e2e/setup-verification.spec.ts
Normal file
129
frontend/e2e/setup-verification.spec.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* E2E Test: Setup Verification
|
||||
*
|
||||
* This test file verifies that the E2E test environment is properly configured.
|
||||
* Run this first to ensure everything is working correctly.
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { navigateTo, waitForLoading } from './utils/test-helpers';
|
||||
|
||||
test.describe('E2E Setup Verification', () => {
|
||||
test('frontend dev server is running', async ({ page }) => {
|
||||
await navigateTo(page, '/');
|
||||
|
||||
// Verify the page loads
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
|
||||
// Check for either dashboard or loading state
|
||||
const bodyText = await page.locator('body').textContent();
|
||||
expect(bodyText).toBeTruthy();
|
||||
expect(bodyText!.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('backend API is accessible', async ({ request }) => {
|
||||
// Try to access the API health endpoint or scenarios endpoint
|
||||
const response = await request.get('http://localhost:8000/api/v1/scenarios', {
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// Should get 200 OK
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
// Response should be JSON
|
||||
const contentType = response.headers()['content-type'];
|
||||
expect(contentType).toContain('application/json');
|
||||
|
||||
// Should have expected structure
|
||||
const data = await response.json();
|
||||
expect(data).toHaveProperty('items');
|
||||
expect(data).toHaveProperty('total');
|
||||
expect(Array.isArray(data.items)).toBe(true);
|
||||
});
|
||||
|
||||
test('CORS is configured correctly', async ({ request }) => {
|
||||
const response = await request.get('http://localhost:8000/api/v1/scenarios', {
|
||||
headers: {
|
||||
'Origin': 'http://localhost:5173',
|
||||
},
|
||||
});
|
||||
|
||||
// Check CORS headers
|
||||
const corsHeader = response.headers()['access-control-allow-origin'];
|
||||
expect(corsHeader).toBeTruthy();
|
||||
});
|
||||
|
||||
test('all required browsers are available', async ({ browserName }) => {
|
||||
// This test will run on all configured browsers
|
||||
// If it passes, the browser is properly installed
|
||||
expect(['chromium', 'firefox', 'webkit']).toContain(browserName);
|
||||
});
|
||||
|
||||
test('screenshots can be captured', async ({ page }) => {
|
||||
await navigateTo(page, '/');
|
||||
await waitForLoading(page);
|
||||
|
||||
// Take a screenshot
|
||||
const screenshot = await page.screenshot();
|
||||
|
||||
// Verify screenshot is not empty
|
||||
expect(screenshot).toBeTruthy();
|
||||
expect(screenshot.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('localStorage and sessionStorage work', async ({ page }) => {
|
||||
await navigateTo(page, '/');
|
||||
|
||||
// Test localStorage
|
||||
await page.evaluate(() => {
|
||||
localStorage.setItem('e2e-test', 'test-value');
|
||||
});
|
||||
|
||||
const localValue = await page.evaluate(() => {
|
||||
return localStorage.getItem('e2e-test');
|
||||
});
|
||||
|
||||
expect(localValue).toBe('test-value');
|
||||
|
||||
// Clean up
|
||||
await page.evaluate(() => {
|
||||
localStorage.removeItem('e2e-test');
|
||||
});
|
||||
});
|
||||
|
||||
test('network interception works', async ({ page }) => {
|
||||
// Intercept API calls
|
||||
const apiCalls: string[] = [];
|
||||
|
||||
await page.route('**/api/**', async (route) => {
|
||||
apiCalls.push(route.request().url());
|
||||
await route.continue();
|
||||
});
|
||||
|
||||
await navigateTo(page, '/');
|
||||
await waitForLoading(page);
|
||||
|
||||
// Verify we intercepted API calls
|
||||
expect(apiCalls.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Environment Variables', () => {
|
||||
test('required environment variables are set', () => {
|
||||
// Verify CI environment if applicable
|
||||
if (process.env.CI) {
|
||||
expect(process.env.CI).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
test('test data directories exist', async () => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const fixturesDir = path.join(__dirname, 'fixtures');
|
||||
const screenshotsDir = path.join(__dirname, 'screenshots');
|
||||
|
||||
expect(fs.existsSync(fixturesDir)).toBe(true);
|
||||
expect(fs.existsSync(screenshotsDir)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user