ktx/packages/cli/test/clack.test.ts

37 lines
1.2 KiB
TypeScript
Raw Normal View History

feat(cli): setup progress spinners, Tab-to-select, and banner polish (#296) * fix(cli): double the height of the setup banner t crossbar * fix(cli): unify setup multi-select hints and make Tab the select key The six interactive multi-select surfaces in `ktx setup` documented three different hint voices, one had no hint at all, and they named two different select keys (Space vs Tab). Tab is the only key that can toggle selection without colliding with type-to-search input, so make it the single documented select key everywhere and compose every hint from one shared fragment vocabulary in prompt-navigation.ts. - Register `updateSettings({ aliases: { tab: 'space' } })` so Tab toggles flat multiselects; the alias applies only to non-text prompts, leaving typed search input (schema/Notion) untouched. - Add the missing hint to the agent-targets prompt and drop the stray "Space to select … Esc …" info line plus the now-dead writeSetupInfo helper. - Replace the schema-scope ad-hoc hint with the searchable-multiselect voice and standardize "filter" -> "search" vocabulary. - Delete DEFAULT_TREE_PICKER_HELP_TEXT and the unused TreePickerChrome.helpText seam; render the shared tree hint instead. * refactor(cli): show LLM check progress for every setup backend Rename runLlmHealthCheckWithProgress to validateModelWithProgress and wrap the Claude subscription and Codex auth probes in the same spinner progress as the Anthropic API and Vertex backends, so each backend shows consistent "Checking <provider> LLM" output during setup. * feat(cli): add ktx-orange progress spinners to setup steps Add a shared runWithCliSpinner helper and a TTY-aware createCliSpinner: an animated clack spinner in a terminal, and a static stderr-only spinner before raw-mode pickers (the table tree picker and demo tour), where the animated spinner's stdin grab would otherwise corrupt the next prompt. Wrap the slow setup waits in progress spinners: managed runtime install, embedding daemon start + first-run model download, embeddings health check, the connection-test gate, and source validation / dbt clone / Metabase discovery. Recolor every spinner frame from clack's magenta to the ktx mascot orange (#FF8A4C) via the static helper and clack's styleFrame option.
2026-06-12 16:43:10 +02:00
import { describe, expect, it } from 'vitest';
import { type KtxCliSpinner, runWithCliSpinner } from '../src/clack.js';
function makeSpinner() {
const events: string[] = [];
const spinner: KtxCliSpinner = {
start: (msg) => events.push(`start:${msg}`),
message: (msg) => events.push(`message:${msg}`),
stop: (msg) => events.push(`stop:${msg}`),
error: (msg) => events.push(`error:${msg}`),
};
return { events, spinner };
}
describe('runWithCliSpinner', () => {
it('starts then stops with the success text and returns the value', async () => {
const { events, spinner } = makeSpinner();
const value = await runWithCliSpinner(spinner, { start: 'Working…', success: 'Done', failure: 'Failed' }, async () => 42);
expect(value).toBe(42);
expect(events).toEqual(['start:Working…', 'stop:Done']);
});
it('errors with the failure text and rethrows when the work throws', async () => {
const { events, spinner } = makeSpinner();
const boom = new Error('boom');
await expect(
runWithCliSpinner(spinner, { start: 'Working…', success: 'Done', failure: 'Failed' }, async () => {
throw boom;
}),
).rejects.toBe(boom);
expect(events).toEqual(['start:Working…', 'error:Failed']);
});
});