Skip to content

Commit a25c528

Browse files
committed
chore: enforce registerSpy via biome lint and migrate all callsites
Upgrades @biomejs/biome to 2.4.11 and enables a noRestrictedImports rule that errors on bare spyOn imports from bun:test, with the message "Use registerSpy instead of spyOn". Migrates all 16 violations across the test suite to use registerSpy from test-utils.
1 parent 828b380 commit a25c528

18 files changed

Lines changed: 85 additions & 57 deletions

biome.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.4.11/schema.json",
33
"files": {
44
"includes": [
55
"**",
@@ -35,7 +35,23 @@
3535
}
3636
},
3737
"linter": {
38-
"enabled": false
38+
"enabled": true,
39+
"rules": {
40+
"recommended": false,
41+
"style": {
42+
"noRestrictedImports": {
43+
"level": "error",
44+
"options": {
45+
"paths": {
46+
"bun:test": {
47+
"importNames": ["spyOn"],
48+
"message": "Use registerSpy instead of spyOn"
49+
}
50+
}
51+
}
52+
}
53+
}
54+
}
3955
},
4056
"assist": {
4157
"enabled": false

bun.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "plexus2",
33
"module": "index.ts",
44
"devDependencies": {
5-
"@biomejs/biome": "^2.4.6",
5+
"@biomejs/biome": "^2.4.11",
66
"biome": "^0.3.3",
77
"bun-types": "^1.3.10",
88
"drizzle-kit": "0.31.10",

packages/backend/src/routes/inference/__tests__/images.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, it, expect, beforeEach, spyOn } from 'bun:test';
1+
import { describe, it, expect, beforeEach } from 'bun:test';
22
import { ImageTransformer } from '../../../transformers/image';
33
import { DebugManager } from '../../../services/debug-manager';
44

packages/backend/src/routes/mcp/__tests__/mcp-routes.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { describe, expect, test, mock, beforeAll, spyOn } from 'bun:test';
1+
import { describe, expect, test, mock, beforeAll } from 'bun:test';
2+
import { registerSpy } from '../../../../test/test-utils';
23
import Fastify, { FastifyInstance } from 'fastify';
34
import { setConfigForTesting } from '../../../config';
45
import { registerMcpRoutes } from '../index';
@@ -27,7 +28,7 @@ describe('MCP Routes', () => {
2728
}));
2829

2930
// Spy on the module and replace the function
30-
spyOn(mcpProxyService, 'proxyMcpRequest').mockImplementation(mockProxyMcpRequest);
31+
registerSpy(mcpProxyService, 'proxyMcpRequest').mockImplementation(mockProxyMcpRequest);
3132

