js: add test suite with 10 tests covering all operations
Swadhin Biswas committed 7 months ago
746f10f
1 parent 1ce48f6
commit 746f10f
1 file changed
+150 -0
Showing 1 changed file+150-0
▼JS/test.ts
+150-0
| @@ -0,0 +1,150 @@ | ||
1 | +/** | |
2 | + * Tests for contexa TypeScript package. | |
3 | + * Run with: tsx --test test.ts | |
4 | + */ | |
5 | + | |
6 | +import { test } from "node:test"; | |
7 | +import assert from "node:assert/strict"; | |
8 | +import { mkdtempSync, rmSync, existsSync } from "node:fs"; | |
9 | +import { tmpdir } from "node:os"; | |
10 | +import { join } from "node:path"; | |
11 | +import { GCCWorkspace } from "./src/workspace"; | |
12 | + | |
13 | +function makeWorkspace(): { dir: string; ws: GCCWorkspace } { | |
14 | + const dir = mkdtempSync(join(tmpdir(), "gcc-test-")); | |
15 | + const ws = new GCCWorkspace(dir); | |
16 | + ws.init("Test project roadmap"); | |
17 | + return { dir, ws }; | |
18 | +} | |
19 | + | |
20 | +test("init creates .GCC structure", () => { | |
21 | + const { dir } = makeWorkspace(); | |
22 | + try { | |
23 | + assert.ok(existsSync(join(dir, ".GCC/main.md"))); | |
24 | + assert.ok(existsSync(join(dir, ".GCC/branches/main/log.md"))); | |
25 | + assert.ok(existsSync(join(dir, ".GCC/branches/main/commit.md"))); | |
26 | + assert.ok(existsSync(join(dir, ".GCC/branches/main/metadata.yaml"))); | |
27 | + } finally { | |
28 | + rmSync(dir, { recursive: true }); | |
29 | + } | |
30 | +}); | |
31 | + | |
32 | +test("logOTA increments step", () => { | |
33 | + const { dir, ws } = makeWorkspace(); | |
34 | + try { | |
35 | + const r1 = ws.logOTA("obs1", "thought1", "action1"); | |
36 | + const r2 = ws.logOTA("obs2", "thought2", "action2"); | |
37 | + assert.equal(r1.step, 1); | |
38 | + assert.equal(r2.step, 2); | |
39 | + } finally { | |
40 | + rmSync(dir, { recursive: true }); | |
41 | + } | |
42 | +}); | |
43 | + | |
44 | +test("commit writes checkpoint with correct fields", () => { | |
45 | + const { dir, ws } = makeWorkspace(); | |
46 | + try { | |
47 | + const c = ws.commit("Initial scaffold done"); | |
48 | + assert.equal(c.thisCommitContribution, "Initial scaffold done"); | |
49 | + assert.equal(c.branchName, "main"); | |
50 | + assert.equal(c.commitId.length, 8); | |
51 | + } finally { | |
52 | + rmSync(dir, { recursive: true }); | |
53 | + } | |
54 | +}); | |
55 | + | |
56 | +test("branch creates isolated workspace", () => { | |
57 | + const { dir, ws } = makeWorkspace(); | |
58 | + try { | |
59 | + ws.branch("experiment-a", "Try alternative algorithm"); | |
60 | + assert.equal(ws.currentBranch, "experiment-a"); | |
61 | + const branches = ws.listBranches(); | |
62 | + assert.ok(branches.includes("main")); | |
63 | + assert.ok(branches.includes("experiment-a")); | |
64 | + } finally { | |
65 | + rmSync(dir, { recursive: true }); | |
66 | + } | |
67 | +}); | |
68 | + | |
69 | +test("branch OTA log starts empty", () => { | |
70 | + const { dir, ws } = makeWorkspace(); | |
71 | + try { | |
72 | + ws.logOTA("main obs", "main thought", "main action"); | |
73 | + ws.branch("clean-branch", "Fresh start"); | |
74 | + // context on new branch should have no OTA | |
75 | + const ctx = ws.context("clean-branch", 1); | |
76 | + assert.equal(ctx.otaRecords.length, 0); | |
77 | + } finally { | |
78 | + rmSync(dir, { recursive: true }); | |
79 | + } | |
80 | +}); | |
81 | + | |
82 | +test("merge integrates branch into main", () => { | |
83 | + const { dir, ws } = makeWorkspace(); | |
84 | + try { | |
85 | + ws.commit("Main first commit"); | |
86 | + ws.branch("feature", "Add feature X"); | |
87 | + ws.logOTA("feature obs", "feature thought", "feature action"); | |
88 | + ws.commit("Feature X implemented"); | |
89 | + const mergeCommit = ws.merge("feature", undefined, "main"); | |
90 | + assert.ok(mergeCommit.thisCommitContribution.includes("feature")); | |
91 | + assert.equal(ws.currentBranch, "main"); | |
92 | + } finally { | |
93 | + rmSync(dir, { recursive: true }); | |
94 | + } | |
95 | +}); | |
96 | + | |
97 | +test("context K=1 returns last commit only", () => { | |
98 | + const { dir, ws } = makeWorkspace(); | |
99 | + try { | |
100 | + ws.commit("C1"); | |
101 | + ws.commit("C2"); | |
102 | + ws.commit("C3"); | |
103 | + const ctx = ws.context(undefined, 1); | |
104 | + assert.equal(ctx.commits.length, 1); | |
105 | + assert.equal(ctx.commits[0]!.thisCommitContribution, "C3"); | |
106 | + } finally { | |
107 | + rmSync(dir, { recursive: true }); | |
108 | + } | |
109 | +}); | |
110 | + | |
111 | +test("context K=3 returns last 3 commits", () => { | |
112 | + const { dir, ws } = makeWorkspace(); | |
113 | + try { | |
114 | + ws.commit("C1"); | |
115 | + ws.commit("C2"); | |
116 | + ws.commit("C3"); | |
117 | + ws.commit("C4"); | |
118 | + const ctx = ws.context(undefined, 3); | |
119 | + assert.equal(ctx.commits.length, 3); | |
120 | + } finally { | |
121 | + rmSync(dir, { recursive: true }); | |
122 | + } | |
123 | +}); | |
124 | + | |
125 | +test("branch metadata records purpose and parent", () => { | |
126 | + const { dir, ws } = makeWorkspace(); | |
127 | + try { | |
128 | + ws.branch("jwt-branch", "JWT auth experiment"); | |
129 | + const ctx = ws.context("jwt-branch", 1); | |
130 | + assert.equal(ctx.metadata?.purpose, "JWT auth experiment"); | |
131 | + assert.equal(ctx.metadata?.createdFrom, "main"); | |
132 | + assert.equal(ctx.metadata?.status, "active"); | |
133 | + } finally { | |
134 | + rmSync(dir, { recursive: true }); | |
135 | + } | |
136 | +}); | |
137 | + | |
138 | +test("merge marks branch as merged", () => { | |
139 | + const { dir, ws } = makeWorkspace(); | |
140 | + try { | |
141 | + ws.branch("to-merge", "Will be merged"); | |
142 | + ws.commit("Branch work done"); | |
143 | + ws.merge("to-merge", undefined, "main"); | |
144 | + const ctx = ws.context("to-merge", 1); | |
145 | + assert.equal(ctx.metadata?.status, "merged"); | |
146 | + assert.equal(ctx.metadata?.mergedInto, "main"); | |
147 | + } finally { | |
148 | + rmSync(dir, { recursive: true }); | |
149 | + } | |
150 | +}); | |
0 | 151 | |