Skip to content

Commit 9207dbd

Browse files
committed
test: cover graph3d_transform.linkKey + app.formatQn (node tests)
1 parent b63dd00 commit 9207dbd

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

tests/test_app_format.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* Tests for formatQn() in codegraph/web/static/app.js
2+
*
3+
* app.js is a classic browser script. Extract the `formatQn` function source
4+
* (along with its `esc` dependency) and evaluate them in a Node vm sandbox.
5+
*
6+
* Run with: node --test tests/test_app_format.js
7+
*/
8+
'use strict';
9+
10+
const test = require('node:test');
11+
const assert = require('node:assert/strict');
12+
const fs = require('node:fs');
13+
const path = require('node:path');
14+
const vm = require('node:vm');
15+
16+
const APP_JS = path.join(
17+
__dirname, '..', 'codegraph', 'web', 'static', 'app.js'
18+
);
19+
20+
function loadFormatQn() {
21+
const source = fs.readFileSync(APP_JS, 'utf-8');
22+
const escMatch = source.match(/function esc\(s\)\s*\{[\s\S]*?\n\}/);
23+
if (!escMatch) throw new Error('esc() not found in app.js');
24+
const fmtMatch = source.match(/function formatQn\(qn,\s*opts\)\s*\{[\s\S]*?\n\}/);
25+
if (!fmtMatch) throw new Error('formatQn() not found in app.js');
26+
const sandbox = {};
27+
vm.createContext(sandbox);
28+
vm.runInContext(
29+
`${escMatch[0]}\n${fmtMatch[0]}\nthis.formatQn = formatQn;`,
30+
sandbox,
31+
);
32+
return sandbox.formatQn;
33+
}
34+
35+
const formatQn = loadFormatQn();
36+
37+
test('formatQn renders single-segment as leaf', () => {
38+
const out = formatQn('foo', { maxParts: 3 });
39+
assert.match(out, /qn-key/);
40+
assert.match(out, />foo</);
41+
});
42+
43+
test('formatQn dims parent path', () => {
44+
const out = formatQn('a.b.c', { maxParts: 3 });
45+
assert.match(out, /qn-dim/);
46+
assert.match(out, /a\.b\./);
47+
assert.match(out, />c</);
48+
});
49+
50+
test('formatQn truncates long paths with ellipsis', () => {
51+
const out = formatQn('a.b.c.d.e', { maxParts: 2 });
52+
assert.match(out, //);
53+
assert.match(out, />e</);
54+
});
55+
56+
test('formatQn escapes HTML in qn segments', () => {
57+
const out = formatQn('a.<b>', { maxParts: 3 });
58+
assert.match(out, /&lt;b&gt;/);
59+
assert.doesNotMatch(out, /<b>/);
60+
});
61+
62+
test('formatQn handles null gracefully', () => {
63+
const out = formatQn(null, { maxParts: 3 });
64+
// null is coalesced to '' before splitting; one empty leaf, no head.
65+
assert.match(out, /qn-key/);
66+
assert.doesNotMatch(out, /null/);
67+
});
68+
69+
test('formatQn defaults maxParts when opts omitted', () => {
70+
const out = formatQn('a.b.c.d.e');
71+
// default maxParts = 3 -> visible head = last 2 segments
72+
assert.match(out, //);
73+
});

tests/test_graph3d_transform.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,53 @@ test('edgeColor varies by edge kind', () => {
175175
assert.notEqual(a, b);
176176
assert.notEqual(b, c);
177177
});
178+
179+
// ---------------------------------------------------------------------------
180+
// linkKey() — pure helper used for dedup. Not exported; load via vm.
181+
// ---------------------------------------------------------------------------
182+
183+
const fs = require('node:fs');
184+
const vm = require('node:vm');
185+
186+
function loadLinkKey() {
187+
const file = path.join(
188+
__dirname, '..', 'codegraph', 'web', 'static', 'views', 'graph3d_transform.js'
189+
);
190+
const source = fs.readFileSync(file, 'utf-8');
191+
const match = source.match(/function linkKey\(source,\s*target\)\s*\{[\s\S]*?\n\}/);
192+
if (!match) throw new Error('linkKey() not found in graph3d_transform.js');
193+
const sandbox = {};
194+
vm.createContext(sandbox);
195+
vm.runInContext(`${match[0]}\nthis.linkKey = linkKey;`, sandbox);
196+
return sandbox.linkKey;
197+
}
198+
199+
const linkKey = loadLinkKey();
200+
201+
test('linkKey accepts plain string ids', () => {
202+
assert.equal(linkKey('a', 'b'), 'a->b');
203+
});
204+
205+
test('linkKey extracts .id from object source', () => {
206+
assert.equal(linkKey({ id: 'x' }, 'y'), 'x->y');
207+
});
208+
209+
test('linkKey extracts .id from object target', () => {
210+
assert.equal(linkKey('a', { id: 'b' }), 'a->b');
211+
});
212+
213+
test('linkKey works for both objects', () => {
214+
assert.equal(linkKey({ id: 'foo' }, { id: 'bar' }), 'foo->bar');
215+
});
216+
217+
test('linkKey stringifies non-string ids', () => {
218+
assert.equal(linkKey(1, 2), '1->2');
219+
});
220+
221+
test('linkKey is deterministic — same inputs same output', () => {
222+
assert.equal(linkKey('a', 'b'), linkKey('a', 'b'));
223+
});
224+
225+
test('linkKey distinguishes direction', () => {
226+
assert.notEqual(linkKey('a', 'b'), linkKey('b', 'a'));
227+
});

0 commit comments

Comments
 (0)