3233
// Set config with keys and MCP servers
3334
setConfigForTesting({

packages/backend/src/services/__tests__/aliases.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { describe, expect, test, beforeEach, afterEach, spyOn } from 'bun:test';
1+
import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2+
import { registerSpy } from '../../../test/test-utils';
23
import { Router } from '../router';
34
import { setConfigForTesting } from '../../config';
45
import { CooldownManager } from '../cooldown-manager';
@@ -156,7 +157,7 @@ describe('Router.resolveCandidates', () => {
156157
const cooldownManager = CooldownManager.getInstance();
157158

158159
afterEach(() => {
159-
spyOn(cooldownManager, 'filterHealthyTargets').mockRestore();
160+
registerSpy(cooldownManager, 'filterHealthyTargets').mockRestore();
160161
});
161162

162163
test('returns empty array when model alias does not exist', async () => {
@@ -254,7 +255,7 @@ describe('Router.resolveCandidates', () => {
254255
keys: {},
255256
} as any);
256257

257-
spyOn(cooldownManager, 'filterHealthyTargets').mockResolvedValue([]);
258+
registerSpy(cooldownManager, 'filterHealthyTargets').mockResolvedValue([]);
258259

259260
const result = await Router.resolveCandidates('cooldown-model');
260261
expect(result).toEqual([]);
@@ -297,7 +298,7 @@ describe('Router.resolveCandidates', () => {
297298
} as any);
298299

299300
// Simulate p1 being unhealthy after disabled filtering
300-
spyOn(cooldownManager, 'filterHealthyTargets').mockResolvedValue([
301+
registerSpy(cooldownManager, 'filterHealthyTargets').mockResolvedValue([
301302
{ provider: 'p3', model: 'm3' },
302303
] as any);
303304

packages/backend/src/services/__tests__/debug-logging-error.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { describe, expect, test, beforeEach, spyOn, mock } from 'bun:test';
1+
import { describe, expect, test, beforeEach, mock } from 'bun:test';
2+
import { registerSpy } from '../../../test/test-utils';
23
import { Dispatcher } from '../dispatcher';
34
import { DebugManager } from '../debug-manager';
45
import { setConfigForTesting } from '../../config';
@@ -15,7 +16,7 @@ describe('Dispatcher Error Logging', () => {
1516
debugManager.pendingLogs.clear();
1617

1718
// Spy on DebugManager.addRawResponse
18-
addRawResponseSpy = spyOn(debugManager, 'addRawResponse');
19+
addRawResponseSpy = registerSpy(debugManager, 'addRawResponse');
1920
});
2021

2122
test('Captures error response in debug log when upstream fails', async () => {

packages/backend/src/services/__tests__/dispatcher-bug-fix.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, expect, test, beforeEach, spyOn, mock } from 'bun:test';
1+
import { describe, expect, test, beforeEach, mock } from 'bun:test';
22
import { Dispatcher } from '../dispatcher';
33
import { setConfigForTesting } from '../../config';
44
import { UnifiedChatRequest } from '../../types/unified';

packages/backend/src/services/__tests__/usage-logging-metadata.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from 'bun:test';
1+
import { describe, it, expect, beforeEach, afterEach, mock } from 'bun:test';
2+
import { registerSpy } from '../../../test/test-utils';
23
import { PassThrough } from 'stream';
34
import { UsageInspector } from '../inspectors/usage-logging';
45
import { DebugManager } from '../debug-manager';
@@ -47,7 +48,7 @@ describe('UsageInspector Metadata Robustness', () => {
4748
dm.addReconstructedRawResponse(requestId, snapshot);
4849

4950
let capturedRecord: UsageRecord | null = null;
50-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
51+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
5152
capturedRecord = record;
5253
return Promise.resolve();
5354
});
@@ -141,7 +142,7 @@ describe('UsageInspector Metadata Robustness', () => {
141142
dm.addReconstructedRawResponse(requestId, snapshot);
142143

143144
let capturedRecord: any = null;
144-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: any) => {
145+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: any) => {
145146
capturedRecord = record;
146147
return Promise.resolve();
147148
});

packages/backend/src/services/__tests__/usage-logging.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from 'bun:test';
1+
import { describe, it, expect, beforeEach, afterEach, mock } from 'bun:test';
2+
import { registerSpy } from '../../../test/test-utils';
23
import { PassThrough } from 'stream';
34
import { UsageInspector } from '../inspectors/usage-logging';
45
import { UsageStorageService } from '../usage-storage';
@@ -68,7 +69,7 @@ describe('UsageInspector', () => {
6869
const mockStream = new PassThrough();
6970

7071
let capturedRecord: UsageRecord | null = null;
71-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
72+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
7273
capturedRecord = record;
7374
return Promise.resolve();
7475
});
@@ -115,7 +116,7 @@ describe('UsageInspector', () => {
115116
const mockStream = new PassThrough();
116117

117118
let capturedRecord: UsageRecord | null = null;
118-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
119+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
119120
capturedRecord = record;
120121
return Promise.resolve();
121122
});
@@ -163,7 +164,7 @@ describe('UsageInspector', () => {
163164
const mockStream = new PassThrough();
164165

165166
let capturedRecord: UsageRecord | null = null;
166-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
167+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
167168
capturedRecord = record;
168169
return Promise.resolve();
169170
});
@@ -208,7 +209,7 @@ describe('UsageInspector', () => {
208209
const mockStream = new PassThrough();
209210

210211
let capturedRecord: UsageRecord | null = null;
211-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
212+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
212213
capturedRecord = record;
213214
return Promise.resolve();
214215
});
@@ -255,7 +256,7 @@ describe('UsageInspector', () => {
255256
const mockStream = new PassThrough();
256257

257258
let capturedRecord: UsageRecord | null = null;
258-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
259+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
259260
capturedRecord = record;
260261
return Promise.resolve();
261262
});
@@ -304,7 +305,7 @@ describe('UsageInspector', () => {
304305
const mockStream = new PassThrough();
305306

306307
let capturedRecord: UsageRecord | null = null;
307-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
308+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
308309
capturedRecord = record;
309310
return Promise.resolve();
310311
});
@@ -354,7 +355,7 @@ describe('UsageInspector', () => {
354355
const mockStream = new PassThrough();
355356

356357
let capturedRecord: UsageRecord | null = null;
357-
spyOn(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
358+
registerSpy(mockStorage, 'saveRequest').mockImplementation(async (record: UsageRecord) => {
358359
capturedRecord = record;
359360
return Promise.resolve();
360361
});

0 commit comments

Comments
 (0)