@node-llm/testing 0.1.0 → 0.2.0

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.
@@ -33,7 +33,11 @@ describe("VCR: Global Configuration", () => {
33
33
  const CASSETTE_NAME = "global-config-keys";
34
34
  const CASSETTE_PATH = path.join(CASSETTE_DIR, `${CASSETTE_NAME}.json`);
35
35
 
36
- const vcr = setupVCR(CASSETTE_NAME, { mode: "record", cassettesDir: CASSETTE_DIR });
36
+ const vcr = setupVCR(CASSETTE_NAME, {
37
+ mode: "record",
38
+ cassettesDir: CASSETTE_DIR,
39
+ _allowRecordingInCI: true
40
+ });
37
41
  const llm = NodeLLM.withProvider("mock-provider");
38
42
 
39
43
  await llm.chat().ask("regular question");
@@ -53,7 +57,11 @@ describe("VCR: Global Configuration", () => {
53
57
  const CASSETTE_NAME = "global-config-patterns";
54
58
  const CASSETTE_PATH = path.join(CASSETTE_DIR, `${CASSETTE_NAME}.json`);
55
59
 
56
- const vcr = setupVCR(CASSETTE_NAME, { mode: "record", cassettesDir: CASSETTE_DIR });
60
+ const vcr = setupVCR(CASSETTE_NAME, {
61
+ mode: "record",
62
+ cassettesDir: CASSETTE_DIR,
63
+ _allowRecordingInCI: true
64
+ });
57
65
  const llm = NodeLLM.withProvider("mock-provider");
58
66
 
59
67
  await llm.chat().ask("Status of custom-secret-omega");
@@ -74,7 +82,11 @@ describe("VCR: Global Configuration", () => {
74
82
  const CASSETTE_NAME = "global-config-reset";
75
83
  const CASSETTE_PATH = path.join(CASSETTE_DIR, `${CASSETTE_NAME}.json`);
76
84
 
77
- const vcr = setupVCR(CASSETTE_NAME, { mode: "record", cassettesDir: CASSETTE_DIR });
85
+ const vcr = setupVCR(CASSETTE_NAME, {
86
+ mode: "record",
87
+ cassettesDir: CASSETTE_DIR,
88
+ _allowRecordingInCI: true
89
+ });
78
90
  const llm = NodeLLM.withProvider("mock-provider");
79
91
 
80
92
  await llm.chat().ask("to_reset should not be redacted");
@@ -34,7 +34,8 @@ describe("VCR: Interaction Mismatch Detection", () => {
34
34
  // First: Record with specific request
35
35
  const vcrRecord = setupVCR(CASSETTE_NAME, {
36
36
  mode: "record",
37
- cassettesDir: CASSETTE_DIR
37
+ cassettesDir: CASSETTE_DIR,
38
+ _allowRecordingInCI: true
38
39
  });
39
40
  const llmRecord = NodeLLM.withProvider("mock-provider");
40
41
  await llmRecord.chat().ask("Record this question");
@@ -0,0 +1,72 @@
1
+ import { test, expect, describe, afterEach } from "vitest";
2
+ import { withVCR, describeVCR } from "../../src/vcr.js";
3
+ import { NodeLLM, providerRegistry } from "@node-llm/core";
4
+ import { MockProvider } from "../helpers/MockProvider.js";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { Serializer } from "../../src/Serializer.js";
8
+
9
+ describe("VCR Advanced Types Persistence", () => {
10
+ const cassettePath = "test/cassettes/vcr-advanced-types-persistence/handles-rich-types.json";
11
+
12
+ afterEach(() => {
13
+ if (fs.existsSync(cassettePath)) {
14
+ // Clean up file
15
+ fs.rmSync(cassettePath);
16
+ // Try to clean up parent dir if empty (optional but good)
17
+ try {
18
+ fs.rmdirSync(path.dirname(cassettePath));
19
+ } catch {
20
+ /* ignore */
21
+ }
22
+ }
23
+ });
24
+
25
+ test("Persists Date and Map in cassettes", async () => {
26
+ const date = new Date("2024-01-01T00:00:00.000Z");
27
+ const map = new Map<string, string>([["key", "value"]]);
28
+
29
+ await describeVCR("VCR Advanced Types Persistence", async () => {
30
+ providerRegistry.register("mock-provider", () => new MockProvider() as any);
31
+
32
+ // 1. Record Phase
33
+ await withVCR(
34
+ "Handles Rich Types",
35
+ { mode: "record", _allowRecordingInCI: true },
36
+ async () => {
37
+ const llm = NodeLLM.withProvider("mock-provider");
38
+
39
+ // Pass rich types in params
40
+ await llm
41
+ .chat()
42
+ .withParams({
43
+ createdAt: date,
44
+ meta: map
45
+ })
46
+ .ask("Hello");
47
+ }
48
+ )();
49
+ });
50
+
51
+ // 2. Verify Disk Content (Serialization)
52
+ expect(fs.existsSync(cassettePath)).toBe(true);
53
+ const rawContent = fs.readFileSync(cassettePath, "utf-8");
54
+
55
+ // Should NOT contain raw ISO string only, but the typed wrapper
56
+ expect(rawContent).toContain('"$type": "Date"');
57
+ expect(rawContent).toContain('"value": "2024-01-01T00:00:00.000Z"');
58
+ expect(rawContent).toContain('"$type": "Map"');
59
+
60
+ // 3. Replay/Load Phase (Deserialization)
61
+ // We manually load to verify the deserialization logic
62
+ const cassette = Serializer.deserialize<any>(rawContent);
63
+ const request = cassette.interactions[0].request;
64
+
65
+ // Check that params are restored as real instances
66
+ expect(request.createdAt).toBeInstanceOf(Date);
67
+ expect(request.createdAt.toISOString()).toBe(date.toISOString());
68
+
69
+ expect(request.meta).toBeInstanceOf(Map);
70
+ expect(request.meta.get("key")).toBe("value");
71
+ });
72
+ });