Files
nexu-io__open-design/packages/contracts/tests/plugin-block.test.ts
Ethan Guo ca9c2d10b5 test(contracts,agui-adapter): cover error helpers, schema parse, ctx.now fallback (#2393)
* test(contracts): cover error helpers and schema parse round-trips

* test(agui-adapter): cover ctx.now fallback and optional field passthrough
2026-06-29 12:41:26 +00:00

92 lines
3.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { renderPluginBlock } from '../src/prompts/plugin-block.js';
import type { AppliedPluginSnapshot } from '../src/plugins/apply.js';
function makeSnapshot(overrides: Partial<AppliedPluginSnapshot> = {}): AppliedPluginSnapshot {
return {
snapshotId: 'snap-1',
pluginId: 'demo-plugin',
pluginVersion: '1.0.0',
manifestSourceDigest: 'sha256:0',
inputs: {},
resolvedContext: { items: [] },
capabilitiesGranted: [],
capabilitiesRequired: [],
assetsStaged: [],
taskKind: 'new-generation',
appliedAt: 0,
connectorsRequired: [],
connectorsResolved: [],
mcpServers: [],
status: 'fresh',
...overrides,
} as AppliedPluginSnapshot;
}
describe('renderPluginBlock', () => {
it('uses pluginTitle when present, falls back to pluginId otherwise', () => {
const withTitle = renderPluginBlock(makeSnapshot({ pluginTitle: 'Pitch Deck' }));
expect(withTitle).toContain('**Pitch Deck** (`demo-plugin@1.0.0`)');
const noTitle = renderPluginBlock(makeSnapshot());
expect(noTitle).toContain('**demo-plugin** (`demo-plugin@1.0.0`)');
});
it('omits Plugin inputs section when no inputs supplied', () => {
const out = renderPluginBlock(makeSnapshot());
expect(out).not.toContain('## Plugin inputs');
});
it('renders inputs in sorted-key order, formatting empty strings as (empty)', () => {
const out = renderPluginBlock(
makeSnapshot({
inputs: { topic: 'pricing', empty: '', count: 3, flag: true },
}),
);
expect(out).toContain('## Plugin inputs');
expect(out).toContain('- **count**: 3');
expect(out).toContain('- **empty**: (empty)');
expect(out).toContain('- **flag**: true');
expect(out).toContain('- **topic**: pricing');
const indices = ['count', 'empty', 'flag', 'topic'].map((k) =>
out.indexOf(`- **${k}**`),
);
for (let i = 1; i < indices.length; i += 1) {
expect(indices[i]!).toBeGreaterThan(indices[i - 1]!);
}
});
it('omits Plugin atoms section when resolvedContext.atoms is empty or absent', () => {
expect(renderPluginBlock(makeSnapshot())).not.toContain('## Plugin atoms');
expect(
renderPluginBlock(
makeSnapshot({ resolvedContext: { items: [], atoms: [] } }),
),
).not.toContain('## Plugin atoms');
});
it('renders one bullet per atom id when atoms are present', () => {
const out = renderPluginBlock(
makeSnapshot({
resolvedContext: { items: [], atoms: ['todo-write', 'direction-picker'] },
}),
);
expect(out).toContain('## Plugin atoms');
expect(out).toContain('- `todo-write`');
expect(out).toContain('- `direction-picker`');
});
it('trims plugin description and example query', () => {
const out = renderPluginBlock(
makeSnapshot({
pluginDescription: ' Walks a designer through a pitch deck. \n',
query: ' write me a deck about fluorine ',
}),
);
expect(out).toContain('Walks a designer through a pitch deck.');
expect(out).not.toContain(' Walks');
expect(out).toContain('_write me a deck about fluorine_');
});
});