mirror of
https://github.com/logos-messaging/js-waku.git
synced 2026-01-03 14:23:12 +00:00
* feat(browser-tests): simplify, refactor, update dockerized browser node * Update packages/browser-tests/web/index.ts * fix: remove comments and console.logs from tests * fix: add temporary logging * fix: debugging static sharding * fix: replace console with logger * fix: remove use of any * fix: log dial error * fix: replace any with libp2p options * fix: remove unused logic around sourcing address.env * fix: uncomment log * fix: add more logging and fix tests * feat: add types for test-config * fix: add types to server.ts * fix: remove more uses of any * fix: remove use of any in endpoint handlers
129 lines
3.8 KiB
TypeScript
129 lines
3.8 KiB
TypeScript
import axios from "axios";
|
|
import { GenericContainer, StartedTestContainer } from "testcontainers";
|
|
import { Logger } from "@waku/utils";
|
|
|
|
const log = new Logger("container-helpers");
|
|
|
|
export interface ContainerSetupOptions {
|
|
environment?: Record<string, string>;
|
|
networkMode?: string;
|
|
timeout?: number;
|
|
maxAttempts?: number;
|
|
}
|
|
|
|
export interface ContainerSetupResult {
|
|
container: StartedTestContainer;
|
|
baseUrl: string;
|
|
}
|
|
|
|
/**
|
|
* Starts a waku-browser-tests Docker container with proper health checking.
|
|
* Follows patterns from @waku/tests package for retry logic and cleanup.
|
|
*/
|
|
export async function startBrowserTestsContainer(
|
|
options: ContainerSetupOptions = {}
|
|
): Promise<ContainerSetupResult> {
|
|
const {
|
|
environment = {},
|
|
networkMode = "bridge",
|
|
timeout = 2000,
|
|
maxAttempts = 60
|
|
} = options;
|
|
|
|
log.info("Starting waku-browser-tests container...");
|
|
|
|
let generic = new GenericContainer("waku-browser-tests:local")
|
|
.withExposedPorts(8080)
|
|
.withNetworkMode(networkMode);
|
|
|
|
// Apply environment variables
|
|
for (const [key, value] of Object.entries(environment)) {
|
|
generic = generic.withEnvironment({ [key]: value });
|
|
}
|
|
|
|
const container = await generic.start();
|
|
|
|
// Set up container logging - stream all output from the start
|
|
const logs = await container.logs();
|
|
logs.on("data", (b) => process.stdout.write("[container] " + b.toString()));
|
|
logs.on("error", (err) => log.error("[container log error]", err));
|
|
|
|
// Give container time to initialize
|
|
await new Promise((r) => setTimeout(r, 5000));
|
|
|
|
const mappedPort = container.getMappedPort(8080);
|
|
const baseUrl = `http://127.0.0.1:${mappedPort}`;
|
|
|
|
// Wait for server readiness with retry logic (following waku/tests patterns)
|
|
const serverReady = await waitForServerReady(baseUrl, maxAttempts, timeout);
|
|
|
|
if (!serverReady) {
|
|
await logFinalContainerState(container);
|
|
throw new Error("Container failed to become ready");
|
|
}
|
|
|
|
log.info("✅ Browser tests container ready");
|
|
await new Promise((r) => setTimeout(r, 500)); // Final settling time
|
|
|
|
return { container, baseUrl };
|
|
}
|
|
|
|
/**
|
|
* Waits for server to become ready with exponential backoff and detailed logging.
|
|
* Follows retry patterns from @waku/tests ServiceNode.
|
|
*/
|
|
async function waitForServerReady(
|
|
baseUrl: string,
|
|
maxAttempts: number,
|
|
timeout: number
|
|
): Promise<boolean> {
|
|
for (let i = 0; i < maxAttempts; i++) {
|
|
try {
|
|
const res = await axios.get(`${baseUrl}/`, { timeout });
|
|
if (res.status === 200) {
|
|
log.info(`Server is ready after ${i + 1} attempts`);
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
if (i % 10 === 0) {
|
|
log.info(`Attempt ${i + 1}/${maxAttempts} failed:`, error.code || error.message);
|
|
}
|
|
}
|
|
await new Promise((r) => setTimeout(r, 1000));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Logs final container state for debugging, following waku/tests error handling patterns.
|
|
*/
|
|
async function logFinalContainerState(container: StartedTestContainer): Promise<void> {
|
|
try {
|
|
const finalLogs = await container.logs({ tail: 50 });
|
|
log.info("=== Final Container Logs ===");
|
|
finalLogs.on("data", (b) => log.info(b.toString()));
|
|
await new Promise((r) => setTimeout(r, 1000));
|
|
} catch (logError) {
|
|
log.error("Failed to get container logs:", logError);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gracefully stops containers with retry logic, following teardown patterns from waku/tests.
|
|
*/
|
|
export async function stopContainer(container: StartedTestContainer): Promise<void> {
|
|
if (!container) return;
|
|
|
|
log.info("Stopping container gracefully...");
|
|
try {
|
|
await container.stop({ timeout: 10000 });
|
|
log.info("Container stopped successfully");
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
log.warn(
|
|
"Container stop had issues (expected):",
|
|
message
|
|
);
|
|
}
|
|
}
|