Files
gbrain/test/skillpack-bootstrap-display.test.ts

107 lines
3.7 KiB
TypeScript

/**
* Tests for src/core/skillpack/bootstrap-display.ts — display-only
* runbook handler (codex T1).
*/
import { describe, test, expect, beforeAll, afterAll } from 'bun:test';
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import { buildBootstrapDisplay } from '../src/core/skillpack/bootstrap-display.ts';
import { SKILLPACK_API_VERSION, type SkillpackManifest } from '../src/core/skillpack/manifest-v1.ts';
function makeManifest(over: Partial<SkillpackManifest> = {}): SkillpackManifest {
return {
api_version: SKILLPACK_API_VERSION,
name: 'p',
version: '0.1.0',
description: 'd',
author: 'a',
license: 'MIT',
homepage: 'https://example.com',
gbrain_min_version: '0.36.0',
skills: ['skills/foo'],
...over,
};
}
let tmp: string;
beforeAll(() => {
tmp = mkdtempSync(join(tmpdir(), 'bootstrap-'));
});
afterAll(() => {
rmSync(tmp, { recursive: true, force: true });
});
describe('buildBootstrapDisplay', () => {
test('returns shown=false when manifest has no runbooks.bootstrap declared', () => {
const r = buildBootstrapDisplay({
packRoot: tmp,
manifest: makeManifest(),
workspace: '/ws',
});
expect(r.shown).toBe(false);
expect(r.text).toBe('');
expect(r.bootstrapPath).toBeNull();
});
test('returns shown=false when bootstrap.md is declared but missing on disk', () => {
const r = buildBootstrapDisplay({
packRoot: tmp,
manifest: makeManifest({
runbooks: { bootstrap: 'runbooks/bootstrap.md' },
}),
workspace: '/ws',
});
expect(r.shown).toBe(false);
// bootstrapPath is join(packRoot, relPath), so it carries '\' on win32.
expect(r.bootstrapPath).toContain(join('runbooks', 'bootstrap.md'));
});
test('returns shown=false when bootstrap.md is empty (whitespace only)', () => {
const packRoot = join(tmp, 'empty-bootstrap');
mkdirSync(join(packRoot, 'runbooks'), { recursive: true });
writeFileSync(join(packRoot, 'runbooks/bootstrap.md'), ' \n \n');
const r = buildBootstrapDisplay({
packRoot,
manifest: makeManifest({ runbooks: { bootstrap: 'runbooks/bootstrap.md' } }),
workspace: '/ws',
});
expect(r.shown).toBe(false);
});
test('returns shown=true with framed text when bootstrap.md has content', () => {
const packRoot = join(tmp, 'with-bootstrap');
mkdirSync(join(packRoot, 'runbooks'), { recursive: true });
writeFileSync(
join(packRoot, 'runbooks/bootstrap.md'),
'1. agent: gbrain put_page wiki/example\n2. show user: "All set."\n',
);
const r = buildBootstrapDisplay({
packRoot,
manifest: makeManifest({ runbooks: { bootstrap: 'runbooks/bootstrap.md' } }),
workspace: '/ws',
});
expect(r.shown).toBe(true);
expect(r.text).toContain('BOOTSTRAP STEPS');
expect(r.text).toContain('agent decides what to run');
expect(r.text).toContain('deliberately does NOT auto-execute');
expect(r.text).toContain('1. agent: gbrain put_page wiki/example');
expect(r.text).toContain('2. show user: "All set."');
expect(r.text).toContain('End of bootstrap steps');
});
test('frames the content with horizontal rules above and below', () => {
const packRoot = join(tmp, 'rules-bootstrap');
mkdirSync(join(packRoot, 'runbooks'), { recursive: true });
writeFileSync(join(packRoot, 'runbooks/bootstrap.md'), 'do the thing');
const r = buildBootstrapDisplay({
packRoot,
manifest: makeManifest({ runbooks: { bootstrap: 'runbooks/bootstrap.md' } }),
workspace: '/ws',
});
expect(r.shown).toBe(true);
expect(r.text).toMatch(/═{20,}/);
});
});