mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): wait until port is available in e2e (#15537)
Related: https://github.com/coder/internal/issues/212 This PR modifies the logic responsible for creating a server in E2E tests to check if the port is free. Alternatively, we could refactor the framework to dynamically create server instances, but this solution might be a cheaper quick win. Note: I'll leave it as is now, it might be worth asking somebody with a frontend skillset to double-check this contribution. --------- Signed-off-by: Danny Kopping <danny@coder.com> Co-authored-by: Danny Kopping <danny@coder.com>
This commit is contained in:
co-authored by
Danny Kopping
parent
5861e516b9
commit
8ca8e016fa
@@ -1,5 +1,6 @@
|
||||
import { type ChildProcess, exec, spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import net from "node:net";
|
||||
import path from "node:path";
|
||||
import { Duplex } from "node:stream";
|
||||
import { type BrowserContext, type Page, expect, test } from "@playwright/test";
|
||||
@@ -687,6 +688,8 @@ export class Awaiter {
|
||||
export const createServer = async (
|
||||
port: number,
|
||||
): Promise<ReturnType<typeof express>> => {
|
||||
await waitForPort(port); // Wait until the port is available
|
||||
|
||||
const e = express();
|
||||
// We need to specify the local IP address as the web server
|
||||
// tends to fail with IPv6 related error:
|
||||
@@ -695,6 +698,44 @@ export const createServer = async (
|
||||
return e;
|
||||
};
|
||||
|
||||
async function waitForPort(
|
||||
port: number,
|
||||
host = "0.0.0.0",
|
||||
timeout = 30000,
|
||||
): Promise<void> {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeout) {
|
||||
const available = await isPortAvailable(port, host);
|
||||
if (available) {
|
||||
return;
|
||||
}
|
||||
console.warn(`${host}:${port} is in use, checking again in 1s`);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second before retrying
|
||||
}
|
||||
throw new Error(
|
||||
`Timeout: port ${port} is still in use after ${timeout / 1000} seconds.`,
|
||||
);
|
||||
}
|
||||
|
||||
function isPortAvailable(port: number, host = "0.0.0.0"): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const probe = net
|
||||
.createServer()
|
||||
.once("error", (err: NodeJS.ErrnoException) => {
|
||||
if (err.code === "EADDRINUSE") {
|
||||
resolve(false); // port is in use
|
||||
} else {
|
||||
resolve(false); // some other error occurred
|
||||
}
|
||||
})
|
||||
.once("listening", () => {
|
||||
probe.close();
|
||||
resolve(true); // port is available
|
||||
})
|
||||
.listen(port, host);
|
||||
});
|
||||
}
|
||||
|
||||
export const findSessionToken = async (page: Page): Promise<string> => {
|
||||
const cookies = await page.context().cookies();
|
||||
const sessionCookie = cookies.find((c) => c.name === "coder_session_token");
|
||||
|
||||
Reference in New Issue
Block a user