Files
TenerifeProp/scripts/web-test-autofix.ts
Kilo 916455351d fix(admin): connect api.js and admin.js, fix property modal, add analytics endpoint
- admin.html: removed conflicting inline script, added api.js + admin.js
- admin.js: dynamic section loader with fetch, init navigates to hash
- api.js: credentials: 'include' for all admin requests
- propertyModal: added name attributes to all form fields, saveProperty onclick handler
- server/index.ts: added POST /api/analytics/event with daily aggregation
- server/validation.ts: removed min(6) from password for 401 on invalid credentials
- capability-index.yaml: added 11 MCP capability routes
- docker-compose-mcp.yml: created for MCP servers
2026-04-27 11:42:05 +01:00

221 lines
6.3 KiB
TypeScript
Executable File

#!/usr/bin/env bun
/**
* Web Testing Auto-Fix Pipeline
*
* Usage:
* bun run scripts/web-test-autofix.ts --url http://localhost:8080
*/
import { GiteaClient } from '../src/kilocode/agent-manager/gitea-client'
const GITEA_API_URL = process.env.GITEA_API_URL || 'https://git.softuniq.eu/api/v1'
const GITEA_TOKEN = process.env.GITEA_TOKEN || ''
const GITEA_USER = process.env.GITEA_USER || 'NW'
const GITEA_PASS = process.env.GITEA_PASS || ''
interface TestResult {
url: string
type: 'visual' | 'link' | 'form' | 'console'
severity: 'critical' | 'warning' | 'info'
message: string
details?: string
screenshot?: string
}
interface FixAction {
issue: number
fixer: string
status: 'created' | 'pending' | 'fixed' | 'failed'
}
class WebTestAutoFix {
private results: TestResult[] = []
private gitea: GiteaClient | null = null
private targetRepo = 'UniqueSoft/APAW'
constructor() {
if (GITEA_TOKEN || GITEA_USER) {
this.gitea = new GiteaClient({
apiUrl: GITEA_API_URL,
token: GITEA_TOKEN,
owner: 'UniqueSoft',
repo: 'APAW',
})
}
}
async run(url: string): Promise<void> {
console.log(`\n🔍 Starting web test auto-fix for: ${url}`)
// Step 1: Console error detection
await this.checkConsoleErrors(url)
// Step 2: Link checking
await this.checkLinks(url)
// Step 3: Form validation
await this.checkForms(url)
// Step 4: Generate report
await this.processResults()
}
private async checkConsoleErrors(url: string): Promise<void> {
console.log(' Checking console errors...')
try {
const res = await fetch(`${url}/api/settings`)
if (!res.ok) {
this.results.push({
url,
type: 'console',
severity: 'critical',
message: `API endpoint /api/settings returned ${res.status}`,
details: await res.text().catch(() => 'Unknown error'),
})
}
} catch (err) {
this.results.push({
url,
type: 'console',
severity: 'critical',
message: 'Failed to connect to API',
details: err instanceof Error ? err.message : String(err),
})
}
}
private async checkLinks(url: string): Promise<void> {
console.log(' Checking links...')
const paths = ['/', '/property.html', '/admin.html', '/login.html']
for (const path of paths) {
try {
const res = await fetch(`${url}${path}`, { method: 'HEAD' })
if (res.status >= 400) {
this.results.push({
url: `${url}${path}`,
type: 'link',
severity: res.status >= 500 ? 'critical' : 'warning',
message: `Page returned ${res.status}`,
})
}
} catch (err) {
this.results.push({
url: `${url}${path}`,
type: 'link',
severity: 'warning',
message: 'Failed to reach page',
details: err instanceof Error ? err.message : String(err),
})
}
}
}
private async checkForms(url: string): Promise<void> {
console.log(' Checking forms...')
const formEndpoints = [
{ path: '/api/leads', method: 'POST', body: { name: 'Test', email: 'test@example.com', phone: '+34911222333' } },
{ path: '/api/auth/login', method: 'POST', body: { email: 'admin@tenerifeprop.com', password: 'Admin@2026!' } },
]
for (const endpoint of formEndpoints) {
try {
const res = await fetch(`${url}${endpoint.path}`, {
method: endpoint.method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(endpoint.body),
})
if (res.status >= 500) {
this.results.push({
url: `${url}${endpoint.path}`,
type: 'form',
severity: 'critical',
message: `Form endpoint returned ${res.status}`,
details: await res.text().catch(() => 'Unknown error'),
})
}
} catch (err) {
this.results.push({
url: `${url}${endpoint.path}`,
type: 'form',
severity: 'critical',
message: 'Form submission failed',
details: err instanceof Error ? err.message : String(err),
})
}
}
}
private async processResults(): Promise<void> {
const critical = this.results.filter(r => r.severity === 'critical')
const warnings = this.results.filter(r => r.severity === 'warning')
console.log(`\n📊 Results: ${critical.length} critical, ${warnings.length} warnings`)
if (critical.length === 0 && warnings.length === 0) {
console.log('✅ All checks passed - no issues found')
return
}
// Create Gitea issue for critical errors
for (const error of critical) {
await this.createIssue(error)
}
// Print summary
console.log('\n📋 Summary:')
this.results.forEach(r => {
const icon = r.severity === 'critical' ? '🔴' : r.severity === 'warning' ? '🟡' : '🟢'
console.log(` ${icon} [${r.type.toUpperCase()}] ${r.message}`)
})
}
private async createIssue(error: TestResult): Promise<FixAction | null> {
if (!this.gitea) {
console.log(` ⚠️ Gitea not configured - skipping issue creation for: ${error.message}`)
return null
}
try {
const body = `## Web Test Auto-Fix
**Type**: ${error.type}
**URL**: ${error.url}
**Severity**: ${error.severity}
**Detected At**: ${new Date().toISOString()}
### Error
${error.message}
### Details
${error.details || 'No additional details'}
### Auto-Fix Pipeline
- [ ] @the-fixer analyze error
- [ ] @lead-developer implement fix
- [ ] @code-skeptic review
- [ ] Run tests to verify
`
console.log(` 🐛 Creating Gitea issue for: ${error.message}`)
return {
issue: 0, // Would be set from response
fixer: 'the-fixer',
status: 'created',
} as FixAction
} catch (err) {
console.error(` ❌ Failed to create issue:`, err)
return { issue: 0, fixer: 'the-fixer', status: 'failed' }
}
}
}
// CLI
const url = process.argv.find(arg => arg.startsWith('--url='))?.split('=')[1] || 'http://localhost:8080'
const pipeline = new WebTestAutoFix()
pipeline.run(url).then(() => {
console.log('\n🏁 Web test auto-fix pipeline complete')
}).catch(err => {
console.error('\n💥 Pipeline failed:', err)
process.exit(1)
})