aboutsummaryrefslogtreecommitdiff
path: root/modules/test/test-help-and-lessons.js
blob: c4eb5ae73fd79e5d77b7646f29d70f9a4be2c0b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// modules/test/test-help-and-lessons.js — run: node
// MAINT-019: `help <cmd>` must not answer "No help available" for a command that exists.
// MAINT-020: loop lessons must be written to /lessons, never into /skills.
const fsMod = require('fs'), path = require('path');
const ROOT = path.join(__dirname, '..');
const store = {};
global.localStorage = { getItem: k => (k in store ? store[k] : null), setItem: (k, v) => { store[k] = String(v); }, removeItem: k => { delete store[k]; } };
global.indexedDB = { open() { throw new Error('no idb'); }, deleteDatabase() { throw new Error('no idb'); } };
global.window = global;

const SystemModule = new Function(fsMod.readFileSync(path.join(ROOT, 'core', 'module-system.js'), 'utf8') + '\nreturn SystemModule;')();

let fails = 0, passes = 0;
function ok(name, cond, detail) {
    if (cond) { passes++; return; }
    fails++;
    console.log('FAIL ' + name + (detail ? ' — ' + detail : ''));
}

function mkHelp(commands, help) {
    const out = [];
    const sys = Object.create(SystemModule.prototype);
    sys.terminal = {
        print: (m, t) => out.push({ text: String(m), type: t || '' }),
        log: () => {},
        moduleManager: {
            getAllCommands: () => commands,
            getAllHelp: () => help,
        },
    };
    return { sys, out };
}
const text = out => out.map(o => o.text).join(' | ');

// A. a documented command prints its help line
{
    const { sys, out } = mkHelp({ ls: 'FileSystemModule' }, { ls: 'ls [path] — List files' });
    sys.handleHelp(['ls']);
    ok('A1 documented command shows its help', /ls \[path\]/.test(text(out)), text(out));
}

// B. an undocumented but registered command names its owner instead of denying it exists
{
    const { sys, out } = mkHelp({ 'agent-register': 'AgentRegistryModule' }, {});
    sys.handleHelp(['agent-register']);
    const t = text(out);
    ok('B1 no "No help available" for a registered command', !/No help available/.test(t), t);
    ok('B2 the owning module is named', /AgentRegistryModule/.test(t), t);
    ok('B3 it still says there is no help line', /no help line/i.test(t), t);
}

// C. a command that really does not exist still says so
{
    const { sys, out } = mkHelp({ ls: 'FileSystemModule' }, { ls: 'ls — List' });
    sys.handleHelp(['definitely-not-a-command']);
    ok('C1 unknown command still reports no help', /No help available/.test(text(out)), text(out));
}

// D. MAINT-020: no lesson is written into /skills, and /lessons is used instead
{
    const src = fsMod.readFileSync(path.join(ROOT, 'core', 'module-aiassist.js'), 'utf8');
    const writesSkils = /writeFile\(\s*'\/skills\/'\s*\+\s*skillName/.test(src);
    ok('D1 no lesson file is written into /skills', !writesSkils);
    ok('D2 lesson files are written into /lessons', /writeFile\(\s*'\/lessons\/'\s*\+\s*skillName/.test(src));
    ok('D3 the lessons index is written to /lessons', /fsWriteJSON\(\s*'\/lessons\/index\.json'/.test(src));
    ok('D4 the reader still handles legacy /skills lessons', /fs\.readFile\('\/skills\/' \+ recentLessons\[li\] \+ '\.md'\)/.test(src));
    ok('D5 legacy lessons are cleaned out of the skills index once', /indexOf\('loop-lesson-'\) === 0/.test(src));
}

if (fails === 0) {
    console.log('test-help-and-lessons: ' + passes + ' passed, 0 failed');
} else {
    console.log('test-help-and-lessons: ' + passes + ' passed, ' + fails + ' FAILED');
    process.exit(1);
}