Skip to content

Commit 9da3397

Browse files
committed
test: add unit tests for fork features (getPeers, getFiles, toggleFileSelection, setThrottle, openStream)
1 parent a33e6b5 commit 9da3397

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { EventEmitter } from "node:events";
2+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
3+
4+
const mockTorrentMap = new Map<string, any>();
5+
const throttleCalls: { down: number; up: number }[] = [];
6+
7+
vi.mock("webtorrent", () => {
8+
return {
9+
default: class extends EventEmitter {
10+
torrentPort = 6881;
11+
throttleDownload(rate: number): void {
12+
throttleCalls.push({ down: rate, up: 0 });
13+
}
14+
throttleUpload(rate: number): void {
15+
const last = throttleCalls[throttleCalls.length - 1];
16+
if (last) last.up = rate;
17+
}
18+
destroy(): void {}
19+
},
20+
};
21+
});
22+
23+
afterEach(() => {
24+
mockTorrentMap.clear();
25+
throttleCalls.length = 0;
26+
vi.resetModules();
27+
});
28+
29+
describe("TorrentEngine Fork Features", () => {
30+
it("getPeers(id) parses active peer wire details", async () => {
31+
const { TorrentEngine } = await import("./engine");
32+
const engine = new TorrentEngine();
33+
34+
const fakeTorrent = {
35+
wires: [
36+
{
37+
remoteAddress: "192.168.1.100",
38+
peerExtendedHandshake: { v: "uTorrent/3.5.5" },
39+
peerId: "peer-1",
40+
downloaded: 1048576,
41+
uploaded: 524288,
42+
downloadSpeed: () => 50000,
43+
uploadSpeed: () => 10000,
44+
},
45+
{
46+
remoteAddress: "10.0.0.5",
47+
peerExtendedHandshake: null,
48+
peerId: "peer-2",
49+
downloaded: 0,
50+
uploaded: 0,
51+
downloadSpeed: () => 0,
52+
uploadSpeed: () => 0,
53+
},
54+
],
55+
};
56+
57+
(engine as unknown as { torrents: Map<string, unknown> }).torrents.set("t1", fakeTorrent);
58+
59+
const peers = engine.getPeers("t1");
60+
expect(peers).toHaveLength(2);
61+
expect(peers![0]).toEqual({
62+
ip: "192.168.1.100",
63+
client: "uTorrent/3.5.5",
64+
peerId: "peer-1",
65+
downloaded: 1048576,
66+
uploaded: 524288,
67+
downSpeed: 50000,
68+
upSpeed: 10000,
69+
});
70+
expect(peers![1]).toEqual({
71+
ip: "10.0.0.5",
72+
client: "Unknown",
73+
peerId: "peer-2",
74+
downloaded: 0,
75+
uploaded: 0,
76+
downSpeed: 0,
77+
upSpeed: 0,
78+
});
79+
80+
expect(engine.getPeers("nonexistent")).toBeNull();
81+
engine.destroy();
82+
});
83+
84+
it("getFiles() and toggleFileSelection() manage file selection and piece selection", async () => {
85+
const { TorrentEngine } = await import("./engine");
86+
const engine = new TorrentEngine();
87+
88+
const selectSpy1 = vi.fn();
89+
const deselectSpy1 = vi.fn();
90+
const selectSpy2 = vi.fn();
91+
const deselectSpy2 = vi.fn();
92+
93+
const fakeTorrent = {
94+
files: [
95+
{ path: "video.mp4", length: 1000, downloaded: 500, select: selectSpy1, deselect: deselectSpy1 },
96+
{ path: "subs.srt", length: 50, downloaded: 50, select: selectSpy2, deselect: deselectSpy2 },
97+
],
98+
};
99+
100+
(engine as unknown as { torrents: Map<string, unknown> }).torrents.set("t1", fakeTorrent);
101+
102+
// Initial files list (all selected by default)
103+
const initialFiles = engine.getFiles("t1");
104+
expect(initialFiles).toHaveLength(2);
105+
expect(initialFiles![0]).toMatchObject({ path: "video.mp4", selected: true });
106+
expect(initialFiles![1]).toMatchObject({ path: "subs.srt", selected: true });
107+
108+
// Deselect video.mp4
109+
engine.toggleFileSelection("t1", "video.mp4", false);
110+
expect(engine.isDeselected("t1", "video.mp4")).toBe(true);
111+
expect(deselectSpy1).toHaveBeenCalledOnce();
112+
expect(selectSpy2).toHaveBeenCalled(); // shared pieces re-selected for subs.srt
113+
114+
const updatedFiles = engine.getFiles("t1");
115+
expect(updatedFiles![0]?.selected).toBe(false);
116+
expect(updatedFiles![1]?.selected).toBe(true);
117+
118+
// Re-select video.mp4
119+
engine.toggleFileSelection("t1", "video.mp4", true);
120+
expect(engine.isDeselected("t1", "video.mp4")).toBe(false);
121+
expect(selectSpy1).toHaveBeenCalled();
122+
123+
engine.destroy();
124+
});
125+
126+
it("setThrottle() applies bandwidth limits to WebTorrent client", async () => {
127+
const { TorrentEngine } = await import("./engine");
128+
const engine = new TorrentEngine();
129+
130+
// Trigger client creation
131+
(engine as unknown as { ensureClient: () => void }).ensureClient();
132+
133+
// Enable throttle with 1MB/s down and 500KB/s up
134+
engine.setThrottle(true, 1_000_000, 500_000);
135+
expect(throttleCalls).toContainEqual({ down: 1_000_000, up: 500_000 });
136+
137+
// Disable throttle
138+
engine.setThrottle(false, 1_000_000, 500_000);
139+
expect(throttleCalls).toContainEqual({ down: -1, up: -1 });
140+
141+
engine.destroy();
142+
});
143+
});

src/util/openStream.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { describe, it, expect } from "vitest";
2+
import { openStream } from "./openStream";
3+
4+
describe("openStream", () => {
5+
it("returns false when given an empty URL", async () => {
6+
const result = await openStream("");
7+
expect(result).toBe(false);
8+
});
9+
});

0 commit comments

Comments
 (0)