Files
smoidoandClaude Opus 5 51e42823d1 Tests, licence, and the tooling to keep the repo consistent
A test suite with no dependencies beyond bash and the Python standard
library, run by one command:

  scripts/test.sh                    (or: make test)
  scripts/test.sh --windows [host]   adds the PowerShell suite over SSH

- tests/static.sh: script syntax, JSON validity, VERSION against the widget
  manifest and CHANGELOG, providers.json against the kinds, probes and checks
  the code implements (and ids that would shadow a command), qmllint and
  shellcheck when installed.
- tests/python: unit tests for cm-json.py - providers and the column contract
  bash depends on, the original three scaffolds byte for byte, every
  catalogue parser and the cache, session scan/dismiss/repair, rename,
  defaults, health, the cost guard.
- tests/cli: the CLI in a sandbox with its own HOME, CM_ROOT,
  CLAUDE_CONFIG_DIR and a file-only vault, against fake Ollama, LM Studio,
  keyed-gateway and proxy servers - preflight, presets, models, doctor, a real
  switch, sessions, and the key helper under a rename race.
- tests/windows: the same idea on a Windows host, with USERPROFILE pointed at
  a temp folder so the real install is never touched.

Also: MIT licence, CHANGELOG.md reconstructed from history, .editorconfig and
.gitattributes pinning LF everywhere (what the tree already is), and
scripts/bump-version.sh, since the version lives in two files and drifted
once before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 01:42:38 +03:00

62 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Preset lifecycle: names, new/rename/rm, and the per-provider default.
. "$(dirname "$0")/../lib.sh"
run_cm preset show ../../etc/passwd
expect_rc 1 'a path is not a preset name'
expect_out 'invalid preset name' 'and it says why'
run_cm preset new .hidden
expect_rc 1 'a leading dot is refused'
run_cm preset new a/b
expect_rc 1 'a slash is refused'
run_cm preset new cheap
expect_rc 0 'new copies default'
expect_eq "$(jget "$P/cheap.json" provider)" openrouter 'the copy keeps the provider'
run_cm preset new z2 --provider zai
expect_out "from 'zai'" "--provider copies that provider's default"
run_cm preset new z3 --provider zai default
expect_rc 1 'copying across providers is refused'
run_cm preset new b1 --provider ollama --blank
expect_eq "$(jget "$P/b1.json" auth.token)" ollama "a blank preset carries its provider's token"
run_cm preset new b2 --blank
expect_rc 1 '--blank needs --provider'
run_cm preset new x --provider foo
expect_rc 1 'an unknown provider is refused'
run_cm preset set nope opus x
expect_rc 1 'setting a tier on a missing preset is refused'
expect_no_file "$P/nope.json" 'and does not create it'
run_cm preset rename cheap cheap2
expect_file "$P/cheap2.json" 'rename moves the file'
expect_no_file "$P/cheap.json" 'and removes the old name'
run_cm preset rename cheap2 default
expect_rc 1 'renaming onto an existing preset is refused'
set_state openrouter cheap2
run_cm preset rename cheap2 cheap3
expect_eq "$(jget "$CM_ROOT/state.json" preset)" cheap3 'state follows the active preset'
run_cm preset rm cheap3
expect_rc 1 'the active preset cannot be deleted'
set_state anthropic
run_cm preset default openrouter cheap3
expect_eq "$("$CM" preset default openrouter)" cheap3 'a chosen default is used'
run_cm preset rename cheap3 cheap4
expect_eq "$(jget "$CM_ROOT/defaults.json" openrouter)" cheap4 'the choice follows a rename'
run_cm preset rm cheap4
expect_eq "$(jget "$CM_ROOT/defaults.json" openrouter)" '' 'deleting clears the choice'
expect_eq "$("$CM" preset default openrouter)" default 'and the built-in applies again'
run_cm preset default openrouter zai
expect_rc 1 "a default from another provider is refused"
"$CM" preset new c5 >/dev/null 2>&1
"$CM" preset default openrouter c5 >/dev/null 2>&1
rm -f "$P/c5.json"
expect_eq "$("$CM" preset default openrouter)" default 'a vanished choice falls back'
run_cm preset rm z2
run_cm preset rm zai
expect_out 'that was the last zai preset' 'removing the last preset warns'
finish