initial commit
This commit is contained in:
commit
e7987e88a7
70 changed files with 13661 additions and 0 deletions
82
web/tests/infinite-loop.spec.ts
Normal file
82
web/tests/infinite-loop.spec.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('E2E - Infinite Loop Detection', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Track all network requests
|
||||
const apiCalls: string[] = []
|
||||
page.on('request', request => {
|
||||
if (request.url().includes('/api/v1/')) {
|
||||
apiCalls.push(`${request.method()} ${request.url()}`)
|
||||
}
|
||||
})
|
||||
|
||||
await page.goto('http://localhost:3000')
|
||||
await page.waitForLoadState('networkidle')
|
||||
})
|
||||
|
||||
test('should not make repeated API calls after initial load', async ({ page }) => {
|
||||
const initialApiCalls = await page.evaluate(() => {
|
||||
return (window as any).__apiCallCount || 0
|
||||
})
|
||||
|
||||
// Wait for initial load
|
||||
await page.waitForSelector('text=Services & Expertise')
|
||||
await page.waitForSelector('text=Technical Skills')
|
||||
|
||||
// Wait a bit more to catch any delayed calls
|
||||
await page.waitForTimeout(3000)
|
||||
|
||||
const finalApiCalls = await page.evaluate(() => {
|
||||
return (window as any).__apiCallCount || 0
|
||||
})
|
||||
|
||||
// Should not have made additional API calls
|
||||
expect(finalApiCalls).toBeLessThanOrEqual(initialApiCalls + 1)
|
||||
})
|
||||
|
||||
test('should load all sections without errors', async ({ page }) => {
|
||||
await expect(page.locator('text=Services & Expertise')).toBeVisible()
|
||||
await expect(page.locator('text=Selected Projects')).toBeVisible()
|
||||
await expect(page.locator('text=Technical Skills')).toBeVisible()
|
||||
await expect(page.locator('text=Experience')).toBeVisible()
|
||||
await expect(page.locator('text=Let\\'s Build Something Great')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should handle navigation without duplicate fetches', async ({ page }) => {
|
||||
// Scroll to trigger any lazy loading
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight))
|
||||
await page.waitForTimeout(1000)
|
||||
await page.evaluate(() => window.scrollTo(0, 0))
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// Check for console errors
|
||||
const errors: string[] = []
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error') {
|
||||
errors.push(msg.text())
|
||||
}
|
||||
})
|
||||
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Filter out known non-critical errors
|
||||
const criticalErrors = errors.filter(e =>
|
||||
!e.includes('favicon') &&
|
||||
!e.includes('404') &&
|
||||
!e.includes('DevTools')
|
||||
)
|
||||
|
||||
expect(criticalErrors.length).toBe(0)
|
||||
})
|
||||
|
||||
test('contact form submission works', async ({ page }) => {
|
||||
await page.locator('input[name="name"]').fill('John Doe')
|
||||
await page.locator('input[name="email"]').fill('john@example.com')
|
||||
await page.locator('input[name="subject"]').fill('Test Subject')
|
||||
await page.locator('textarea[name="message"]').fill('This is a test message for the contact form.')
|
||||
|
||||
await page.click('button:has-text("Send Message")')
|
||||
|
||||
await expect(page.locator('text=Message Sent!')).toBeVisible({ timeout: 10000 })
|
||||
})
|
||||
})
|
||||
73
web/tests/network-monitoring.spec.ts
Normal file
73
web/tests/network-monitoring.spec.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Network Request Monitoring', () => {
|
||||
test('tracks API calls to detect infinite loops', async ({ page }) => {
|
||||
const apiCalls: { url: string; timestamp: number; count: number }[] = []
|
||||
const urlCounts = new Map<string, number>()
|
||||
|
||||
page.on('request', request => {
|
||||
const url = request.url()
|
||||
if (url.includes('/api/v1/')) {
|
||||
const count = (urlCounts.get(url) || 0) + 1
|
||||
urlCounts.set(url, count)
|
||||
apiCalls.push({ url, timestamp: Date.now(), count })
|
||||
}
|
||||
})
|
||||
|
||||
await page.goto('http://localhost:3000')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForSelector('text=Technical Skills')
|
||||
|
||||
// Wait for any potential delayed calls
|
||||
await page.waitForTimeout(5000)
|
||||
|
||||
// Check for duplicate calls to the same endpoint
|
||||
const duplicateCalls = Array.from(urlCounts.entries())
|
||||
.filter(([_, count]) => count > 1)
|
||||
.map(([url, count]) => ({ url, count }))
|
||||
|
||||
console.log('API Call counts:', Object.fromEntries(urlCounts))
|
||||
console.log('Duplicate calls:', duplicateCalls)
|
||||
|
||||
// Allow 1 call per endpoint, but flag if any endpoint is called more than twice
|
||||
const excessiveCalls = duplicateCalls.filter(d => d.count > 2)
|
||||
expect(excessiveCalls.length).toBe(0)
|
||||
})
|
||||
|
||||
test('monitors fetch calls for repeated patterns', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000')
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Inject monitoring script
|
||||
await page.addInitScript(() => {
|
||||
const originalFetch = window.fetch
|
||||
const callLog: { url: string; count: number }[] = []
|
||||
|
||||
window.fetch = async function(...args) {
|
||||
const url = args[0]?.toString() || ''
|
||||
if (url.includes('/api/v1/')) {
|
||||
const existing = callLog.find(c => c.url === url)
|
||||
if (existing) {
|
||||
existing.count++
|
||||
} else {
|
||||
callLog.push({ url, count: 1 })
|
||||
}
|
||||
}
|
||||
return originalFetch.apply(this, args)
|
||||
}
|
||||
|
||||
;(window as any).__getApiCallLog = () => callLog
|
||||
})
|
||||
|
||||
await page.waitForSelector('text=Technical Skills')
|
||||
await page.waitForTimeout(3000)
|
||||
|
||||
const callLog = await page.evaluate(() => (window as any).__getApiCallLog())
|
||||
|
||||
console.log('Fetch call log:', callLog)
|
||||
|
||||
// Check for excessive calls
|
||||
const excessive = callLog.filter((c: { count: number }) => c.count > 2)
|
||||
expect(excessive.length).toBe(0)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue