lynkr 8.0.0 → 9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.lynkr/telemetry.db +0 -0
- package/.lynkr/telemetry.db-shm +0 -0
- package/.lynkr/telemetry.db-wal +0 -0
- package/README.md +196 -322
- package/lynkr-skill.tar.gz +0 -0
- package/package.json +4 -3
- package/src/api/openai-router.js +64 -13
- package/src/api/providers-handler.js +171 -3
- package/src/api/router.js +9 -2
- package/src/clients/circuit-breaker.js +10 -247
- package/src/clients/codex-process.js +342 -0
- package/src/clients/codex-utils.js +143 -0
- package/src/clients/databricks.js +210 -63
- package/src/clients/resilience.js +540 -0
- package/src/clients/retry.js +22 -167
- package/src/clients/standard-tools.js +23 -0
- package/src/config/index.js +77 -0
- package/src/context/compression.js +42 -9
- package/src/context/distill.js +492 -0
- package/src/orchestrator/index.js +48 -8
- package/src/routing/complexity-analyzer.js +258 -5
- package/src/routing/index.js +12 -2
- package/src/routing/latency-tracker.js +148 -0
- package/src/routing/model-tiers.js +2 -0
- package/src/routing/quality-scorer.js +113 -0
- package/src/routing/telemetry.js +464 -0
- package/src/server.js +13 -12
- package/src/tools/code-graph.js +538 -0
- package/src/tools/code-mode.js +304 -0
- package/src/tools/index.js +4 -0
- package/src/tools/lazy-loader.js +18 -0
- package/src/tools/mcp-remote.js +7 -0
- package/src/tools/smart-selection.js +11 -0
- package/src/tools/tinyfish.js +358 -0
- package/src/tools/truncate.js +1 -0
- package/src/utils/payload.js +206 -0
- package/src/utils/perf-timer.js +80 -0
- package/.github/FUNDING.yml +0 -15
- package/.github/workflows/README.md +0 -215
- package/.github/workflows/ci.yml +0 -69
- package/.github/workflows/index.yml +0 -62
- package/.github/workflows/web-tools-tests.yml +0 -56
- package/CITATIONS.bib +0 -6
- package/DEPLOYMENT.md +0 -1001
- package/LYNKR-TUI-PLAN.md +0 -984
- package/PERFORMANCE-REPORT.md +0 -866
- package/PLAN-per-client-model-routing.md +0 -252
- package/docs/42642f749da6234f41b6b425c3bb07c9.txt +0 -1
- package/docs/BingSiteAuth.xml +0 -4
- package/docs/docs-style.css +0 -478
- package/docs/docs.html +0 -198
- package/docs/google5be250e608e6da39.html +0 -1
- package/docs/index.html +0 -577
- package/docs/index.md +0 -584
- package/docs/robots.txt +0 -4
- package/docs/sitemap.xml +0 -44
- package/docs/style.css +0 -1223
- package/docs/toon-integration-spec.md +0 -130
- package/documentation/README.md +0 -101
- package/documentation/api.md +0 -806
- package/documentation/claude-code-cli.md +0 -679
- package/documentation/codex-cli.md +0 -397
- package/documentation/contributing.md +0 -571
- package/documentation/cursor-integration.md +0 -734
- package/documentation/docker.md +0 -874
- package/documentation/embeddings.md +0 -762
- package/documentation/faq.md +0 -713
- package/documentation/features.md +0 -403
- package/documentation/headroom.md +0 -519
- package/documentation/installation.md +0 -758
- package/documentation/memory-system.md +0 -476
- package/documentation/production.md +0 -636
- package/documentation/providers.md +0 -1009
- package/documentation/routing.md +0 -476
- package/documentation/testing.md +0 -629
- package/documentation/token-optimization.md +0 -325
- package/documentation/tools.md +0 -697
- package/documentation/troubleshooting.md +0 -969
- package/final-test.js +0 -33
- package/headroom-sidecar/config.py +0 -93
- package/headroom-sidecar/requirements.txt +0 -14
- package/headroom-sidecar/server.py +0 -451
- package/monitor-agents.sh +0 -31
- package/scripts/audit-log-reader.js +0 -399
- package/scripts/compact-dictionary.js +0 -204
- package/scripts/test-deduplication.js +0 -448
- package/src/db/database.sqlite +0 -0
- package/te +0 -11622
- package/test/README.md +0 -212
- package/test/azure-openai-config.test.js +0 -213
- package/test/azure-openai-error-resilience.test.js +0 -238
- package/test/azure-openai-format-conversion.test.js +0 -354
- package/test/azure-openai-integration.test.js +0 -287
- package/test/azure-openai-routing.test.js +0 -175
- package/test/azure-openai-streaming.test.js +0 -171
- package/test/bedrock-integration.test.js +0 -457
- package/test/comprehensive-test-suite.js +0 -928
- package/test/config-validation.test.js +0 -207
- package/test/cursor-integration.test.js +0 -484
- package/test/format-conversion.test.js +0 -578
- package/test/hybrid-routing-integration.test.js +0 -269
- package/test/hybrid-routing-performance.test.js +0 -428
- package/test/llamacpp-integration.test.js +0 -882
- package/test/lmstudio-integration.test.js +0 -347
- package/test/memory/extractor.test.js +0 -398
- package/test/memory/retriever.test.js +0 -613
- package/test/memory/retriever.test.js.bak +0 -585
- package/test/memory/search.test.js +0 -537
- package/test/memory/search.test.js.bak +0 -389
- package/test/memory/store.test.js +0 -344
- package/test/memory/store.test.js.bak +0 -312
- package/test/memory/surprise.test.js +0 -300
- package/test/memory-performance.test.js +0 -472
- package/test/openai-integration.test.js +0 -683
- package/test/openrouter-error-resilience.test.js +0 -418
- package/test/passthrough-mode.test.js +0 -385
- package/test/performance-benchmark.js +0 -351
- package/test/performance-tests.js +0 -528
- package/test/routing.test.js +0 -225
- package/test/toon-compression.test.js +0 -131
- package/test/web-tools.test.js +0 -329
- package/test-agents-simple.js +0 -43
- package/test-cli-connection.sh +0 -33
- package/test-learning-unit.js +0 -126
- package/test-learning.js +0 -112
- package/test-parallel-agents.sh +0 -124
- package/test-parallel-direct.js +0 -155
- package/test-subagents.sh +0 -117
package/documentation/testing.md
DELETED
|
@@ -1,629 +0,0 @@
|
|
|
1
|
-
# Testing Guide
|
|
2
|
-
|
|
3
|
-
Comprehensive guide to testing Lynkr, including unit tests, integration tests, and manual testing.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Running Tests
|
|
8
|
-
|
|
9
|
-
### Quick Start
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
# Run all tests
|
|
13
|
-
npm test
|
|
14
|
-
|
|
15
|
-
# Run specific test file
|
|
16
|
-
npm test test/config.test.js
|
|
17
|
-
|
|
18
|
-
# Run tests with coverage
|
|
19
|
-
npm run test:coverage
|
|
20
|
-
|
|
21
|
-
# Run tests in watch mode
|
|
22
|
-
npm run test:watch
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Test Structure
|
|
28
|
-
|
|
29
|
-
Lynkr uses **Node.js built-in test runner** (no external dependencies):
|
|
30
|
-
|
|
31
|
-
```javascript
|
|
32
|
-
const assert = require("assert");
|
|
33
|
-
const { describe, it, beforeEach, afterEach } = require("node:test");
|
|
34
|
-
|
|
35
|
-
describe("Feature Name", () => {
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
// Setup before each test
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
afterEach(() => {
|
|
41
|
-
// Cleanup after each test
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("should do something specific", () => {
|
|
45
|
-
// Test implementation
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Test Categories
|
|
53
|
-
|
|
54
|
-
### 1. Unit Tests
|
|
55
|
-
|
|
56
|
-
Test individual functions and modules in isolation.
|
|
57
|
-
|
|
58
|
-
**Location**: `test/`
|
|
59
|
-
|
|
60
|
-
**Examples**:
|
|
61
|
-
- `test/config.test.js` - Configuration loading and validation
|
|
62
|
-
- `test/prompt-cache.test.js` - Prompt caching logic
|
|
63
|
-
- `test/circuit-breaker.test.js` - Circuit breaker state machine
|
|
64
|
-
|
|
65
|
-
**Running**:
|
|
66
|
-
```bash
|
|
67
|
-
npm test test/config.test.js
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Integration Tests
|
|
71
|
-
|
|
72
|
-
Test integration between multiple components.
|
|
73
|
-
|
|
74
|
-
**Location**: `test/`
|
|
75
|
-
|
|
76
|
-
**Examples**:
|
|
77
|
-
- `test/databricks-integration.test.js` - Databricks provider
|
|
78
|
-
- `test/bedrock-integration.test.js` - AWS Bedrock provider
|
|
79
|
-
- `test/openrouter-integration.test.js` - OpenRouter provider
|
|
80
|
-
- `test/cursor-integration.test.js` - Cursor IDE compatibility
|
|
81
|
-
|
|
82
|
-
**Running**:
|
|
83
|
-
```bash
|
|
84
|
-
npm test test/databricks-integration.test.js
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 3. End-to-End Tests
|
|
88
|
-
|
|
89
|
-
Test complete request/response flows.
|
|
90
|
-
|
|
91
|
-
**Location**: `test/e2e/`
|
|
92
|
-
|
|
93
|
-
**Examples**:
|
|
94
|
-
- `test/e2e/claude-cli.test.js` - Claude Code CLI integration
|
|
95
|
-
- `test/e2e/cursor.test.js` - Cursor IDE integration
|
|
96
|
-
- `test/e2e/streaming.test.js` - Streaming responses
|
|
97
|
-
|
|
98
|
-
**Running**:
|
|
99
|
-
```bash
|
|
100
|
-
npm test test/e2e/
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Writing Tests
|
|
106
|
-
|
|
107
|
-
### Basic Test Structure
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
const assert = require("assert");
|
|
111
|
-
const { describe, it, beforeEach, afterEach } = require("node:test");
|
|
112
|
-
|
|
113
|
-
describe("Module Name", () => {
|
|
114
|
-
let originalEnv;
|
|
115
|
-
|
|
116
|
-
beforeEach(() => {
|
|
117
|
-
// Save original environment
|
|
118
|
-
originalEnv = { ...process.env };
|
|
119
|
-
|
|
120
|
-
// Clear module cache to get fresh config
|
|
121
|
-
delete require.cache[require.resolve("../src/config")];
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
afterEach(() => {
|
|
125
|
-
// Restore original environment
|
|
126
|
-
process.env = originalEnv;
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("should handle valid input", () => {
|
|
130
|
-
// Arrange
|
|
131
|
-
const input = "test-input";
|
|
132
|
-
|
|
133
|
-
// Act
|
|
134
|
-
const result = myFunction(input);
|
|
135
|
-
|
|
136
|
-
// Assert
|
|
137
|
-
assert.strictEqual(result, "expected-output");
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("should throw error for invalid input", () => {
|
|
141
|
-
// Assert that function throws
|
|
142
|
-
assert.throws(
|
|
143
|
-
() => myFunction(null),
|
|
144
|
-
/Expected error message/
|
|
145
|
-
);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Testing Async Functions
|
|
151
|
-
|
|
152
|
-
```javascript
|
|
153
|
-
it("should handle async operations", async () => {
|
|
154
|
-
const result = await myAsyncFunction();
|
|
155
|
-
assert.strictEqual(result.success, true);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it("should reject with error", async () => {
|
|
159
|
-
await assert.rejects(
|
|
160
|
-
() => myAsyncFunction("invalid"),
|
|
161
|
-
/Expected error/
|
|
162
|
-
);
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Testing Environment Variables
|
|
167
|
-
|
|
168
|
-
```javascript
|
|
169
|
-
it("should use environment variable", () => {
|
|
170
|
-
process.env.MY_VARIABLE = "test-value";
|
|
171
|
-
|
|
172
|
-
const config = require("../src/config");
|
|
173
|
-
|
|
174
|
-
assert.strictEqual(config.myVariable, "test-value");
|
|
175
|
-
});
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### Mocking External Dependencies
|
|
179
|
-
|
|
180
|
-
```javascript
|
|
181
|
-
// Simple mock
|
|
182
|
-
const originalFetch = global.fetch;
|
|
183
|
-
global.fetch = async (url, options) => {
|
|
184
|
-
return {
|
|
185
|
-
ok: true,
|
|
186
|
-
json: async () => ({ data: "mocked" }),
|
|
187
|
-
};
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// Test code...
|
|
191
|
-
|
|
192
|
-
// Restore
|
|
193
|
-
global.fetch = originalFetch;
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Test Coverage
|
|
199
|
-
|
|
200
|
-
### Viewing Coverage
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
# Generate coverage report
|
|
204
|
-
npm run test:coverage
|
|
205
|
-
|
|
206
|
-
# View HTML report
|
|
207
|
-
open coverage/index.html
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Coverage Goals
|
|
211
|
-
|
|
212
|
-
- **Overall**: 80%+ coverage
|
|
213
|
-
- **Critical paths**: 90%+ coverage
|
|
214
|
-
- **Edge cases**: All error conditions tested
|
|
215
|
-
- **New code**: 100% coverage for new features
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## Provider Testing
|
|
220
|
-
|
|
221
|
-
### Testing With Real Providers
|
|
222
|
-
|
|
223
|
-
To test with real provider APIs:
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
# Set real credentials
|
|
227
|
-
export MODEL_PROVIDER=databricks
|
|
228
|
-
export DATABRICKS_API_BASE=https://your-workspace.databricks.com
|
|
229
|
-
export DATABRICKS_API_KEY=your-real-key
|
|
230
|
-
|
|
231
|
-
# Run integration tests
|
|
232
|
-
npm test test/databricks-integration.test.js
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
**Note**: These tests make real API calls and may incur costs.
|
|
236
|
-
|
|
237
|
-
### Testing With Mock Providers
|
|
238
|
-
|
|
239
|
-
For local testing without API costs:
|
|
240
|
-
|
|
241
|
-
```javascript
|
|
242
|
-
beforeEach(() => {
|
|
243
|
-
// Mock API responses
|
|
244
|
-
global.fetch = async (url, options) => {
|
|
245
|
-
if (url.includes("/invocations")) {
|
|
246
|
-
return {
|
|
247
|
-
ok: true,
|
|
248
|
-
json: async () => ({
|
|
249
|
-
id: "msg_test",
|
|
250
|
-
type: "message",
|
|
251
|
-
role: "assistant",
|
|
252
|
-
content: [{ type: "text", text: "mocked response" }],
|
|
253
|
-
model: "claude-3-5-sonnet",
|
|
254
|
-
stop_reason: "end_turn",
|
|
255
|
-
usage: { input_tokens: 10, output_tokens: 20 },
|
|
256
|
-
}),
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
});
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## Manual Testing
|
|
266
|
-
|
|
267
|
-
### Testing Claude Code CLI
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
# Start Lynkr
|
|
271
|
-
npm start
|
|
272
|
-
|
|
273
|
-
# In another terminal, configure Claude CLI
|
|
274
|
-
export ANTHROPIC_BASE_URL=http://localhost:8081
|
|
275
|
-
export ANTHROPIC_API_KEY=dummy
|
|
276
|
-
|
|
277
|
-
# Test basic query
|
|
278
|
-
claude "What is 2+2?"
|
|
279
|
-
|
|
280
|
-
# Test file operations
|
|
281
|
-
claude "List files in current directory"
|
|
282
|
-
|
|
283
|
-
# Test tool calling
|
|
284
|
-
claude "What changed in git?"
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Testing Cursor IDE
|
|
288
|
-
|
|
289
|
-
1. **Start Lynkr**: `npm start`
|
|
290
|
-
|
|
291
|
-
2. **Configure Cursor**:
|
|
292
|
-
- Settings → Models → OpenAI API
|
|
293
|
-
- API Key: `sk-lynkr`
|
|
294
|
-
- Base URL: `http://localhost:8081/v1`
|
|
295
|
-
- Model: `claude-3.5-sonnet`
|
|
296
|
-
|
|
297
|
-
3. **Test Chat**: `Cmd+L` / `Ctrl+L`
|
|
298
|
-
- Enter: "Hello, can you see this?"
|
|
299
|
-
- Should get response
|
|
300
|
-
|
|
301
|
-
4. **Test Inline Edits**: `Cmd+K` / `Ctrl+K`
|
|
302
|
-
- Select code
|
|
303
|
-
- Enter: "Add error handling"
|
|
304
|
-
- Should modify code
|
|
305
|
-
|
|
306
|
-
5. **Test @Codebase**: (requires embeddings)
|
|
307
|
-
- In chat: `@Codebase find authentication`
|
|
308
|
-
- Should return relevant files
|
|
309
|
-
|
|
310
|
-
### Testing Health Endpoints
|
|
311
|
-
|
|
312
|
-
```bash
|
|
313
|
-
# Liveness probe
|
|
314
|
-
curl http://localhost:8081/health/live
|
|
315
|
-
# Expected: {"status":"ok"}
|
|
316
|
-
|
|
317
|
-
# Readiness probe
|
|
318
|
-
curl http://localhost:8081/health/ready
|
|
319
|
-
# Expected: {"status":"ready","checks":{"database":"ok","provider":"ok"}}
|
|
320
|
-
|
|
321
|
-
# Deep health check
|
|
322
|
-
curl "http://localhost:8081/health/ready?deep=true"
|
|
323
|
-
# Expected: Detailed health information
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Testing Embeddings
|
|
327
|
-
|
|
328
|
-
```bash
|
|
329
|
-
# Test embeddings endpoint
|
|
330
|
-
curl http://localhost:8081/v1/embeddings \
|
|
331
|
-
-H "Content-Type: application/json" \
|
|
332
|
-
-d '{
|
|
333
|
-
"input": "function to sort array",
|
|
334
|
-
"model": "text-embedding-ada-002"
|
|
335
|
-
}'
|
|
336
|
-
|
|
337
|
-
# Should return embedding vector
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Testing Metrics
|
|
341
|
-
|
|
342
|
-
```bash
|
|
343
|
-
# Get Prometheus metrics
|
|
344
|
-
curl http://localhost:8081/metrics
|
|
345
|
-
|
|
346
|
-
# Should return metrics like:
|
|
347
|
-
# lynkr_requests_total{provider="databricks",status="200"} 42
|
|
348
|
-
# lynkr_request_duration_seconds_sum 12.5
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
## Performance Testing
|
|
354
|
-
|
|
355
|
-
### Load Testing
|
|
356
|
-
|
|
357
|
-
Use tools like Apache Bench or k6:
|
|
358
|
-
|
|
359
|
-
```bash
|
|
360
|
-
# Simple load test with curl
|
|
361
|
-
for i in {1..100}; do
|
|
362
|
-
curl -s http://localhost:8081/health/live > /dev/null &
|
|
363
|
-
done
|
|
364
|
-
wait
|
|
365
|
-
|
|
366
|
-
# Or use Apache Bench
|
|
367
|
-
ab -n 1000 -c 10 http://localhost:8081/health/live
|
|
368
|
-
|
|
369
|
-
# Or use k6
|
|
370
|
-
k6 run test/load/simple-load-test.js
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Stress Testing
|
|
374
|
-
|
|
375
|
-
```bash
|
|
376
|
-
# High concurrency
|
|
377
|
-
ab -n 10000 -c 100 http://localhost:8081/health/live
|
|
378
|
-
|
|
379
|
-
# Check metrics after
|
|
380
|
-
curl http://localhost:8081/metrics | grep lynkr_requests
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## Debugging Tests
|
|
386
|
-
|
|
387
|
-
### Enable Debug Logging
|
|
388
|
-
|
|
389
|
-
```bash
|
|
390
|
-
# Run tests with debug output
|
|
391
|
-
LOG_LEVEL=debug npm test
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### Run Single Test
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
# Run specific test file
|
|
398
|
-
npm test test/config.test.js
|
|
399
|
-
|
|
400
|
-
# Run only tests matching pattern
|
|
401
|
-
npm test -- --grep="should accept bedrock"
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
### Inspect Test Failures
|
|
405
|
-
|
|
406
|
-
```bash
|
|
407
|
-
# Run tests with verbose output
|
|
408
|
-
npm test -- --verbose
|
|
409
|
-
|
|
410
|
-
# Run tests with stack traces
|
|
411
|
-
npm test -- --trace-uncaught
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
## Continuous Integration
|
|
417
|
-
|
|
418
|
-
Lynkr uses GitHub Actions for CI:
|
|
419
|
-
|
|
420
|
-
**File**: `.github/workflows/test.yml`
|
|
421
|
-
|
|
422
|
-
```yaml
|
|
423
|
-
name: Tests
|
|
424
|
-
|
|
425
|
-
on: [push, pull_request]
|
|
426
|
-
|
|
427
|
-
jobs:
|
|
428
|
-
test:
|
|
429
|
-
runs-on: ubuntu-latest
|
|
430
|
-
|
|
431
|
-
steps:
|
|
432
|
-
- uses: actions/checkout@v3
|
|
433
|
-
|
|
434
|
-
- name: Setup Node.js
|
|
435
|
-
uses: actions/setup-node@v3
|
|
436
|
-
with:
|
|
437
|
-
node-version: '18'
|
|
438
|
-
|
|
439
|
-
- name: Install dependencies
|
|
440
|
-
run: npm ci
|
|
441
|
-
|
|
442
|
-
- name: Run tests
|
|
443
|
-
run: npm test
|
|
444
|
-
|
|
445
|
-
- name: Generate coverage
|
|
446
|
-
run: npm run test:coverage
|
|
447
|
-
|
|
448
|
-
- name: Upload coverage
|
|
449
|
-
uses: codecov/codecov-action@v3
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## Test Best Practices
|
|
455
|
-
|
|
456
|
-
### 1. Isolate Tests
|
|
457
|
-
|
|
458
|
-
- Each test should be independent
|
|
459
|
-
- Use `beforeEach`/`afterEach` for setup/cleanup
|
|
460
|
-
- Don't rely on test execution order
|
|
461
|
-
|
|
462
|
-
### 2. Clear Test Names
|
|
463
|
-
|
|
464
|
-
```javascript
|
|
465
|
-
// Good
|
|
466
|
-
it("should throw error when API key is missing", () => {});
|
|
467
|
-
|
|
468
|
-
// Bad
|
|
469
|
-
it("test config", () => {});
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### 3. Arrange-Act-Assert Pattern
|
|
473
|
-
|
|
474
|
-
```javascript
|
|
475
|
-
it("should calculate total correctly", () => {
|
|
476
|
-
// Arrange
|
|
477
|
-
const items = [1, 2, 3];
|
|
478
|
-
|
|
479
|
-
// Act
|
|
480
|
-
const total = calculateTotal(items);
|
|
481
|
-
|
|
482
|
-
// Assert
|
|
483
|
-
assert.strictEqual(total, 6);
|
|
484
|
-
});
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
### 4. Test Edge Cases
|
|
488
|
-
|
|
489
|
-
```javascript
|
|
490
|
-
it("should handle empty array", () => {
|
|
491
|
-
assert.strictEqual(calculateTotal([]), 0);
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
it("should handle null input", () => {
|
|
495
|
-
assert.throws(() => calculateTotal(null));
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
it("should handle negative numbers", () => {
|
|
499
|
-
assert.strictEqual(calculateTotal([-1, -2]), -3);
|
|
500
|
-
});
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
### 5. Mock External Dependencies
|
|
504
|
-
|
|
505
|
-
Don't make real API calls in unit tests:
|
|
506
|
-
|
|
507
|
-
```javascript
|
|
508
|
-
beforeEach(() => {
|
|
509
|
-
// Mock fetch
|
|
510
|
-
global.fetch = async () => ({
|
|
511
|
-
ok: true,
|
|
512
|
-
json: async () => ({ data: "mocked" }),
|
|
513
|
-
});
|
|
514
|
-
});
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
---
|
|
518
|
-
|
|
519
|
-
## Common Test Scenarios
|
|
520
|
-
|
|
521
|
-
### Testing Configuration
|
|
522
|
-
|
|
523
|
-
```javascript
|
|
524
|
-
it("should accept bedrock as MODEL_PROVIDER", () => {
|
|
525
|
-
process.env.MODEL_PROVIDER = "bedrock";
|
|
526
|
-
process.env.AWS_BEDROCK_API_KEY = "test-key";
|
|
527
|
-
|
|
528
|
-
const config = require("../src/config");
|
|
529
|
-
|
|
530
|
-
assert.strictEqual(config.modelProvider.type, "bedrock");
|
|
531
|
-
});
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
### Testing Error Handling
|
|
535
|
-
|
|
536
|
-
```javascript
|
|
537
|
-
it("should throw error for invalid provider", () => {
|
|
538
|
-
process.env.MODEL_PROVIDER = "invalid";
|
|
539
|
-
|
|
540
|
-
assert.throws(
|
|
541
|
-
() => require("../src/config"),
|
|
542
|
-
/Unsupported MODEL_PROVIDER/
|
|
543
|
-
);
|
|
544
|
-
});
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
### Testing Async Retries
|
|
548
|
-
|
|
549
|
-
```javascript
|
|
550
|
-
it("should retry on transient failure", async () => {
|
|
551
|
-
let callCount = 0;
|
|
552
|
-
|
|
553
|
-
global.fetch = async () => {
|
|
554
|
-
callCount++;
|
|
555
|
-
if (callCount < 3) {
|
|
556
|
-
return { ok: false, status: 503 };
|
|
557
|
-
}
|
|
558
|
-
return { ok: true, json: async () => ({}) };
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
const result = await invokeWithRetry();
|
|
562
|
-
|
|
563
|
-
assert.strictEqual(callCount, 3);
|
|
564
|
-
assert.ok(result);
|
|
565
|
-
});
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
### Testing Circuit Breaker
|
|
569
|
-
|
|
570
|
-
```javascript
|
|
571
|
-
it("should open circuit after threshold failures", async () => {
|
|
572
|
-
const breaker = new CircuitBreaker({ threshold: 3 });
|
|
573
|
-
|
|
574
|
-
// Simulate 3 failures
|
|
575
|
-
for (let i = 0; i < 3; i++) {
|
|
576
|
-
await breaker.call(() => Promise.reject(new Error("fail")))
|
|
577
|
-
.catch(() => {});
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// Circuit should now be open
|
|
581
|
-
assert.strictEqual(breaker.state, "open");
|
|
582
|
-
});
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
---
|
|
586
|
-
|
|
587
|
-
## Troubleshooting Tests
|
|
588
|
-
|
|
589
|
-
### Tests Hanging
|
|
590
|
-
|
|
591
|
-
```bash
|
|
592
|
-
# Set timeout
|
|
593
|
-
npm test -- --timeout 5000
|
|
594
|
-
|
|
595
|
-
# Or in test file
|
|
596
|
-
it("should complete quickly", { timeout: 1000 }, async () => {
|
|
597
|
-
// Test code
|
|
598
|
-
});
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
### Tests Failing Intermittently
|
|
602
|
-
|
|
603
|
-
- Check for race conditions
|
|
604
|
-
- Add explicit waits for async operations
|
|
605
|
-
- Ensure tests don't depend on timing
|
|
606
|
-
|
|
607
|
-
### Module Cache Issues
|
|
608
|
-
|
|
609
|
-
```javascript
|
|
610
|
-
beforeEach(() => {
|
|
611
|
-
// Clear module cache
|
|
612
|
-
delete require.cache[require.resolve("../src/config")];
|
|
613
|
-
});
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
---
|
|
617
|
-
|
|
618
|
-
## Next Steps
|
|
619
|
-
|
|
620
|
-
- **[Contributing Guide](contributing.md)** - How to contribute
|
|
621
|
-
- **[Development Setup](contributing.md#development-setup)** - Set up dev environment
|
|
622
|
-
- **[GitHub Issues](https://github.com/vishalveerareddy123/Lynkr/issues)** - Report test failures
|
|
623
|
-
|
|
624
|
-
---
|
|
625
|
-
|
|
626
|
-
## Getting Help
|
|
627
|
-
|
|
628
|
-
- **[GitHub Discussions](https://github.com/vishalveerareddy123/Lynkr/discussions)** - Ask questions
|
|
629
|
-
- **[GitHub Issues](https://github.com/vishalveerareddy123/Lynkr/issues)** - Report bugs
|