Skip to content

Commit 6f65ade

Browse files
CopilotHexagon
andauthored
Fix timeout clearTimeout bug and edge case handling in bun/deno shims (#15)
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
1 parent b61db86 commit 6f65ade

4 files changed

Lines changed: 51 additions & 11 deletions

File tree

mod.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,27 @@ test("Three-Level Nesting with Mixed Operations", async (context) => {
250250

251251
assertEquals(executionCount, 4);
252252
});
253+
254+
// Test timeout with zero value (should be treated as no timeout)
255+
test("Test with timeout = 0 (no timeout)", async () => {
256+
await delay(50);
257+
assertEquals(1, 1);
258+
}, { timeout: 0 });
259+
260+
// Test timeout with negative value (should be treated as no timeout)
261+
test("Test with negative timeout (no timeout)", async () => {
262+
await delay(50);
263+
assertEquals(1, 1);
264+
}, { timeout: -100 });
265+
266+
// Test that completes well within timeout
267+
test("Test completes within generous timeout", async () => {
268+
await delay(50);
269+
assertEquals(1, 1);
270+
}, { timeout: 5000 });
271+
272+
// Test longer execution with sufficient timeout (7 seconds with 10 second timeout)
273+
test("7 second execution with 10 second timeout", async () => {
274+
await delay(7000);
275+
assertEquals(1, 1);
276+
}, { timeout: 10000 });

shims/bun.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ export async function wrappedTest(
66
testFn: TestSubject,
77
options: WrappedTestOptions,
88
): Promise<void> {
9+
// Build Bun test options - pass timeout to Bun's native test runner
10+
// If timeout is 0 or not specified, Bun will use its default 5s timeout
11+
// If we're using custom timeout logic, we need to set a high value for Bun
12+
const bunOptions: { timeout?: number; skip?: boolean } = {
13+
skip: options?.skip || false,
14+
};
15+
16+
// If a timeout is specified and > 0, pass it to Bun's native timeout
17+
// This makes Bun's timeout and our custom timeout work together
18+
if (options.timeout && options.timeout > 0) {
19+
bunOptions.timeout = options.timeout;
20+
}
21+
922
return await test(name, async () => {
1023
// Create wrapped context with step method
1124
const wrappedContext: TestContext = {
@@ -87,7 +100,7 @@ export async function wrappedTest(
87100
});
88101
let timeoutId: number = -1; // Store the timeout ID
89102
try {
90-
if (options.timeout) {
103+
if (options.timeout && options.timeout > 0) {
91104
const timeoutPromise = new Promise((_, reject) => {
92105
timeoutId = setTimeout(() => {
93106
reject(new Error("Test timed out"));
@@ -98,13 +111,11 @@ export async function wrappedTest(
98111
// No timeout, just await testFn
99112
await options.waitForCallback ? callbackPromise : testFnPromise;
100113
}
101-
} catch (error) {
102-
throw error;
103114
} finally {
104-
if (timeoutId) clearTimeout(timeoutId);
115+
if (timeoutId !== -1) clearTimeout(timeoutId);
105116
// Make sure testFnPromise has completed
106117
await testFnPromise;
107118
if (options.waitForCallback) await callbackPromise;
108119
}
109-
});
120+
}, bunOptions);
110121
}

shims/deno.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export function wrappedTest(name: string, testFn: TestSubject, options: WrappedT
114114
});
115115
let timeoutId: number = -1; // Store the timeout ID
116116
try {
117-
if (options.timeout) {
117+
if (options.timeout && options.timeout > 0) {
118118
const timeoutPromise = new Promise((_, reject) => {
119119
timeoutId = setTimeout(() => {
120120
reject(new Error("Test timed out"));
@@ -124,10 +124,8 @@ export function wrappedTest(name: string, testFn: TestSubject, options: WrappedT
124124
} else {
125125
await options.waitForCallback ? callbackPromise : testFnPromise;
126126
}
127-
} catch (error) {
128-
throw error;
129127
} finally {
130-
if (timeoutId) clearTimeout(timeoutId);
128+
if (timeoutId !== -1) clearTimeout(timeoutId);
131129
await testFnPromise;
132130
if (options.waitForCallback) await callbackPromise;
133131
}

shims/node.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ import type { ContextStepFunction, SimpleStepFunction, StepOptions, StepSubject,
33
import type { TestSubject } from "../mod.ts";
44

55
function transformOptions(options?: WrappedTestOptions) {
6-
return {
6+
const nodeOptions: { skip: boolean; timeout?: number } = {
77
skip: options?.skip || false,
8-
timeout: options?.timeout,
98
};
9+
10+
// Node.js requires timeout to be > 0 and <= 2147483647
11+
// Only set timeout if it's a valid positive number
12+
if (options?.timeout && options.timeout > 0) {
13+
nodeOptions.timeout = options.timeout;
14+
}
15+
16+
return nodeOptions;
1017
}
1118

1219
// Helper function to create a fallback context for older Node versions

0 commit comments

Comments
 (0)