Initial Commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
|
||||
describe("network-discovery-webtorrent dep-graph", () => {
|
||||
it("must not have circular dependencies", { timeout: 5000 }, async () => {
|
||||
const mod = await import("../src/index.js");
|
||||
expect(mod).toBeDefined();
|
||||
expect(mod.WebTorrentDiscovery).toBeDefined();
|
||||
expect(mod.NET_DISC_WEBTORRENT_CODES).toBeDefined();
|
||||
expect(mod.NetDiscWebTorrentError).toBeDefined();
|
||||
expect(mod.WebTorrentDiscoveryConfigSchema).toBeDefined();
|
||||
expect(mod.WebTorrentPeerMetadataSchema).toBeDefined();
|
||||
expect(mod.withStartSpan).toBeDefined();
|
||||
expect(mod.recordPeersDiscovered).toBeDefined();
|
||||
expect(mod.recordTrackerError).toBeDefined();
|
||||
expect(mod.recordTrackerAnnounceDuration).toBeDefined();
|
||||
expect(mod.WebTorrentTransport).toBeDefined();
|
||||
expect(mod.WebTorrentPlugin).toBeDefined();
|
||||
expect(mod.WebTorrentTransportConfigSchema).toBeDefined();
|
||||
expect(mod.recordTransportMessage).toBeDefined();
|
||||
expect(mod.adjustTransportActivePeers).toBeDefined();
|
||||
expect(mod.withTransportSpan).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import type { P2PTLike } from "../../src/types/types.js";
|
||||
|
||||
/**
|
||||
* In-memory deterministic implementation of the `P2PTLike` surface. Used
|
||||
* across every test in this package so the real `p2pt` runtime is never
|
||||
* pulled into the test environment (Node-flavoured, expects WebSocket /
|
||||
* WebRTC globals) and `vi.mock` is never needed.
|
||||
*/
|
||||
export class FakeP2PT implements P2PTLike {
|
||||
public started = false;
|
||||
public destroyed = false;
|
||||
public readonly trackers: readonly string[];
|
||||
public readonly announceId: string;
|
||||
public startError: Error | null = null;
|
||||
|
||||
private readonly handlers = new Map<
|
||||
string,
|
||||
Array<(...args: unknown[]) => void>
|
||||
>();
|
||||
|
||||
public constructor(trackers: readonly string[], announceId: string) {
|
||||
this.trackers = trackers;
|
||||
this.announceId = announceId;
|
||||
}
|
||||
|
||||
public on(event: string, handler: (...args: unknown[]) => void): void {
|
||||
const list = this.handlers.get(event) ?? [];
|
||||
list.push(handler);
|
||||
this.handlers.set(event, list);
|
||||
}
|
||||
|
||||
public async start(): Promise<void> {
|
||||
if (this.startError !== null) {
|
||||
throw this.startError;
|
||||
}
|
||||
this.started = true;
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.destroyed = true;
|
||||
// Keep handlers around so tests can drive late events through a
|
||||
// captured reference and exercise the orchestrator's `running`
|
||||
// guard. Real p2pt instances detach internally; the orchestrator
|
||||
// never re-uses a destroyed instance.
|
||||
}
|
||||
|
||||
public requestMorePeers(): void {
|
||||
/* no-op in tests */
|
||||
}
|
||||
|
||||
/** Captured outbound sends for transport-adapter tests. */
|
||||
public readonly outbound: Array<{ peer: unknown; msg: unknown }> = [];
|
||||
/** Programmable per-call failure for `send`. */
|
||||
public sendError: Error | null = null;
|
||||
|
||||
public send(peer: unknown, msg: unknown): Promise<void> {
|
||||
if (this.sendError !== null) {
|
||||
return Promise.reject(this.sendError);
|
||||
}
|
||||
this.outbound.push({ peer, msg });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/** Fire an event into every subscribed handler. Tests use this to
|
||||
* drive the orchestrator. */
|
||||
public emit(event: string, ...args: unknown[]): void {
|
||||
const list = this.handlers.get(event);
|
||||
if (list === undefined) return;
|
||||
for (const handler of [...list]) {
|
||||
handler(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory helper producing a `FakeP2PT` and recording every instance the
|
||||
* factory created so the test can introspect destroy / start state.
|
||||
*/
|
||||
export function makeFakeFactory(): {
|
||||
readonly instances: FakeP2PT[];
|
||||
readonly factory: (
|
||||
trackers: readonly string[],
|
||||
announceId: string
|
||||
) => FakeP2PT;
|
||||
} {
|
||||
const instances: FakeP2PT[] = [];
|
||||
return {
|
||||
instances,
|
||||
factory: (trackers, announceId) => {
|
||||
const inst = new FakeP2PT(trackers, announceId);
|
||||
instances.push(inst);
|
||||
return inst;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Ensure `globalThis.crypto` is available in bare-Node vitest runs.
|
||||
import { webcrypto } from "node:crypto";
|
||||
|
||||
type WritableGlobal = { crypto?: Crypto };
|
||||
const g = globalThis as WritableGlobal;
|
||||
if (g.crypto === undefined) {
|
||||
g.crypto = webcrypto as unknown as Crypto;
|
||||
}
|
||||
Reference in New Issue
Block a user