|
1 | 1 | import { describe, it } from "node:test"; |
2 | 2 | import assert from "node:assert/strict"; |
3 | 3 | import { Readable } from "node:stream"; |
4 | | -import { filterUnindexed, dedup, postProcessResults, isOurServer, isIndexable, MIN_SCORE, createHandler } from "./lib.js"; |
| 4 | +import { filterUnindexed, dedup, postProcessResults, isOurServer, isIndexable, userPort, BASE_PORT, MIN_SCORE, createHandler } from "./lib.js"; |
5 | 5 |
|
6 | 6 | // --- Mock helpers for handler tests --- |
7 | 7 |
|
@@ -50,6 +50,27 @@ function makeDeps(overrides = {}) { |
50 | 50 | }; |
51 | 51 | } |
52 | 52 |
|
| 53 | +describe("userPort", () => { |
| 54 | + it("returns a number within the expected range", () => { |
| 55 | + const port = userPort("testuser"); |
| 56 | + assert.ok(port >= BASE_PORT, `port ${port} should be >= ${BASE_PORT}`); |
| 57 | + assert.ok(port <= BASE_PORT + 0xFFF, `port ${port} should be <= ${BASE_PORT + 0xFFF}`); |
| 58 | + }); |
| 59 | + |
| 60 | + it("is deterministic for the same username", () => { |
| 61 | + assert.equal(userPort("alice"), userPort("alice")); |
| 62 | + }); |
| 63 | + |
| 64 | + it("is case-insensitive", () => { |
| 65 | + assert.equal(userPort("Alice"), userPort("alice")); |
| 66 | + }); |
| 67 | + |
| 68 | + it("returns different ports for different usernames", () => { |
| 69 | + // Not guaranteed for all pairs, but statistically overwhelmingly likely |
| 70 | + assert.notEqual(userPort("alice"), userPort("bob")); |
| 71 | + }); |
| 72 | +}); |
| 73 | + |
53 | 74 | describe("filterUnindexed", () => { |
54 | 75 | it("returns items not in the existing index", () => { |
55 | 76 | const all = [ |
@@ -251,6 +272,19 @@ describe("handleRequest - /ping", () => { |
251 | 272 | assert.equal(res.statusCode, 200); |
252 | 273 | assert.deepEqual(res.body, { ok: true }); |
253 | 274 | }); |
| 275 | + |
| 276 | + it("includes identity when getIdentity is provided", async () => { |
| 277 | + const deps = makeDeps({ |
| 278 | + getIdentity: () => ({ user: "testuser", version: "1.0.0" }), |
| 279 | + }); |
| 280 | + const handler = createHandler(deps); |
| 281 | + const res = mockRes(); |
| 282 | + await handler(mockReq("POST", "/ping"), res); |
| 283 | + assert.equal(res.statusCode, 200); |
| 284 | + assert.equal(res.body.ok, true); |
| 285 | + assert.equal(res.body.user, "testuser"); |
| 286 | + assert.equal(res.body.version, "1.0.0"); |
| 287 | + }); |
254 | 288 | }); |
255 | 289 |
|
256 | 290 | describe("handleRequest - routing", () => { |
@@ -343,6 +377,19 @@ describe("handleRequest - /search", () => { |
343 | 377 | await handler(mockReq("POST", "/search", { query: "test" }), mockRes()); |
344 | 378 | assert.ok(deps._closedDbs.includes("vec")); |
345 | 379 | }); |
| 380 | + |
| 381 | + it("skips indexing when sessionStore is null", async () => { |
| 382 | + let indexCalled = false; |
| 383 | + const deps = makeDeps({ |
| 384 | + openSessionStore: () => null, |
| 385 | + indexContent: async () => { indexCalled = true; return 1; }, |
| 386 | + }); |
| 387 | + const handler = createHandler(deps); |
| 388 | + const res = mockRes(); |
| 389 | + await handler(mockReq("POST", "/search", { query: "test" }), res); |
| 390 | + assert.equal(res.statusCode, 200); |
| 391 | + assert.ok(!indexCalled, "indexContent should not be called when sessionStore is null"); |
| 392 | + }); |
346 | 393 | }); |
347 | 394 |
|
348 | 395 | describe("handleRequest - /reindex", () => { |
|
0 commit comments