mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Generated by Spark: Run npm run test:e2e --if-present || echo "No E2E tests configured"
> spark-template@0.0.0 test:e2e > playwright test [WebServer] [WebServer] > spark-template@0.0.0 dev [WebServer] > vite [WebServer] [WebServer] [WebServer] VITE v7.3.1 ready in 272 ms [WebServer] [WebServer] ➜ Local: http://localhost:5000/ [WebServer] ➜ Network: http://10.1.0.146:5000/ Error: Timed out waiting 180000ms from config.webServer. No E2E tests configured
This commit is contained in:
72
E2E_TEST_FIX.md
Normal file
72
E2E_TEST_FIX.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# E2E Test Configuration Fix
|
||||
|
||||
## Problem
|
||||
Playwright E2E tests were timing out with the error:
|
||||
```
|
||||
Error: Timed out waiting 180000ms from config.webServer.
|
||||
```
|
||||
|
||||
## Root Cause
|
||||
**Port mismatch** between Playwright configuration and Vite dev server:
|
||||
- `playwright.config.ts` was configured to expect server on port **5173** (Vite's default)
|
||||
- `vite.config.ts` was configured to run server on port **5000**
|
||||
|
||||
This caused Playwright to wait for a server that would never respond on the expected port.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Fixed Port Configuration in `playwright.config.ts`
|
||||
- Changed `baseURL` from `http://localhost:5173` → `http://localhost:5000`
|
||||
- Changed `webServer.url` from `http://localhost:5173` → `http://localhost:5000`
|
||||
- Reduced `webServer.timeout` from `180000ms` → `120000ms` (2 minutes)
|
||||
- Reduced `timeout` from `60000ms` → `45000ms` per test
|
||||
- Reduced `expect.timeout` from `15000ms` → `10000ms`
|
||||
- Reduced `actionTimeout` from `15000ms` → `10000ms`
|
||||
- Reduced `navigationTimeout` from `30000ms` → `20000ms`
|
||||
|
||||
### 2. Optimized Test Files
|
||||
|
||||
#### `e2e/smoke.spec.ts`
|
||||
- Replaced `page.waitForTimeout()` with `page.waitForLoadState('networkidle')` for more reliable waits
|
||||
- Added explicit timeout values to all `page.goto()` calls
|
||||
- Reduced individual test timeouts (20-30s instead of 30-45s)
|
||||
- More efficient waiting strategies
|
||||
|
||||
#### `e2e/codeforge.spec.ts`
|
||||
- Same optimizations as smoke tests
|
||||
- Better handling of async operations
|
||||
- Explicit timeouts prevent hanging
|
||||
|
||||
## Benefits
|
||||
1. ✅ Tests now connect to correct port
|
||||
2. ✅ Faster test execution (no arbitrary waits)
|
||||
3. ✅ More reliable (networkidle vs fixed timeouts)
|
||||
4. ✅ Better timeout management per test
|
||||
5. ✅ Clearer failure messages when tests do fail
|
||||
|
||||
## Test Execution
|
||||
Run E2E tests with:
|
||||
```bash
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
Or with the fallback:
|
||||
```bash
|
||||
npm run test:e2e --if-present || echo "No E2E tests configured"
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
The tests will now:
|
||||
- Start the dev server on port 5000
|
||||
- Wait up to 2 minutes for server to be ready
|
||||
- Run tests with appropriate per-test timeouts
|
||||
- Retry failed tests 2x in CI environments
|
||||
- Generate HTML reports
|
||||
|
||||
## Future Improvements
|
||||
Consider adding:
|
||||
- More granular test timeouts based on test complexity
|
||||
- Test parallelization configuration
|
||||
- Screenshot comparison tests
|
||||
- Visual regression testing
|
||||
- API mocking for faster, more isolated tests
|
||||
@@ -2,9 +2,9 @@ import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('CodeForge - Core Functionality', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
test.setTimeout(20000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
})
|
||||
|
||||
test('should load the application successfully', async ({ page }) => {
|
||||
@@ -13,7 +13,7 @@ test.describe('CodeForge - Core Functionality', () => {
|
||||
|
||||
test('should display main navigation', async ({ page }) => {
|
||||
const tabList = page.locator('[role="tablist"]').first()
|
||||
await expect(tabList).toBeVisible({ timeout: 10000 })
|
||||
await expect(tabList).toBeVisible({ timeout: 5000 })
|
||||
})
|
||||
|
||||
test('should switch between tabs', async ({ page }) => {
|
||||
@@ -22,44 +22,43 @@ test.describe('CodeForge - Core Functionality', () => {
|
||||
|
||||
if (tabCount > 1) {
|
||||
await tabs.nth(1).click()
|
||||
await page.waitForTimeout(500)
|
||||
await expect(page.locator('[role="tabpanel"]:visible')).toBeVisible()
|
||||
await expect(page.locator('[role="tabpanel"]:visible')).toBeVisible({ timeout: 3000 })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('CodeForge - Code Editor', () => {
|
||||
test('should display Monaco editor', async ({ page }) => {
|
||||
test.setTimeout(45000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
test.setTimeout(30000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
const codeEditorTab = page.locator('button[role="tab"]').filter({ hasText: /Code Editor/i }).first()
|
||||
if (await codeEditorTab.isVisible({ timeout: 5000 })) {
|
||||
if (await codeEditorTab.isVisible({ timeout: 3000 })) {
|
||||
await codeEditorTab.click()
|
||||
await page.waitForTimeout(3000)
|
||||
await page.waitForLoadState('networkidle', { timeout: 10000 })
|
||||
|
||||
const monacoEditor = page.locator('.monaco-editor').first()
|
||||
await expect(monacoEditor).toBeVisible({ timeout: 20000 })
|
||||
await expect(monacoEditor).toBeVisible({ timeout: 15000 })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('CodeForge - Responsive Design', () => {
|
||||
test('should work on mobile viewport', async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
test.setTimeout(20000)
|
||||
await page.setViewportSize({ width: 375, height: 667 })
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should work on tablet viewport', async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
test.setTimeout(20000)
|
||||
await page.setViewportSize({ width: 768, height: 1024 })
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
|
||||
@@ -2,43 +2,41 @@ import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('CodeForge - Smoke Tests', () => {
|
||||
test('app loads successfully', async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
test.setTimeout(20000)
|
||||
await page.goto('/', { waitUntil: 'networkidle', timeout: 15000 })
|
||||
|
||||
await expect(page.locator('body')).toBeVisible({ timeout: 10000 })
|
||||
await page.waitForTimeout(2000)
|
||||
await expect(page.locator('body')).toBeVisible({ timeout: 5000 })
|
||||
})
|
||||
|
||||
test('can navigate to dashboard tab', async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
test.setTimeout(20000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
const dashboardTab = page.locator('button[role="tab"]').filter({ hasText: /Dashboard/i }).first()
|
||||
if (await dashboardTab.isVisible({ timeout: 5000 })) {
|
||||
if (await dashboardTab.isVisible({ timeout: 3000 })) {
|
||||
await dashboardTab.click()
|
||||
await page.waitForTimeout(500)
|
||||
await expect(page.locator('[role="tabpanel"]:visible')).toBeVisible({ timeout: 5000 })
|
||||
await expect(page.locator('[role="tabpanel"]:visible')).toBeVisible({ timeout: 3000 })
|
||||
}
|
||||
})
|
||||
|
||||
test('Monaco editor loads in code editor', async ({ page }) => {
|
||||
test.setTimeout(45000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(2000)
|
||||
test.setTimeout(30000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
const codeEditorTab = page.locator('button[role="tab"]').filter({ hasText: /Code Editor/i }).first()
|
||||
if (await codeEditorTab.isVisible({ timeout: 5000 })) {
|
||||
if (await codeEditorTab.isVisible({ timeout: 3000 })) {
|
||||
await codeEditorTab.click()
|
||||
await page.waitForTimeout(3000)
|
||||
await page.waitForLoadState('networkidle', { timeout: 10000 })
|
||||
|
||||
const monaco = page.locator('.monaco-editor').first()
|
||||
await expect(monaco).toBeVisible({ timeout: 20000 })
|
||||
await expect(monaco).toBeVisible({ timeout: 15000 })
|
||||
}
|
||||
})
|
||||
|
||||
test('no critical console errors', async ({ page }) => {
|
||||
test.setTimeout(30000)
|
||||
test.setTimeout(20000)
|
||||
const errors: string[] = []
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
@@ -46,8 +44,8 @@ test.describe('CodeForge - Smoke Tests', () => {
|
||||
}
|
||||
})
|
||||
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded' })
|
||||
await page.waitForTimeout(3000)
|
||||
await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 10000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 })
|
||||
|
||||
const criticalErrors = errors.filter(e =>
|
||||
!e.includes('Download the React DevTools') &&
|
||||
|
||||
@@ -7,16 +7,16 @@ export default defineConfig({
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: 'html',
|
||||
timeout: 60000,
|
||||
timeout: 45000,
|
||||
expect: {
|
||||
timeout: 15000,
|
||||
timeout: 10000,
|
||||
},
|
||||
use: {
|
||||
baseURL: 'http://localhost:5173',
|
||||
baseURL: 'http://localhost:5000',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
actionTimeout: 15000,
|
||||
navigationTimeout: 30000,
|
||||
actionTimeout: 10000,
|
||||
navigationTimeout: 20000,
|
||||
},
|
||||
|
||||
projects: [
|
||||
@@ -28,9 +28,9 @@ export default defineConfig({
|
||||
|
||||
webServer: {
|
||||
command: 'npm run dev',
|
||||
url: 'http://localhost:5173',
|
||||
url: 'http://localhost:5000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 180000,
|
||||
timeout: 120000,
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user