fix: add more logging and fix tests

This commit is contained in:
Arseniy Klempner 2025-10-06 20:05:45 -07:00
parent 4871935389
commit 36aa64df59
No known key found for this signature in database
GPG Key ID: 51653F18863BD24B
9 changed files with 76 additions and 47 deletions

View File

@ -12,7 +12,6 @@ module.exports = {
plugins: ["import"],
extends: ["eslint:recommended"],
rules: {
"no-console": "off",
"no-unused-vars": ["error", { "argsIgnorePattern": "^_", "ignoreRestSiblings": true }]
},
globals: {

View File

@ -14,7 +14,7 @@
"build:server": "tsc -p tsconfig.json",
"build:web": "esbuild web/index.ts --bundle --format=esm --platform=browser --outdir=dist/web && cp web/index.html dist/web/index.html",
"build": "npm-run-all -s build:server build:web",
"docker:build": "docker build -t waku-browser-tests:local ."
"docker:build": "docker build -t waku-browser-tests:local . && docker tag waku-browser-tests:local waku-browser-tests:latest"
},
"dependencies": {
"@playwright/test": "^1.51.1",

View File

@ -13,7 +13,7 @@ if (!process.env.CI) {
const EXAMPLE_PORT = process.env.EXAMPLE_PORT || "8080";
const BASE_URL = `http://127.0.0.1:${EXAMPLE_PORT}`;
const TEST_IGNORE = process.env.CI ? ["tests/docker-*.spec.ts"] : [];
const TEST_IGNORE = process.env.CI ? ["tests/e2e.spec.ts"] : [];
export default defineConfig({
testDir: "./tests",

View File

@ -5,11 +5,14 @@
# Supports reading discovered addresses from /etc/addrs/addrs.env (10k sim pattern)
echo "docker-entrypoint.sh"
echo "Using address: $addrs1"
export WAKU_LIGHTPUSH_NODE="$addrs1"
# Only set WAKU_LIGHTPUSH_NODE if it's not already set and addrs1 is available
if [ -z "$WAKU_LIGHTPUSH_NODE" ] && [ -n "$addrs1" ]; then
export WAKU_LIGHTPUSH_NODE="$addrs1"
fi
echo "Num Args: $#"
echo "Args: $@"
echo "WAKU_LIGHTPUSH_NODE=$addrs1"
echo "WAKU_LIGHTPUSH_NODE=$WAKU_LIGHTPUSH_NODE"
# Parse command line arguments
while [[ $# -gt 0 ]]; do

View File

@ -1,27 +1,27 @@
import { test, expect } from "@playwright/test";
import axios from "axios";
import { StartedTestContainer } from "testcontainers";
import { ServiceNodesFleet } from "@waku/tests";
import { DefaultTestRoutingInfo } from "@waku/tests";
import {
startBrowserTestsContainer,
stopContainer
import {
startBrowserTestsContainer,
stopContainer
} from "./utils/container-helpers.js";
import {
createTwoNodeNetwork,
getDockerAccessibleMultiaddr,
stopNwakuNodes
import {
createTwoNodeNetwork,
getDockerAccessibleMultiaddr,
stopNwakuNodes,
TwoNodeNetwork
} from "./utils/nwaku-helpers.js";
import {
ENV_BUILDERS,
TEST_CONFIG,
ASSERTIONS
import {
ENV_BUILDERS,
TEST_CONFIG,
ASSERTIONS
} from "./utils/test-config.js";
test.describe.configure({ mode: "serial" });
let container: StartedTestContainer;
let nwakuNodes: ServiceNodesFleet;
let nwakuNodes: TwoNodeNetwork;
let baseUrl: string;
test.beforeAll(async () => {
@ -30,10 +30,14 @@ test.beforeAll(async () => {
const lightPushPeerAddr = await getDockerAccessibleMultiaddr(nwakuNodes.nodes[0]);
const result = await startBrowserTestsContainer({
environment: ENV_BUILDERS.withLocalLightPush(lightPushPeerAddr),
environment: {
...ENV_BUILDERS.withLocalLightPush(lightPushPeerAddr),
DEBUG: "waku:*",
WAKU_LIGHTPUSH_NODE: lightPushPeerAddr,
},
networkMode: "waku",
});
container = result.container;
baseUrl = result.baseUrl;
});
@ -67,14 +71,14 @@ test("WakuHeadless can discover nwaku peer and use it for light push", async ()
const peerInfoResponse = await axios.get(`${baseUrl}/waku/v1/peer-info`);
ASSERTIONS.peerInfo(peerInfoResponse);
const routingInfo = DefaultTestRoutingInfo;
const subscriptionResults = await Promise.all([
nwakuNodes.nodes[0].ensureSubscriptions([routingInfo.pubsubTopic]),
nwakuNodes.nodes[1].ensureSubscriptions([routingInfo.pubsubTopic])
]);
expect(subscriptionResults[0]).toBe(true);
expect(subscriptionResults[1]).toBe(true);
@ -99,15 +103,15 @@ test("WakuHeadless can discover nwaku peer and use it for light push", async ()
nwakuNodes.nodes[0].messages(contentTopic),
nwakuNodes.nodes[1].messages(contentTopic)
]);
const totalMessages = node1Messages.length + node2Messages.length;
expect(totalMessages).toBeGreaterThanOrEqual(1);
const receivedMessages = [...node1Messages, ...node2Messages];
expect(receivedMessages.length).toBeGreaterThan(0);
const receivedMessage = receivedMessages[0];
ASSERTIONS.messageContent(receivedMessage, testMessage, contentTopic);
});
});

View File

@ -19,9 +19,12 @@ let wakuNode: LightNode;
test.beforeAll(async () => {
const result = await startBrowserTestsContainer({
environment: ENV_BUILDERS.withProductionEnr(),
environment: {
...ENV_BUILDERS.withProductionEnr(),
DEBUG: "waku:*",
},
});
container = result.container;
baseUrl = result.baseUrl;
});

View File

@ -43,12 +43,14 @@ export async function startBrowserTestsContainer(
const container = await generic.start();
// Set up container logging
await new Promise((r) => setTimeout(r, 5000));
const logs = await container.logs({ tail: 100 });
// 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}`;

View File

@ -1,17 +1,23 @@
import { ServiceNode, ServiceNodesFleet } from "@waku/tests";
import { ServiceNode } from "@waku/tests";
import { DefaultTestRoutingInfo } from "@waku/tests";
import { Logger } from "@waku/utils";
const log = new Logger("nwaku-helpers");
export interface TwoNodeNetwork {
nodes: ServiceNode[];
}
/**
* Creates a two-node nwaku network following waku/tests patterns.
* Node 1: Relay + Light Push (service provider)
* Node 2: Relay only (network peer)
*/
export async function createTwoNodeNetwork(): Promise<ServiceNodesFleet> {
export async function createTwoNodeNetwork(): Promise<TwoNodeNetwork> {
log.info("Creating nwaku node 1 (Relay + Light Push)...");
const lightPushNode = new ServiceNode("lightpush-node-" + Math.random().toString(36).substring(7));
const lightPushNode = new ServiceNode(
"lightpush-node-" + Math.random().toString(36).substring(7),
);
const lightPushArgs = {
relay: true,
@ -20,13 +26,15 @@ export async function createTwoNodeNetwork(): Promise<ServiceNodesFleet> {
store: false,
clusterId: DefaultTestRoutingInfo.clusterId,
numShardsInNetwork: DefaultTestRoutingInfo.networkConfig.numShardsInCluster,
contentTopic: [DefaultTestRoutingInfo.contentTopic]
contentTopic: [DefaultTestRoutingInfo.contentTopic],
};
await lightPushNode.start(lightPushArgs, { retries: 3 });
log.info("Creating nwaku node 2 (Relay only)...");
const relayNode = new ServiceNode("relay-node-" + Math.random().toString(36).substring(7));
const relayNode = new ServiceNode(
"relay-node-" + Math.random().toString(36).substring(7),
);
// Connect second node to first node (following ServiceNodesFleet pattern)
const firstNodeAddr = await lightPushNode.getExternalMultiaddr();
@ -38,7 +46,7 @@ export async function createTwoNodeNetwork(): Promise<ServiceNodesFleet> {
staticnode: firstNodeAddr,
clusterId: DefaultTestRoutingInfo.clusterId,
numShardsInNetwork: DefaultTestRoutingInfo.networkConfig.numShardsInCluster,
contentTopic: [DefaultTestRoutingInfo.contentTopic]
contentTopic: [DefaultTestRoutingInfo.contentTopic],
};
await relayNode.start(relayArgs, { retries: 3 });
@ -50,12 +58,9 @@ export async function createTwoNodeNetwork(): Promise<ServiceNodesFleet> {
// Verify connectivity (optional, for debugging)
await verifyNetworkFormation([lightPushNode, relayNode]);
// Return ServiceNodesFleet-compatible object
// Note: We're returning a partial ServiceNodesFleet for testing purposes
return {
nodes: [lightPushNode, relayNode],
messageCollector: null
} as ServiceNodesFleet;
};
}
/**
@ -69,10 +74,10 @@ async function verifyNetworkFormation(nodes: ServiceNode[]): Promise<void> {
const peers = await node.peers();
log.info(`Node ${index + 1} has ${peers.length} peer(s)`);
return peers.length;
})
}),
);
if (peerCounts.every(count => count === 0)) {
if (peerCounts.every((count) => count === 0)) {
log.warn("⚠️ Nodes may not be properly connected yet");
}
} catch (error) {
@ -84,7 +89,9 @@ async function verifyNetworkFormation(nodes: ServiceNode[]): Promise<void> {
* Extracts Docker-accessible multiaddr from nwaku node.
* Returns multiaddr using container's internal IP for Docker network communication.
*/
export async function getDockerAccessibleMultiaddr(node: ServiceNode): Promise<string> {
export async function getDockerAccessibleMultiaddr(
node: ServiceNode,
): Promise<string> {
// Get multiaddr with localhost and extract components
const localhostMultiaddr = await node.getMultiaddrWithId();
const peerId = await node.getPeerId();
@ -100,7 +107,9 @@ export async function getDockerAccessibleMultiaddr(node: ServiceNode): Promise<s
// Get Docker container IP (accessing internal field)
// Note: This accesses an internal implementation detail of ServiceNode
const nodeWithDocker = node as ServiceNode & { docker?: { containerIp?: string } };
const nodeWithDocker = node as ServiceNode & {
docker?: { containerIp?: string };
};
const containerIp = nodeWithDocker.docker?.containerIp;
if (!containerIp) {
throw new Error("Could not get container IP from node");
@ -123,7 +132,7 @@ export async function stopNwakuNodes(nodes: ServiceNode[]): Promise<void> {
log.info("Stopping nwaku nodes...");
try {
await Promise.all(nodes.map(node => node.stop()));
await Promise.all(nodes.map((node) => node.stop()));
log.info("Nwaku nodes stopped successfully");
} catch (error) {
const message = error instanceof Error ? error.message : String(error);

View File

@ -334,14 +334,17 @@ export class WakuHeadless {
private async dialPreferredLightpushNode() {
if (!this.waku || !this.lightpushNode) {
log.info("Skipping dial: waku or lightpushNode not set");
return;
}
try {
log.info("Attempting to dial preferred lightpush node:", this.lightpushNode);
await this.waku.dial(this.lightpushNode);
log.info("Successfully dialed preferred lightpush node:", this.lightpushNode);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.warn(
log.error(
"Failed to dial preferred lightpush node:",
this.lightpushNode,
message
@ -388,6 +391,12 @@ export class WakuHeadless {
const globalLightpushNode = testWindow.__WAKU_LIGHTPUSH_NODE;
const globalEnrBootstrap = testWindow.__WAKU_ENR_BOOTSTRAP;
log.info("Global config from window:", {
networkConfig: globalNetworkConfig,
lightpushNode: globalLightpushNode,
enrBootstrap: globalEnrBootstrap
});
const instance = new WakuHeadless(
globalNetworkConfig,
globalLightpushNode,