Compare commits

..

2 Commits

Author SHA1 Message Date
gpt-engineer-app[bot]
4a18462c37 Add delay countdown UI progress
Introduce visible countdown indicators for rate-limit delays between tests:
- Extend test runner to emit and expose delay progress updates.
- Update IntegrationTestRunner UI to display countdown while pausing.
- Ensure users see why tests are paused during delays.
2025-11-10 17:34:53 +00:00
gpt-engineer-app[bot]
f7f22f4817 Add delays between tests
Introduce automatic delay between test executions in the test runner to prevent rate limiting. Added a delayBetweenTests config (default 2.5s), a delay() helper, and updated runSuite to wait between tests. This helps avoid "Too many submissions in a short time" errors during test runs.
2025-11-10 17:33:43 +00:00
2 changed files with 53 additions and 5 deletions

View File

@@ -264,11 +264,13 @@ export function IntegrationTestRunner() {
{results.map(result => ( {results.map(result => (
<Collapsible key={result.id}> <Collapsible key={result.id}>
<div className="flex items-start gap-3 p-3 rounded-lg border bg-card"> <div className="flex items-start gap-3 p-3 rounded-lg border bg-card">
<div className="pt-0.5"> <div className="pt-0.5">
{result.status === 'pass' && <CheckCircle2 className="w-4 h-4 text-green-500" />} {result.status === 'pass' && <CheckCircle2 className="w-4 h-4 text-green-500" />}
{result.status === 'fail' && <XCircle className="w-4 h-4 text-destructive" />} {result.status === 'fail' && <XCircle className="w-4 h-4 text-destructive" />}
{result.status === 'skip' && <SkipForward className="w-4 h-4 text-muted-foreground" />} {result.status === 'skip' && !result.name.includes('⏳') && <SkipForward className="w-4 h-4 text-muted-foreground" />}
{result.status === 'running' && <Clock className="w-4 h-4 text-blue-500 animate-pulse" />} {result.status === 'skip' && result.name.includes('⏳') && <Clock className="w-4 h-4 text-muted-foreground" />}
{result.status === 'running' && !result.name.includes('⏳') && <Clock className="w-4 h-4 text-blue-500 animate-pulse" />}
{result.status === 'running' && result.name.includes('⏳') && <Clock className="w-4 h-4 text-amber-500 animate-pulse" />}
</div> </div>
<div className="flex-1 space-y-1"> <div className="flex-1 space-y-1">
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">

View File

@@ -51,9 +51,18 @@ export class IntegrationTestRunner {
private isRunning = false; private isRunning = false;
private shouldStop = false; private shouldStop = false;
private onProgress?: (result: TestResult) => void; private onProgress?: (result: TestResult) => void;
private delayBetweenTests: number;
constructor(onProgress?: (result: TestResult) => void) { constructor(onProgress?: (result: TestResult) => void, delayBetweenTests: number = 2500) {
this.onProgress = onProgress; this.onProgress = onProgress;
this.delayBetweenTests = delayBetweenTests; // Default 2.5 seconds to prevent rate limiting
}
/**
* Wait for specified milliseconds (for rate limiting prevention)
*/
private async delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
} }
/** /**
@@ -123,13 +132,50 @@ export class IntegrationTestRunner {
async runSuite(suite: TestSuite): Promise<TestResult[]> { async runSuite(suite: TestSuite): Promise<TestResult[]> {
const suiteResults: TestResult[] = []; const suiteResults: TestResult[] = [];
for (const test of suite.tests) { for (let i = 0; i < suite.tests.length; i++) {
const test = suite.tests[i];
const result = await this.runTest(test, suite.name); const result = await this.runTest(test, suite.name);
suiteResults.push(result); suiteResults.push(result);
if (this.shouldStop) { if (this.shouldStop) {
break; break;
} }
// Add delay between tests to prevent rate limiting (except after the last test)
if (i < suite.tests.length - 1 && this.delayBetweenTests > 0) {
// Report delay status with countdown
const delaySeconds = this.delayBetweenTests / 1000;
const delayResult: TestResult = {
id: `delay-${Date.now()}`,
name: `⏳ Rate limit delay: ${delaySeconds}s`,
suite: suite.name,
status: 'running',
duration: 0,
timestamp: new Date().toISOString(),
details: {
reason: 'Pausing to prevent rate limiting',
delayMs: this.delayBetweenTests
}
};
if (this.onProgress) {
this.onProgress(delayResult);
}
await this.delay(this.delayBetweenTests);
// Mark delay as complete
const delayCompleteResult: TestResult = {
...delayResult,
status: 'skip',
duration: this.delayBetweenTests,
details: { reason: 'Rate limit delay completed' }
};
if (this.onProgress) {
this.onProgress(delayCompleteResult);
}
}
} }
return suiteResults; return suiteResults;