Skip to content

Commit 755c925

Browse files
committed
fix(site): e2e: wait until port is available)
1 parent aca5be5 commit 755c925

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

site/e2e/helpers.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type ChildProcess, exec, spawn } from "node:child_process";
22
import { randomUUID } from "node:crypto";
33
import path from "node:path";
44
import { Duplex } from "node:stream";
5+
import net from "node:net";
56
import { type BrowserContext, type Page, expect, test } from "@playwright/test";
67
import { API } from "api/api";
78
import type {
@@ -685,6 +686,8 @@ export class Awaiter {
685686
export const createServer = async (
686687
port: number,
687688
): Promise<ReturnType<typeof express>> => {
689+
await waitForPort(port); // Wait until the port is available
690+
688691
const e = express();
689692
// We need to specify the local IP address as the web server
690693
// tends to fail with IPv6 related error:
@@ -693,6 +696,36 @@ export const createServer = async (
693696
return e;
694697
};
695698

699+
async function waitForPort(port: number, host = "0.0.0.0", timeout = 5000): Promise<void> {
700+
const start = Date.now();
701+
while (Date.now() - start < timeout) {
702+
const available = await isPortAvailable(port, host);
703+
if (available) {
704+
return;
705+
}
706+
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait 1 second before retrying
707+
}
708+
throw new Error(`Timeout: port ${port} is still in use after ${timeout / 1000} seconds.`);
709+
}
710+
711+
function isPortAvailable(port: number, host = "0.0.0.0"): Promise<boolean> {
712+
return new Promise((resolve) => {
713+
const probe = net.createServer()
714+
.once('error', (err: any) => {
715+
if (err.code === 'EADDRINUSE') {
716+
resolve(false); // port is in use
717+
} else {
718+
resolve(false); // some other error occurred
719+
}
720+
})
721+
.once('listening', () => {
722+
probe.close();
723+
resolve(true); // port is available
724+
})
725+
.listen(port, host);
726+
});
727+
}
728+
696729
export const findSessionToken = async (page: Page): Promise<string> => {
697730
const cookies = await page.context().cookies();
698731
const sessionCookie = cookies.find((c) => c.name === "coder_session_token");

0 commit comments

Comments
 (0)