ktx/packages/cli/test/reveal-password-prompt.test.ts
Andrey Avtomonov c2beaf7d55
feat(setup): wizard prompt tweaks and quieter query-history filter output (#259)
Setup wizard flow tweaks:
- Add a reveal-tail password prompt (reveal-password-prompt.ts) that unmasks
  the last few characters of a typed/pasted secret, and wire it into the setup
  prompt adapter in place of clack's password(); adds the @clack/core dep.
- Reorder wizard select options: surface "Paste a key" before the
  environment-variable option across embeddings/models/sources, promote
  Metabase/Notion in the source list, put Git URL before Local path, reorder
  the Notion crawl-mode choices, and relabel the sources "Done" action.

Query-history filter picker output:
- Collapse the per-template parse-failure lines into a single count in the
  setup output and route the full template-id list to --debug stderr.
- Model parse failures as a structured parseFailedTemplateIds field instead of
  warning strings.
- Add a privacy-safe query_history_filter_completed telemetry event
  (counts/enums only), mirrored into the Python daemon schema.
2026-06-04 14:11:08 +02:00

40 lines
1.5 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { maskRevealingTail } from '../src/reveal-password-prompt.js';
const MASK = '▪';
describe('maskRevealingTail', () => {
it('reveals the last `tail` characters of a long value', () => {
const value = 'example-token-value-abcd';
const masked = maskRevealingTail(value, MASK, 4);
expect(masked).toBe(`${MASK.repeat(value.length - 4)}abcd`);
expect(masked.endsWith('abcd')).toBe(true);
});
it('keeps the same length as the input so cursor slicing stays aligned', () => {
for (const secret of ['', 'a', 'abcdefgh', 'abcdefghijklmnop']) {
expect(maskRevealingTail(secret, MASK, 4)).toHaveLength(secret.length);
}
});
it('fully masks secrets that are not longer than tail * 2', () => {
expect(maskRevealingTail('abcdefgh', MASK, 4)).toBe(MASK.repeat(8));
expect(maskRevealingTail('abcd', MASK, 4)).toBe(MASK.repeat(4));
expect(maskRevealingTail('ab', MASK, 4)).toBe(MASK.repeat(2));
});
it('reveals the tail once the secret crosses the tail * 2 boundary', () => {
// length 9 > 8 → reveal last 4, hide the first 5
expect(maskRevealingTail('abcdefghi', MASK, 4)).toBe(`${MASK.repeat(5)}fghi`);
});
it('fully masks an empty value', () => {
expect(maskRevealingTail('', MASK, 4)).toBe('');
});
it('honors a custom tail count', () => {
// tail 2 reveals only when length > 4
expect(maskRevealingTail('abcde', MASK, 2)).toBe(`${MASK.repeat(3)}de`);
expect(maskRevealingTail('abcd', MASK, 2)).toBe(MASK.repeat(4));
});
});