@camaradesuk/git-worktree-tools 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -1
- package/package.json +12 -3
- package/schemas/worktreerc.schema.json +1 -1
- package/dist/api/list.test.d.ts +0 -5
- package/dist/api/list.test.d.ts.map +0 -1
- package/dist/api/list.test.js +0 -390
- package/dist/api/list.test.js.map +0 -1
- package/dist/cli/cleanpr.test.d.ts +0 -2
- package/dist/cli/cleanpr.test.d.ts.map +0 -1
- package/dist/cli/cleanpr.test.js +0 -954
- package/dist/cli/cleanpr.test.js.map +0 -1
- package/dist/cli/lswt.test.d.ts +0 -2
- package/dist/cli/lswt.test.d.ts.map +0 -1
- package/dist/cli/lswt.test.js +0 -376
- package/dist/cli/lswt.test.js.map +0 -1
- package/dist/cli/newpr.test.d.ts +0 -2
- package/dist/cli/newpr.test.d.ts.map +0 -1
- package/dist/cli/newpr.test.js +0 -1182
- package/dist/cli/newpr.test.js.map +0 -1
- package/dist/cli/prs.test.d.ts +0 -8
- package/dist/cli/prs.test.d.ts.map +0 -1
- package/dist/cli/prs.test.js +0 -463
- package/dist/cli/prs.test.js.map +0 -1
- package/dist/cli/wt/clean.test.d.ts +0 -8
- package/dist/cli/wt/clean.test.d.ts.map +0 -1
- package/dist/cli/wt/clean.test.js +0 -624
- package/dist/cli/wt/clean.test.js.map +0 -1
- package/dist/cli/wt/completion.test.d.ts +0 -5
- package/dist/cli/wt/completion.test.d.ts.map +0 -1
- package/dist/cli/wt/completion.test.js +0 -275
- package/dist/cli/wt/completion.test.js.map +0 -1
- package/dist/cli/wt/config.test.d.ts +0 -7
- package/dist/cli/wt/config.test.d.ts.map +0 -1
- package/dist/cli/wt/config.test.js +0 -440
- package/dist/cli/wt/config.test.js.map +0 -1
- package/dist/cli/wt/entry.test.d.ts +0 -8
- package/dist/cli/wt/entry.test.d.ts.map +0 -1
- package/dist/cli/wt/entry.test.js +0 -201
- package/dist/cli/wt/entry.test.js.map +0 -1
- package/dist/cli/wt/init.test.d.ts +0 -5
- package/dist/cli/wt/init.test.d.ts.map +0 -1
- package/dist/cli/wt/init.test.js +0 -165
- package/dist/cli/wt/init.test.js.map +0 -1
- package/dist/cli/wt/init.unit.test.d.ts +0 -5
- package/dist/cli/wt/init.unit.test.d.ts.map +0 -1
- package/dist/cli/wt/init.unit.test.js +0 -432
- package/dist/cli/wt/init.unit.test.js.map +0 -1
- package/dist/cli/wt/interactive-menu.test.d.ts +0 -12
- package/dist/cli/wt/interactive-menu.test.d.ts.map +0 -1
- package/dist/cli/wt/interactive-menu.test.js +0 -796
- package/dist/cli/wt/interactive-menu.test.js.map +0 -1
- package/dist/cli/wt/list.test.d.ts +0 -10
- package/dist/cli/wt/list.test.d.ts.map +0 -1
- package/dist/cli/wt/list.test.js +0 -157
- package/dist/cli/wt/list.test.js.map +0 -1
- package/dist/cli/wt/prs.test.d.ts +0 -5
- package/dist/cli/wt/prs.test.d.ts.map +0 -1
- package/dist/cli/wt/prs.test.js +0 -410
- package/dist/cli/wt/prs.test.js.map +0 -1
- package/dist/cli/wt/run-command.test.d.ts +0 -5
- package/dist/cli/wt/run-command.test.d.ts.map +0 -1
- package/dist/cli/wt/run-command.test.js +0 -88
- package/dist/cli/wt/run-command.test.js.map +0 -1
- package/dist/cli/wt/state.test.d.ts +0 -9
- package/dist/cli/wt/state.test.d.ts.map +0 -1
- package/dist/cli/wt/state.test.js +0 -127
- package/dist/cli/wt/state.test.js.map +0 -1
- package/dist/cli/wt/wt.test.d.ts +0 -8
- package/dist/cli/wt/wt.test.d.ts.map +0 -1
- package/dist/cli/wt/wt.test.js +0 -739
- package/dist/cli/wt/wt.test.js.map +0 -1
- package/dist/cli/wt.unit.test.d.ts +0 -7
- package/dist/cli/wt.unit.test.d.ts.map +0 -1
- package/dist/cli/wt.unit.test.js +0 -160
- package/dist/cli/wt.unit.test.js.map +0 -1
- package/dist/cli/wtconfig.test.d.ts +0 -5
- package/dist/cli/wtconfig.test.d.ts.map +0 -1
- package/dist/cli/wtconfig.test.js +0 -1289
- package/dist/cli/wtconfig.test.js.map +0 -1
- package/dist/cli/wtlink.test.d.ts +0 -2
- package/dist/cli/wtlink.test.d.ts.map +0 -1
- package/dist/cli/wtlink.test.js +0 -249
- package/dist/cli/wtlink.test.js.map +0 -1
- package/dist/cli/wtstate.test.d.ts +0 -5
- package/dist/cli/wtstate.test.d.ts.map +0 -1
- package/dist/cli/wtstate.test.js +0 -193
- package/dist/cli/wtstate.test.js.map +0 -1
- package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts +0 -2
- package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts.map +0 -1
- package/dist/e2e/cleanpr/cleanpr.e2e.test.js +0 -326
- package/dist/e2e/cleanpr/cleanpr.e2e.test.js.map +0 -1
- package/dist/e2e/cli.e2e.test.d.ts +0 -2
- package/dist/e2e/cli.e2e.test.d.ts.map +0 -1
- package/dist/e2e/cli.e2e.test.js +0 -417
- package/dist/e2e/cli.e2e.test.js.map +0 -1
- package/dist/e2e/lswt/lswt.e2e.test.d.ts +0 -2
- package/dist/e2e/lswt/lswt.e2e.test.d.ts.map +0 -1
- package/dist/e2e/lswt/lswt.e2e.test.js +0 -361
- package/dist/e2e/lswt/lswt.e2e.test.js.map +0 -1
- package/dist/e2e/newpr/newpr.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr/newpr.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr/newpr.e2e.test.js +0 -286
- package/dist/e2e/newpr/newpr.e2e.test.js.map +0 -1
- package/dist/e2e/newpr/scenarios.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr/scenarios.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr/scenarios.e2e.test.js +0 -426
- package/dist/e2e/newpr/scenarios.e2e.test.js.map +0 -1
- package/dist/e2e/newpr-full-flow.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr-full-flow.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr-full-flow.e2e.test.js +0 -280
- package/dist/e2e/newpr-full-flow.e2e.test.js.map +0 -1
- package/dist/e2e/prs/prs.e2e.test.d.ts +0 -7
- package/dist/e2e/prs/prs.e2e.test.d.ts.map +0 -1
- package/dist/e2e/prs/prs.e2e.test.js +0 -606
- package/dist/e2e/prs/prs.e2e.test.js.map +0 -1
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts +0 -2
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts.map +0 -1
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.js +0 -298
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.js.map +0 -1
- package/dist/e2e/wt/interactive-menu.e2e.test.d.ts +0 -8
- package/dist/e2e/wt/interactive-menu.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wt/interactive-menu.e2e.test.js +0 -583
- package/dist/e2e/wt/interactive-menu.e2e.test.js.map +0 -1
- package/dist/e2e/wt/wt.e2e.test.d.ts +0 -9
- package/dist/e2e/wt/wt.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wt/wt.e2e.test.js +0 -597
- package/dist/e2e/wt/wt.e2e.test.js.map +0 -1
- package/dist/e2e/wtlink/wtlink.e2e.test.d.ts +0 -2
- package/dist/e2e/wtlink/wtlink.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wtlink/wtlink.e2e.test.js +0 -416
- package/dist/e2e/wtlink/wtlink.e2e.test.js.map +0 -1
- package/dist/integration/git.integration.test.d.ts +0 -2
- package/dist/integration/git.integration.test.d.ts.map +0 -1
- package/dist/integration/git.integration.test.js +0 -336
- package/dist/integration/git.integration.test.js.map +0 -1
- package/dist/integration/lswt-remote-pr.integration.test.d.ts +0 -2
- package/dist/integration/lswt-remote-pr.integration.test.d.ts.map +0 -1
- package/dist/integration/lswt-remote-pr.integration.test.js +0 -222
- package/dist/integration/lswt-remote-pr.integration.test.js.map +0 -1
- package/dist/integration/newpr-branchfrom-head.integration.test.d.ts +0 -2
- package/dist/integration/newpr-branchfrom-head.integration.test.d.ts.map +0 -1
- package/dist/integration/newpr-branchfrom-head.integration.test.js +0 -498
- package/dist/integration/newpr-branchfrom-head.integration.test.js.map +0 -1
- package/dist/integration/newpr.integration.test.d.ts +0 -2
- package/dist/integration/newpr.integration.test.d.ts.map +0 -1
- package/dist/integration/newpr.integration.test.js +0 -460
- package/dist/integration/newpr.integration.test.js.map +0 -1
- package/dist/integration/prs.integration.test.d.ts +0 -8
- package/dist/integration/prs.integration.test.d.ts.map +0 -1
- package/dist/integration/prs.integration.test.js +0 -478
- package/dist/integration/prs.integration.test.js.map +0 -1
- package/dist/lib/ai/base-provider.test.d.ts +0 -7
- package/dist/lib/ai/base-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/base-provider.test.js +0 -319
- package/dist/lib/ai/base-provider.test.js.map +0 -1
- package/dist/lib/ai/cli-provider.test.d.ts +0 -5
- package/dist/lib/ai/cli-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/cli-provider.test.js +0 -460
- package/dist/lib/ai/cli-provider.test.js.map +0 -1
- package/dist/lib/ai/fallback-provider.test.d.ts +0 -7
- package/dist/lib/ai/fallback-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/fallback-provider.test.js +0 -165
- package/dist/lib/ai/fallback-provider.test.js.map +0 -1
- package/dist/lib/ai/generation-service.test.d.ts +0 -7
- package/dist/lib/ai/generation-service.test.d.ts.map +0 -1
- package/dist/lib/ai/generation-service.test.js +0 -213
- package/dist/lib/ai/generation-service.test.js.map +0 -1
- package/dist/lib/ai/provider-manager.test.d.ts +0 -5
- package/dist/lib/ai/provider-manager.test.d.ts.map +0 -1
- package/dist/lib/ai/provider-manager.test.js +0 -312
- package/dist/lib/ai/provider-manager.test.js.map +0 -1
- package/dist/lib/ai/repo-docs.test.d.ts +0 -5
- package/dist/lib/ai/repo-docs.test.d.ts.map +0 -1
- package/dist/lib/ai/repo-docs.test.js +0 -357
- package/dist/lib/ai/repo-docs.test.js.map +0 -1
- package/dist/lib/cleanpr/args.test.d.ts +0 -2
- package/dist/lib/cleanpr/args.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/args.test.js +0 -269
- package/dist/lib/cleanpr/args.test.js.map +0 -1
- package/dist/lib/cleanpr/cleanup.test.d.ts +0 -2
- package/dist/lib/cleanpr/cleanup.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/cleanup.test.js +0 -296
- package/dist/lib/cleanpr/cleanup.test.js.map +0 -1
- package/dist/lib/cleanpr/worktree-info.test.d.ts +0 -2
- package/dist/lib/cleanpr/worktree-info.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/worktree-info.test.js +0 -228
- package/dist/lib/cleanpr/worktree-info.test.js.map +0 -1
- package/dist/lib/colors.test.d.ts +0 -2
- package/dist/lib/colors.test.d.ts.map +0 -1
- package/dist/lib/colors.test.js +0 -142
- package/dist/lib/colors.test.js.map +0 -1
- package/dist/lib/config-editor.test.d.ts +0 -11
- package/dist/lib/config-editor.test.d.ts.map +0 -1
- package/dist/lib/config-editor.test.js +0 -526
- package/dist/lib/config-editor.test.js.map +0 -1
- package/dist/lib/config-migration/detector.test.d.ts +0 -5
- package/dist/lib/config-migration/detector.test.d.ts.map +0 -1
- package/dist/lib/config-migration/detector.test.js +0 -201
- package/dist/lib/config-migration/detector.test.js.map +0 -1
- package/dist/lib/config-migration/reporter.test.d.ts +0 -5
- package/dist/lib/config-migration/reporter.test.d.ts.map +0 -1
- package/dist/lib/config-migration/reporter.test.js +0 -305
- package/dist/lib/config-migration/reporter.test.js.map +0 -1
- package/dist/lib/config-migration/runner.test.d.ts +0 -5
- package/dist/lib/config-migration/runner.test.d.ts.map +0 -1
- package/dist/lib/config-migration/runner.test.js +0 -235
- package/dist/lib/config-migration/runner.test.js.map +0 -1
- package/dist/lib/config-validation.test.d.ts +0 -5
- package/dist/lib/config-validation.test.d.ts.map +0 -1
- package/dist/lib/config-validation.test.js +0 -423
- package/dist/lib/config-validation.test.js.map +0 -1
- package/dist/lib/config.test.d.ts +0 -2
- package/dist/lib/config.test.d.ts.map +0 -1
- package/dist/lib/config.test.js +0 -554
- package/dist/lib/config.test.js.map +0 -1
- package/dist/lib/constants.test.d.ts +0 -5
- package/dist/lib/constants.test.d.ts.map +0 -1
- package/dist/lib/constants.test.js +0 -180
- package/dist/lib/constants.test.js.map +0 -1
- package/dist/lib/deprecation.test.d.ts +0 -2
- package/dist/lib/deprecation.test.d.ts.map +0 -1
- package/dist/lib/deprecation.test.js +0 -71
- package/dist/lib/deprecation.test.js.map +0 -1
- package/dist/lib/errors.test.d.ts +0 -2
- package/dist/lib/errors.test.d.ts.map +0 -1
- package/dist/lib/errors.test.js +0 -117
- package/dist/lib/errors.test.js.map +0 -1
- package/dist/lib/git.test.d.ts +0 -2
- package/dist/lib/git.test.d.ts.map +0 -1
- package/dist/lib/git.test.js +0 -608
- package/dist/lib/git.test.js.map +0 -1
- package/dist/lib/github.test.d.ts +0 -2
- package/dist/lib/github.test.d.ts.map +0 -1
- package/dist/lib/github.test.js +0 -441
- package/dist/lib/github.test.js.map +0 -1
- package/dist/lib/global-check.test.d.ts +0 -5
- package/dist/lib/global-check.test.d.ts.map +0 -1
- package/dist/lib/global-check.test.js +0 -150
- package/dist/lib/global-check.test.js.map +0 -1
- package/dist/lib/global-config.test.d.ts +0 -5
- package/dist/lib/global-config.test.d.ts.map +0 -1
- package/dist/lib/global-config.test.js +0 -282
- package/dist/lib/global-config.test.js.map +0 -1
- package/dist/lib/hooks/confirmation.test.d.ts +0 -7
- package/dist/lib/hooks/confirmation.test.d.ts.map +0 -1
- package/dist/lib/hooks/confirmation.test.js +0 -300
- package/dist/lib/hooks/confirmation.test.js.map +0 -1
- package/dist/lib/hooks/executor.test.d.ts +0 -5
- package/dist/lib/hooks/executor.test.d.ts.map +0 -1
- package/dist/lib/hooks/executor.test.js +0 -648
- package/dist/lib/hooks/executor.test.js.map +0 -1
- package/dist/lib/hooks/templates.test.d.ts +0 -5
- package/dist/lib/hooks/templates.test.d.ts.map +0 -1
- package/dist/lib/hooks/templates.test.js +0 -163
- package/dist/lib/hooks/templates.test.js.map +0 -1
- package/dist/lib/hooks/types.test.d.ts +0 -5
- package/dist/lib/hooks/types.test.d.ts.map +0 -1
- package/dist/lib/hooks/types.test.js +0 -132
- package/dist/lib/hooks/types.test.js.map +0 -1
- package/dist/lib/json-output.test.d.ts +0 -5
- package/dist/lib/json-output.test.d.ts.map +0 -1
- package/dist/lib/json-output.test.js +0 -261
- package/dist/lib/json-output.test.js.map +0 -1
- package/dist/lib/logger.test.d.ts +0 -14
- package/dist/lib/logger.test.d.ts.map +0 -1
- package/dist/lib/logger.test.js +0 -692
- package/dist/lib/logger.test.js.map +0 -1
- package/dist/lib/lswt/action-executors.test.d.ts +0 -2
- package/dist/lib/lswt/action-executors.test.d.ts.map +0 -1
- package/dist/lib/lswt/action-executors.test.js +0 -1127
- package/dist/lib/lswt/action-executors.test.js.map +0 -1
- package/dist/lib/lswt/actions.test.d.ts +0 -2
- package/dist/lib/lswt/actions.test.d.ts.map +0 -1
- package/dist/lib/lswt/actions.test.js +0 -497
- package/dist/lib/lswt/actions.test.js.map +0 -1
- package/dist/lib/lswt/args.test.d.ts +0 -2
- package/dist/lib/lswt/args.test.d.ts.map +0 -1
- package/dist/lib/lswt/args.test.js +0 -195
- package/dist/lib/lswt/args.test.js.map +0 -1
- package/dist/lib/lswt/environment.test.d.ts +0 -2
- package/dist/lib/lswt/environment.test.d.ts.map +0 -1
- package/dist/lib/lswt/environment.test.js +0 -544
- package/dist/lib/lswt/environment.test.js.map +0 -1
- package/dist/lib/lswt/formatters.test.d.ts +0 -2
- package/dist/lib/lswt/formatters.test.d.ts.map +0 -1
- package/dist/lib/lswt/formatters.test.js +0 -323
- package/dist/lib/lswt/formatters.test.js.map +0 -1
- package/dist/lib/lswt/fuzzy-search.test.d.ts +0 -5
- package/dist/lib/lswt/fuzzy-search.test.d.ts.map +0 -1
- package/dist/lib/lswt/fuzzy-search.test.js +0 -207
- package/dist/lib/lswt/fuzzy-search.test.js.map +0 -1
- package/dist/lib/lswt/interactive.test.d.ts +0 -2
- package/dist/lib/lswt/interactive.test.d.ts.map +0 -1
- package/dist/lib/lswt/interactive.test.js +0 -771
- package/dist/lib/lswt/interactive.test.js.map +0 -1
- package/dist/lib/lswt/table.test.d.ts +0 -5
- package/dist/lib/lswt/table.test.d.ts.map +0 -1
- package/dist/lib/lswt/table.test.js +0 -262
- package/dist/lib/lswt/table.test.js.map +0 -1
- package/dist/lib/lswt/worktree-info.test.d.ts +0 -2
- package/dist/lib/lswt/worktree-info.test.d.ts.map +0 -1
- package/dist/lib/lswt/worktree-info.test.js +0 -484
- package/dist/lib/lswt/worktree-info.test.js.map +0 -1
- package/dist/lib/newpr/action-deps.test.d.ts +0 -5
- package/dist/lib/newpr/action-deps.test.d.ts.map +0 -1
- package/dist/lib/newpr/action-deps.test.js +0 -111
- package/dist/lib/newpr/action-deps.test.js.map +0 -1
- package/dist/lib/newpr/actions.test.d.ts +0 -2
- package/dist/lib/newpr/actions.test.d.ts.map +0 -1
- package/dist/lib/newpr/actions.test.js +0 -254
- package/dist/lib/newpr/actions.test.js.map +0 -1
- package/dist/lib/newpr/args.test.d.ts +0 -2
- package/dist/lib/newpr/args.test.d.ts.map +0 -1
- package/dist/lib/newpr/args.test.js +0 -479
- package/dist/lib/newpr/args.test.js.map +0 -1
- package/dist/lib/newpr/hook-runner.test.d.ts +0 -7
- package/dist/lib/newpr/hook-runner.test.d.ts.map +0 -1
- package/dist/lib/newpr/hook-runner.test.js +0 -422
- package/dist/lib/newpr/hook-runner.test.js.map +0 -1
- package/dist/lib/newpr/plan-generator.test.d.ts +0 -7
- package/dist/lib/newpr/plan-generator.test.d.ts.map +0 -1
- package/dist/lib/newpr/plan-generator.test.js +0 -387
- package/dist/lib/newpr/plan-generator.test.js.map +0 -1
- package/dist/lib/newpr/scenario-handler.test.d.ts +0 -2
- package/dist/lib/newpr/scenario-handler.test.d.ts.map +0 -1
- package/dist/lib/newpr/scenario-handler.test.js +0 -256
- package/dist/lib/newpr/scenario-handler.test.js.map +0 -1
- package/dist/lib/prompts.test.d.ts +0 -2
- package/dist/lib/prompts.test.d.ts.map +0 -1
- package/dist/lib/prompts.test.js +0 -807
- package/dist/lib/prompts.test.js.map +0 -1
- package/dist/lib/prs/actions.test.d.ts +0 -5
- package/dist/lib/prs/actions.test.d.ts.map +0 -1
- package/dist/lib/prs/actions.test.js +0 -356
- package/dist/lib/prs/actions.test.js.map +0 -1
- package/dist/lib/prs/command.test.d.ts +0 -11
- package/dist/lib/prs/command.test.d.ts.map +0 -1
- package/dist/lib/prs/command.test.js +0 -409
- package/dist/lib/prs/command.test.js.map +0 -1
- package/dist/lib/prs/data.test.d.ts +0 -5
- package/dist/lib/prs/data.test.d.ts.map +0 -1
- package/dist/lib/prs/data.test.js +0 -417
- package/dist/lib/prs/data.test.js.map +0 -1
- package/dist/lib/prs/details.test.d.ts +0 -5
- package/dist/lib/prs/details.test.d.ts.map +0 -1
- package/dist/lib/prs/details.test.js +0 -325
- package/dist/lib/prs/details.test.js.map +0 -1
- package/dist/lib/prs/filters.test.d.ts +0 -5
- package/dist/lib/prs/filters.test.d.ts.map +0 -1
- package/dist/lib/prs/filters.test.js +0 -312
- package/dist/lib/prs/filters.test.js.map +0 -1
- package/dist/lib/prs/formatters.test.d.ts +0 -2
- package/dist/lib/prs/formatters.test.d.ts.map +0 -1
- package/dist/lib/prs/formatters.test.js +0 -387
- package/dist/lib/prs/formatters.test.js.map +0 -1
- package/dist/lib/prs/interactive.test.d.ts +0 -5
- package/dist/lib/prs/interactive.test.d.ts.map +0 -1
- package/dist/lib/prs/interactive.test.js +0 -517
- package/dist/lib/prs/interactive.test.js.map +0 -1
- package/dist/lib/schema.test.d.ts +0 -10
- package/dist/lib/schema.test.d.ts.map +0 -1
- package/dist/lib/schema.test.js +0 -309
- package/dist/lib/schema.test.js.map +0 -1
- package/dist/lib/state-detection.test.d.ts +0 -2
- package/dist/lib/state-detection.test.d.ts.map +0 -1
- package/dist/lib/state-detection.test.js +0 -451
- package/dist/lib/state-detection.test.js.map +0 -1
- package/dist/lib/ui/error.test.d.ts +0 -2
- package/dist/lib/ui/error.test.d.ts.map +0 -1
- package/dist/lib/ui/error.test.js +0 -143
- package/dist/lib/ui/error.test.js.map +0 -1
- package/dist/lib/ui/output.test.d.ts +0 -2
- package/dist/lib/ui/output.test.d.ts.map +0 -1
- package/dist/lib/ui/output.test.js +0 -59
- package/dist/lib/ui/output.test.js.map +0 -1
- package/dist/lib/ui/status.test.d.ts +0 -2
- package/dist/lib/ui/status.test.d.ts.map +0 -1
- package/dist/lib/ui/status.test.js +0 -158
- package/dist/lib/ui/status.test.js.map +0 -1
- package/dist/lib/ui/table.test.d.ts +0 -2
- package/dist/lib/ui/table.test.d.ts.map +0 -1
- package/dist/lib/ui/table.test.js +0 -115
- package/dist/lib/ui/table.test.js.map +0 -1
- package/dist/lib/ui/theme.test.d.ts +0 -2
- package/dist/lib/ui/theme.test.d.ts.map +0 -1
- package/dist/lib/ui/theme.test.js +0 -76
- package/dist/lib/ui/theme.test.js.map +0 -1
- package/dist/lib/wtconfig/config-manager.test.d.ts +0 -5
- package/dist/lib/wtconfig/config-manager.test.d.ts.map +0 -1
- package/dist/lib/wtconfig/config-manager.test.js +0 -501
- package/dist/lib/wtconfig/config-manager.test.js.map +0 -1
- package/dist/lib/wtconfig/environment.test.d.ts +0 -5
- package/dist/lib/wtconfig/environment.test.d.ts.map +0 -1
- package/dist/lib/wtconfig/environment.test.js +0 -285
- package/dist/lib/wtconfig/environment.test.js.map +0 -1
- package/dist/lib/wtlink/config-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/config-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/config-manifest.test.js +0 -486
- package/dist/lib/wtlink/config-manifest.test.js.map +0 -1
- package/dist/lib/wtlink/link-configs.test.d.ts +0 -2
- package/dist/lib/wtlink/link-configs.test.d.ts.map +0 -1
- package/dist/lib/wtlink/link-configs.test.js +0 -612
- package/dist/lib/wtlink/link-configs.test.js.map +0 -1
- package/dist/lib/wtlink/main-menu.test.d.ts +0 -5
- package/dist/lib/wtlink/main-menu.test.d.ts.map +0 -1
- package/dist/lib/wtlink/main-menu.test.js +0 -126
- package/dist/lib/wtlink/main-menu.test.js.map +0 -1
- package/dist/lib/wtlink/manage-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/manage-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/manage-manifest.test.js +0 -714
- package/dist/lib/wtlink/manage-manifest.test.js.map +0 -1
- package/dist/lib/wtlink/validate-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/validate-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/validate-manifest.test.js +0 -220
- package/dist/lib/wtlink/validate-manifest.test.js.map +0 -1
- package/dist/lib/wtstate/analyze.test.d.ts +0 -5
- package/dist/lib/wtstate/analyze.test.d.ts.map +0 -1
- package/dist/lib/wtstate/analyze.test.js +0 -282
- package/dist/lib/wtstate/analyze.test.js.map +0 -1
- package/dist/lib/wtstate/args.test.d.ts +0 -5
- package/dist/lib/wtstate/args.test.d.ts.map +0 -1
- package/dist/lib/wtstate/args.test.js +0 -120
- package/dist/lib/wtstate/args.test.js.map +0 -1
- package/dist/mcp/server.test.d.ts +0 -9
- package/dist/mcp/server.test.d.ts.map +0 -1
- package/dist/mcp/server.test.js +0 -550
- package/dist/mcp/server.test.js.map +0 -1
package/dist/lib/prompts.test.js
DELETED
|
@@ -1,807 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import readline from 'readline';
|
|
3
|
-
import { promptChoiceIndex, promptChoice, promptConfirm, promptInput, printHeader, printListItem, withSpinner, UserNavigatedBack, } from './prompts.js';
|
|
4
|
-
// Mock readline
|
|
5
|
-
vi.mock('readline', () => ({
|
|
6
|
-
default: {
|
|
7
|
-
createInterface: vi.fn(),
|
|
8
|
-
emitKeypressEvents: vi.fn(),
|
|
9
|
-
},
|
|
10
|
-
}));
|
|
11
|
-
// Mock console.log
|
|
12
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
13
|
-
const stdoutWriteSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
14
|
-
describe('prompts', () => {
|
|
15
|
-
let mockRl;
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
vi.clearAllMocks();
|
|
18
|
-
mockRl = {
|
|
19
|
-
question: vi.fn(),
|
|
20
|
-
close: vi.fn(),
|
|
21
|
-
on: vi.fn(),
|
|
22
|
-
};
|
|
23
|
-
vi.mocked(readline.createInterface).mockReturnValue(mockRl);
|
|
24
|
-
});
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
consoleSpy.mockClear();
|
|
27
|
-
stdoutWriteSpy.mockClear();
|
|
28
|
-
});
|
|
29
|
-
describe('promptChoiceIndex', () => {
|
|
30
|
-
it('displays prompt and options', async () => {
|
|
31
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
32
|
-
callback('1');
|
|
33
|
-
});
|
|
34
|
-
await promptChoiceIndex('Choose an option:', ['Option A', 'Option B', 'Option C']);
|
|
35
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Choose an option:'));
|
|
36
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Option A'));
|
|
37
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Option B'));
|
|
38
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Option C'));
|
|
39
|
-
});
|
|
40
|
-
it('returns 1-based index of selected option', async () => {
|
|
41
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
42
|
-
callback('2');
|
|
43
|
-
});
|
|
44
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
45
|
-
expect(result).toBe(2);
|
|
46
|
-
expect(mockRl.close).toHaveBeenCalled();
|
|
47
|
-
});
|
|
48
|
-
it('re-prompts on invalid input', async () => {
|
|
49
|
-
let callCount = 0;
|
|
50
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
51
|
-
callCount++;
|
|
52
|
-
if (callCount === 1) {
|
|
53
|
-
callback('invalid');
|
|
54
|
-
}
|
|
55
|
-
else if (callCount === 2) {
|
|
56
|
-
callback('5'); // out of range
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
callback('1'); // valid
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B']);
|
|
63
|
-
expect(result).toBe(1);
|
|
64
|
-
expect(mockRl.question).toHaveBeenCalledTimes(3);
|
|
65
|
-
});
|
|
66
|
-
it('re-prompts on empty input', async () => {
|
|
67
|
-
let callCount = 0;
|
|
68
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
69
|
-
callCount++;
|
|
70
|
-
if (callCount === 1) {
|
|
71
|
-
callback('');
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
callback('1');
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
const result = await promptChoiceIndex('Choose:', ['A']);
|
|
78
|
-
expect(result).toBe(1);
|
|
79
|
-
expect(mockRl.question).toHaveBeenCalledTimes(2);
|
|
80
|
-
});
|
|
81
|
-
it('rejects on quit command', async () => {
|
|
82
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
83
|
-
callback('q');
|
|
84
|
-
});
|
|
85
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toThrow('User cancelled');
|
|
86
|
-
});
|
|
87
|
-
it('rejects on quit word', async () => {
|
|
88
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
89
|
-
callback('quit');
|
|
90
|
-
});
|
|
91
|
-
await expect(promptChoiceIndex('Choose:', ['A'])).rejects.toThrow('User cancelled');
|
|
92
|
-
});
|
|
93
|
-
it('rejects on SIGINT', async () => {
|
|
94
|
-
let sigintHandler = null;
|
|
95
|
-
mockRl.on.mockImplementation((event, handler) => {
|
|
96
|
-
if (event === 'SIGINT') {
|
|
97
|
-
sigintHandler = handler;
|
|
98
|
-
}
|
|
99
|
-
return mockRl;
|
|
100
|
-
});
|
|
101
|
-
mockRl.question.mockImplementation(() => {
|
|
102
|
-
setImmediate(() => {
|
|
103
|
-
if (sigintHandler) {
|
|
104
|
-
sigintHandler();
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toThrow('User cancelled');
|
|
109
|
-
expect(mockRl.close).toHaveBeenCalled();
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
describe('promptChoice', () => {
|
|
113
|
-
it('returns value of selected option', async () => {
|
|
114
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
115
|
-
callback('2');
|
|
116
|
-
});
|
|
117
|
-
const result = await promptChoice('Choose:', [
|
|
118
|
-
{ label: 'First', value: 'first-value' },
|
|
119
|
-
{ label: 'Second', value: 'second-value' },
|
|
120
|
-
{ label: 'Third', value: 'third-value' },
|
|
121
|
-
]);
|
|
122
|
-
expect(result).toBe('second-value');
|
|
123
|
-
});
|
|
124
|
-
it('displays descriptions when provided', async () => {
|
|
125
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
126
|
-
callback('1');
|
|
127
|
-
});
|
|
128
|
-
await promptChoice('Choose:', [
|
|
129
|
-
{ label: 'Option', description: 'A helpful description', value: 'opt' },
|
|
130
|
-
]);
|
|
131
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('A helpful description'));
|
|
132
|
-
});
|
|
133
|
-
it('works with typed values', async () => {
|
|
134
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
135
|
-
callback('1');
|
|
136
|
-
});
|
|
137
|
-
const result = await promptChoice('Choose:', [
|
|
138
|
-
{ label: 'Item 1', value: { id: 1, name: 'One' } },
|
|
139
|
-
{ label: 'Item 2', value: { id: 2, name: 'Two' } },
|
|
140
|
-
]);
|
|
141
|
-
expect(result).toEqual({ id: 1, name: 'One' });
|
|
142
|
-
});
|
|
143
|
-
it('re-prompts on invalid choice', async () => {
|
|
144
|
-
let callCount = 0;
|
|
145
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
146
|
-
callCount++;
|
|
147
|
-
if (callCount === 1) {
|
|
148
|
-
callback('99'); // invalid choice
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
callback('1'); // valid choice
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
const result = await promptChoice('Choose:', [
|
|
155
|
-
{ label: 'Option A', value: 'a' },
|
|
156
|
-
{ label: 'Option B', value: 'b' },
|
|
157
|
-
]);
|
|
158
|
-
expect(result).toBe('a');
|
|
159
|
-
expect(mockRl.question).toHaveBeenCalledTimes(2);
|
|
160
|
-
});
|
|
161
|
-
it('re-prompts on empty input', async () => {
|
|
162
|
-
let callCount = 0;
|
|
163
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
164
|
-
callCount++;
|
|
165
|
-
if (callCount === 1) {
|
|
166
|
-
callback(''); // empty input
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
callback('1'); // valid choice
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
const result = await promptChoice('Choose:', [{ label: 'Option A', value: 'a' }]);
|
|
173
|
-
expect(result).toBe('a');
|
|
174
|
-
expect(mockRl.question).toHaveBeenCalledTimes(2);
|
|
175
|
-
});
|
|
176
|
-
it('rejects on quit command', async () => {
|
|
177
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
178
|
-
callback('q');
|
|
179
|
-
});
|
|
180
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toThrow('User cancelled');
|
|
181
|
-
});
|
|
182
|
-
it('rejects on quit word', async () => {
|
|
183
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
184
|
-
callback('quit');
|
|
185
|
-
});
|
|
186
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toThrow('User cancelled');
|
|
187
|
-
});
|
|
188
|
-
it('rejects on SIGINT', async () => {
|
|
189
|
-
let sigintHandler = null;
|
|
190
|
-
mockRl.on.mockImplementation((event, handler) => {
|
|
191
|
-
if (event === 'SIGINT') {
|
|
192
|
-
sigintHandler = handler;
|
|
193
|
-
}
|
|
194
|
-
return mockRl;
|
|
195
|
-
});
|
|
196
|
-
mockRl.question.mockImplementation(() => {
|
|
197
|
-
setImmediate(() => {
|
|
198
|
-
if (sigintHandler) {
|
|
199
|
-
sigintHandler();
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toThrow('User cancelled');
|
|
204
|
-
expect(mockRl.close).toHaveBeenCalled();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
describe('promptConfirm', () => {
|
|
208
|
-
it('returns true for y input', async () => {
|
|
209
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
210
|
-
callback('y');
|
|
211
|
-
});
|
|
212
|
-
const result = await promptConfirm('Continue?');
|
|
213
|
-
expect(result).toBe(true);
|
|
214
|
-
});
|
|
215
|
-
it('returns true for yes input', async () => {
|
|
216
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
217
|
-
callback('yes');
|
|
218
|
-
});
|
|
219
|
-
const result = await promptConfirm('Continue?');
|
|
220
|
-
expect(result).toBe(true);
|
|
221
|
-
});
|
|
222
|
-
it('returns true for Y input (case insensitive)', async () => {
|
|
223
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
224
|
-
callback('Y');
|
|
225
|
-
});
|
|
226
|
-
const result = await promptConfirm('Continue?');
|
|
227
|
-
expect(result).toBe(true);
|
|
228
|
-
});
|
|
229
|
-
it('returns false for n input', async () => {
|
|
230
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
231
|
-
callback('n');
|
|
232
|
-
});
|
|
233
|
-
const result = await promptConfirm('Continue?');
|
|
234
|
-
expect(result).toBe(false);
|
|
235
|
-
});
|
|
236
|
-
it('returns false for no input', async () => {
|
|
237
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
238
|
-
callback('no');
|
|
239
|
-
});
|
|
240
|
-
const result = await promptConfirm('Continue?');
|
|
241
|
-
expect(result).toBe(false);
|
|
242
|
-
});
|
|
243
|
-
it('returns default false for empty input', async () => {
|
|
244
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
245
|
-
callback('');
|
|
246
|
-
});
|
|
247
|
-
const result = await promptConfirm('Continue?');
|
|
248
|
-
expect(result).toBe(false);
|
|
249
|
-
});
|
|
250
|
-
it('returns default true when specified', async () => {
|
|
251
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
252
|
-
callback('');
|
|
253
|
-
});
|
|
254
|
-
const result = await promptConfirm('Continue?', true);
|
|
255
|
-
expect(result).toBe(true);
|
|
256
|
-
});
|
|
257
|
-
it('returns default for invalid input', async () => {
|
|
258
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
259
|
-
callback('maybe');
|
|
260
|
-
});
|
|
261
|
-
const result = await promptConfirm('Continue?', true);
|
|
262
|
-
expect(result).toBe(true);
|
|
263
|
-
});
|
|
264
|
-
it('displays correct hint for default false', async () => {
|
|
265
|
-
mockRl.question.mockImplementation((question, callback) => {
|
|
266
|
-
expect(question).toContain('[y/N]');
|
|
267
|
-
callback('');
|
|
268
|
-
});
|
|
269
|
-
await promptConfirm('Continue?', false);
|
|
270
|
-
});
|
|
271
|
-
it('displays correct hint for default true', async () => {
|
|
272
|
-
mockRl.question.mockImplementation((question, callback) => {
|
|
273
|
-
expect(question).toContain('[Y/n]');
|
|
274
|
-
callback('');
|
|
275
|
-
});
|
|
276
|
-
await promptConfirm('Continue?', true);
|
|
277
|
-
});
|
|
278
|
-
it('rejects on SIGINT', async () => {
|
|
279
|
-
let sigintHandler = null;
|
|
280
|
-
mockRl.on.mockImplementation((event, handler) => {
|
|
281
|
-
if (event === 'SIGINT') {
|
|
282
|
-
sigintHandler = handler;
|
|
283
|
-
}
|
|
284
|
-
return mockRl;
|
|
285
|
-
});
|
|
286
|
-
mockRl.question.mockImplementation(() => {
|
|
287
|
-
// Trigger SIGINT asynchronously to allow Promise to be set up
|
|
288
|
-
setImmediate(() => {
|
|
289
|
-
if (sigintHandler) {
|
|
290
|
-
sigintHandler();
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
await expect(promptConfirm('Continue?')).rejects.toThrow('User cancelled');
|
|
295
|
-
expect(mockRl.close).toHaveBeenCalled();
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
describe('promptInput', () => {
|
|
299
|
-
it('returns user input', async () => {
|
|
300
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
301
|
-
callback('user input');
|
|
302
|
-
});
|
|
303
|
-
const result = await promptInput('Enter value:');
|
|
304
|
-
expect(result).toBe('user input');
|
|
305
|
-
});
|
|
306
|
-
it('trims whitespace', async () => {
|
|
307
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
308
|
-
callback(' trimmed ');
|
|
309
|
-
});
|
|
310
|
-
const result = await promptInput('Enter value:');
|
|
311
|
-
expect(result).toBe('trimmed');
|
|
312
|
-
});
|
|
313
|
-
it('returns default for empty input', async () => {
|
|
314
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
315
|
-
callback('');
|
|
316
|
-
});
|
|
317
|
-
const result = await promptInput('Enter value:', 'default');
|
|
318
|
-
expect(result).toBe('default');
|
|
319
|
-
});
|
|
320
|
-
it('returns empty string if no default and empty input', async () => {
|
|
321
|
-
mockRl.question.mockImplementation((_, callback) => {
|
|
322
|
-
callback('');
|
|
323
|
-
});
|
|
324
|
-
const result = await promptInput('Enter value:');
|
|
325
|
-
expect(result).toBe('');
|
|
326
|
-
});
|
|
327
|
-
it('displays default value hint', async () => {
|
|
328
|
-
mockRl.question.mockImplementation((question, callback) => {
|
|
329
|
-
expect(question).toContain('[default-value]');
|
|
330
|
-
callback('');
|
|
331
|
-
});
|
|
332
|
-
await promptInput('Enter:', 'default-value');
|
|
333
|
-
});
|
|
334
|
-
it('rejects on SIGINT', async () => {
|
|
335
|
-
let sigintHandler = null;
|
|
336
|
-
mockRl.on.mockImplementation((event, handler) => {
|
|
337
|
-
if (event === 'SIGINT') {
|
|
338
|
-
sigintHandler = handler;
|
|
339
|
-
}
|
|
340
|
-
return mockRl;
|
|
341
|
-
});
|
|
342
|
-
mockRl.question.mockImplementation(() => {
|
|
343
|
-
// Trigger SIGINT asynchronously to allow Promise to be set up
|
|
344
|
-
setImmediate(() => {
|
|
345
|
-
if (sigintHandler) {
|
|
346
|
-
sigintHandler();
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
await expect(promptInput('Enter value:')).rejects.toThrow('User cancelled');
|
|
351
|
-
expect(mockRl.close).toHaveBeenCalled();
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
describe('printHeader', () => {
|
|
355
|
-
it('prints formatted header', () => {
|
|
356
|
-
printHeader('Test Header');
|
|
357
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Test Header'));
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
describe('printListItem', () => {
|
|
361
|
-
it('prints bullet point item', () => {
|
|
362
|
-
printListItem('List item');
|
|
363
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('•'));
|
|
364
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('List item'));
|
|
365
|
-
});
|
|
366
|
-
it('prints indented item', () => {
|
|
367
|
-
printListItem('Indented item', 2);
|
|
368
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching(/^\s{4}•/));
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
describe('withSpinner', () => {
|
|
372
|
-
let originalIsTTY;
|
|
373
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
374
|
-
let stdoutWriteSpy;
|
|
375
|
-
beforeEach(() => {
|
|
376
|
-
originalIsTTY = process.stdout.isTTY;
|
|
377
|
-
stdoutWriteSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
378
|
-
vi.useFakeTimers();
|
|
379
|
-
});
|
|
380
|
-
afterEach(() => {
|
|
381
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
382
|
-
value: originalIsTTY,
|
|
383
|
-
writable: true,
|
|
384
|
-
configurable: true,
|
|
385
|
-
});
|
|
386
|
-
stdoutWriteSpy.mockRestore();
|
|
387
|
-
vi.useRealTimers();
|
|
388
|
-
});
|
|
389
|
-
it('returns the result of the operation', async () => {
|
|
390
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
391
|
-
value: false,
|
|
392
|
-
writable: true,
|
|
393
|
-
configurable: true,
|
|
394
|
-
});
|
|
395
|
-
const result = await withSpinner('Loading...', async () => 'test-result');
|
|
396
|
-
expect(result).toBe('test-result');
|
|
397
|
-
});
|
|
398
|
-
it('logs message when not a TTY', async () => {
|
|
399
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
400
|
-
value: false,
|
|
401
|
-
writable: true,
|
|
402
|
-
configurable: true,
|
|
403
|
-
});
|
|
404
|
-
await withSpinner('Loading data', async () => 'done');
|
|
405
|
-
expect(consoleSpy).toHaveBeenCalledWith('Loading data');
|
|
406
|
-
});
|
|
407
|
-
it('shows spinner animation when TTY', async () => {
|
|
408
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
409
|
-
value: true,
|
|
410
|
-
writable: true,
|
|
411
|
-
configurable: true,
|
|
412
|
-
});
|
|
413
|
-
const promise = withSpinner('Processing', async () => {
|
|
414
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
415
|
-
return 'done';
|
|
416
|
-
});
|
|
417
|
-
// Advance timers to trigger spinner frames
|
|
418
|
-
await vi.advanceTimersByTimeAsync(80);
|
|
419
|
-
expect(stdoutWriteSpy).toHaveBeenCalled();
|
|
420
|
-
// Complete the operation
|
|
421
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
422
|
-
await promise;
|
|
423
|
-
});
|
|
424
|
-
it('clears spinner on success when TTY', async () => {
|
|
425
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
426
|
-
value: true,
|
|
427
|
-
writable: true,
|
|
428
|
-
configurable: true,
|
|
429
|
-
});
|
|
430
|
-
const promise = withSpinner('Test', async () => 'result');
|
|
431
|
-
await promise;
|
|
432
|
-
// Should have written to clear the line
|
|
433
|
-
expect(stdoutWriteSpy).toHaveBeenCalledWith(expect.stringContaining('\r'));
|
|
434
|
-
});
|
|
435
|
-
it('throws error from operation', async () => {
|
|
436
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
437
|
-
value: false,
|
|
438
|
-
writable: true,
|
|
439
|
-
configurable: true,
|
|
440
|
-
});
|
|
441
|
-
await expect(withSpinner('Failing', async () => {
|
|
442
|
-
throw new Error('Operation failed');
|
|
443
|
-
})).rejects.toThrow('Operation failed');
|
|
444
|
-
});
|
|
445
|
-
it('clears spinner on error when TTY', async () => {
|
|
446
|
-
Object.defineProperty(process.stdout, 'isTTY', {
|
|
447
|
-
value: true,
|
|
448
|
-
writable: true,
|
|
449
|
-
configurable: true,
|
|
450
|
-
});
|
|
451
|
-
const promise = withSpinner('Error test', async () => {
|
|
452
|
-
throw new Error('Test error');
|
|
453
|
-
});
|
|
454
|
-
await expect(promise).rejects.toThrow('Test error');
|
|
455
|
-
// Should have written to clear the line
|
|
456
|
-
expect(stdoutWriteSpy).toHaveBeenCalledWith(expect.stringContaining('\r'));
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
describe('arrow-key navigation (TTY mode)', () => {
|
|
460
|
-
let originalIsTTY;
|
|
461
|
-
let mockStdinOn;
|
|
462
|
-
let mockStdinRemoveListener;
|
|
463
|
-
let mockStdinSetRawMode;
|
|
464
|
-
let mockStdinResume;
|
|
465
|
-
let mockStdinPause;
|
|
466
|
-
beforeEach(() => {
|
|
467
|
-
originalIsTTY = process.stdin.isTTY;
|
|
468
|
-
// Set up TTY mode
|
|
469
|
-
Object.defineProperty(process.stdin, 'isTTY', {
|
|
470
|
-
value: true,
|
|
471
|
-
writable: true,
|
|
472
|
-
configurable: true,
|
|
473
|
-
});
|
|
474
|
-
// Mock stdin methods
|
|
475
|
-
mockStdinOn = vi.fn();
|
|
476
|
-
mockStdinRemoveListener = vi.fn();
|
|
477
|
-
mockStdinSetRawMode = vi.fn();
|
|
478
|
-
mockStdinResume = vi.fn();
|
|
479
|
-
mockStdinPause = vi.fn();
|
|
480
|
-
// Apply mocks to process.stdin
|
|
481
|
-
vi.spyOn(process.stdin, 'on').mockImplementation(mockStdinOn);
|
|
482
|
-
vi.spyOn(process.stdin, 'removeListener').mockImplementation(mockStdinRemoveListener);
|
|
483
|
-
// Mock setRawMode, resume, pause
|
|
484
|
-
Object.defineProperty(process.stdin, 'setRawMode', {
|
|
485
|
-
value: mockStdinSetRawMode,
|
|
486
|
-
writable: true,
|
|
487
|
-
configurable: true,
|
|
488
|
-
});
|
|
489
|
-
vi.spyOn(process.stdin, 'resume').mockImplementation(mockStdinResume);
|
|
490
|
-
vi.spyOn(process.stdin, 'pause').mockImplementation(mockStdinPause);
|
|
491
|
-
});
|
|
492
|
-
afterEach(() => {
|
|
493
|
-
Object.defineProperty(process.stdin, 'isTTY', {
|
|
494
|
-
value: originalIsTTY,
|
|
495
|
-
writable: true,
|
|
496
|
-
configurable: true,
|
|
497
|
-
});
|
|
498
|
-
vi.restoreAllMocks();
|
|
499
|
-
});
|
|
500
|
-
describe('promptChoiceIndex with arrow keys', () => {
|
|
501
|
-
it('enters arrow-key mode when TTY is available', async () => {
|
|
502
|
-
// Simulate Enter key immediately after setup
|
|
503
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
504
|
-
if (event === 'keypress') {
|
|
505
|
-
// Simulate pressing Enter immediately
|
|
506
|
-
setImmediate(() => {
|
|
507
|
-
handler('', { name: 'return' });
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
return process.stdin;
|
|
511
|
-
});
|
|
512
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
513
|
-
expect(result).toBe(1); // First option selected (1-based)
|
|
514
|
-
expect(mockStdinSetRawMode).toHaveBeenCalledWith(true);
|
|
515
|
-
expect(mockStdinResume).toHaveBeenCalled();
|
|
516
|
-
});
|
|
517
|
-
it('navigates down with arrow key', async () => {
|
|
518
|
-
let keypressHandler = null;
|
|
519
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
520
|
-
if (event === 'keypress') {
|
|
521
|
-
keypressHandler = handler;
|
|
522
|
-
// Simulate pressing down then enter
|
|
523
|
-
setImmediate(() => {
|
|
524
|
-
handler('', { name: 'down' });
|
|
525
|
-
setImmediate(() => {
|
|
526
|
-
handler('', { name: 'return' });
|
|
527
|
-
});
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
return process.stdin;
|
|
531
|
-
});
|
|
532
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
533
|
-
expect(result).toBe(2); // Second option selected (1-based)
|
|
534
|
-
});
|
|
535
|
-
it('navigates up with arrow key', async () => {
|
|
536
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
537
|
-
if (event === 'keypress') {
|
|
538
|
-
// Simulate pressing up (wraps to end) then enter
|
|
539
|
-
setImmediate(() => {
|
|
540
|
-
handler('', { name: 'up' });
|
|
541
|
-
setImmediate(() => {
|
|
542
|
-
handler('', { name: 'return' });
|
|
543
|
-
});
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
return process.stdin;
|
|
547
|
-
});
|
|
548
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
549
|
-
expect(result).toBe(3); // Last option selected (wraps around, 1-based)
|
|
550
|
-
});
|
|
551
|
-
it('rejects on q key press', async () => {
|
|
552
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
553
|
-
if (event === 'keypress') {
|
|
554
|
-
setImmediate(() => {
|
|
555
|
-
handler('q', { name: 'q' });
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
return process.stdin;
|
|
559
|
-
});
|
|
560
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toThrow('User cancelled');
|
|
561
|
-
});
|
|
562
|
-
it('rejects on Q key press', async () => {
|
|
563
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
564
|
-
if (event === 'keypress') {
|
|
565
|
-
setImmediate(() => {
|
|
566
|
-
handler('Q', { name: 'Q' });
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
return process.stdin;
|
|
570
|
-
});
|
|
571
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toThrow('User cancelled');
|
|
572
|
-
});
|
|
573
|
-
it('rejects on Ctrl+C', async () => {
|
|
574
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
575
|
-
if (event === 'keypress') {
|
|
576
|
-
setImmediate(() => {
|
|
577
|
-
handler('', { name: 'c', ctrl: true });
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
return process.stdin;
|
|
581
|
-
});
|
|
582
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toThrow('User cancelled');
|
|
583
|
-
});
|
|
584
|
-
it('cleans up stdin on selection', async () => {
|
|
585
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
586
|
-
if (event === 'keypress') {
|
|
587
|
-
setImmediate(() => {
|
|
588
|
-
handler('', { name: 'return' });
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
return process.stdin;
|
|
592
|
-
});
|
|
593
|
-
await promptChoiceIndex('Choose:', ['A', 'B']);
|
|
594
|
-
expect(mockStdinRemoveListener).toHaveBeenCalledWith('keypress', expect.any(Function));
|
|
595
|
-
expect(mockStdinSetRawMode).toHaveBeenCalledWith(false);
|
|
596
|
-
expect(mockStdinPause).toHaveBeenCalled();
|
|
597
|
-
});
|
|
598
|
-
it('wraps around when navigating past last option', async () => {
|
|
599
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
600
|
-
if (event === 'keypress') {
|
|
601
|
-
setImmediate(() => {
|
|
602
|
-
// Navigate down 3 times on a 3-item list (wraps to first)
|
|
603
|
-
handler('', { name: 'down' });
|
|
604
|
-
setImmediate(() => {
|
|
605
|
-
handler('', { name: 'down' });
|
|
606
|
-
setImmediate(() => {
|
|
607
|
-
handler('', { name: 'down' });
|
|
608
|
-
setImmediate(() => {
|
|
609
|
-
handler('', { name: 'return' });
|
|
610
|
-
});
|
|
611
|
-
});
|
|
612
|
-
});
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
return process.stdin;
|
|
616
|
-
});
|
|
617
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
618
|
-
expect(result).toBe(1); // Wrapped back to first (1-based)
|
|
619
|
-
});
|
|
620
|
-
it('calls readline emitKeypressEvents', async () => {
|
|
621
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
622
|
-
if (event === 'keypress') {
|
|
623
|
-
setImmediate(() => {
|
|
624
|
-
handler('', { name: 'return' });
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
return process.stdin;
|
|
628
|
-
});
|
|
629
|
-
await promptChoiceIndex('Choose:', ['Option A', 'Option B']);
|
|
630
|
-
// Check readline.emitKeypressEvents was called
|
|
631
|
-
expect(readline.emitKeypressEvents).toHaveBeenCalledWith(process.stdin);
|
|
632
|
-
});
|
|
633
|
-
});
|
|
634
|
-
describe('promptChoice with arrow keys', () => {
|
|
635
|
-
it('returns value of selected option', async () => {
|
|
636
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
637
|
-
if (event === 'keypress') {
|
|
638
|
-
setImmediate(() => {
|
|
639
|
-
handler('', { name: 'down' });
|
|
640
|
-
setImmediate(() => {
|
|
641
|
-
handler('', { name: 'return' });
|
|
642
|
-
});
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
return process.stdin;
|
|
646
|
-
});
|
|
647
|
-
const result = await promptChoice('Choose:', [
|
|
648
|
-
{ label: 'First', value: 'first-value' },
|
|
649
|
-
{ label: 'Second', value: 'second-value' },
|
|
650
|
-
]);
|
|
651
|
-
expect(result).toBe('second-value');
|
|
652
|
-
});
|
|
653
|
-
it('handles options with descriptions', async () => {
|
|
654
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
655
|
-
if (event === 'keypress') {
|
|
656
|
-
setImmediate(() => {
|
|
657
|
-
handler('', { name: 'return' });
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
return process.stdin;
|
|
661
|
-
});
|
|
662
|
-
const result = await promptChoice('Choose:', [
|
|
663
|
-
{ label: 'Option', description: 'A helpful description', value: 'opt' },
|
|
664
|
-
]);
|
|
665
|
-
expect(result).toBe('opt');
|
|
666
|
-
});
|
|
667
|
-
it('rejects on q key press', async () => {
|
|
668
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
669
|
-
if (event === 'keypress') {
|
|
670
|
-
setImmediate(() => {
|
|
671
|
-
handler('q', {});
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
return process.stdin;
|
|
675
|
-
});
|
|
676
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toThrow('User cancelled');
|
|
677
|
-
});
|
|
678
|
-
it('rejects on Ctrl+C', async () => {
|
|
679
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
680
|
-
if (event === 'keypress') {
|
|
681
|
-
setImmediate(() => {
|
|
682
|
-
handler('', { name: 'c', ctrl: true });
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
return process.stdin;
|
|
686
|
-
});
|
|
687
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toThrow('User cancelled');
|
|
688
|
-
});
|
|
689
|
-
it('navigates up and wraps to last option', async () => {
|
|
690
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
691
|
-
if (event === 'keypress') {
|
|
692
|
-
setImmediate(() => {
|
|
693
|
-
handler('', { name: 'up' });
|
|
694
|
-
setImmediate(() => {
|
|
695
|
-
handler('', { name: 'return' });
|
|
696
|
-
});
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
return process.stdin;
|
|
700
|
-
});
|
|
701
|
-
const result = await promptChoice('Choose:', [
|
|
702
|
-
{ label: 'First', value: 'first' },
|
|
703
|
-
{ label: 'Second', value: 'second' },
|
|
704
|
-
{ label: 'Third', value: 'third' },
|
|
705
|
-
]);
|
|
706
|
-
expect(result).toBe('third'); // Wrapped to last
|
|
707
|
-
});
|
|
708
|
-
it('navigates down and wraps to first option', async () => {
|
|
709
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
710
|
-
if (event === 'keypress') {
|
|
711
|
-
setImmediate(() => {
|
|
712
|
-
handler('', { name: 'down' });
|
|
713
|
-
setImmediate(() => {
|
|
714
|
-
handler('', { name: 'down' });
|
|
715
|
-
setImmediate(() => {
|
|
716
|
-
handler('', { name: 'down' });
|
|
717
|
-
setImmediate(() => {
|
|
718
|
-
handler('', { name: 'return' });
|
|
719
|
-
});
|
|
720
|
-
});
|
|
721
|
-
});
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
return process.stdin;
|
|
725
|
-
});
|
|
726
|
-
const result = await promptChoice('Choose:', [
|
|
727
|
-
{ label: 'First', value: 'first' },
|
|
728
|
-
{ label: 'Second', value: 'second' },
|
|
729
|
-
{ label: 'Third', value: 'third' },
|
|
730
|
-
]);
|
|
731
|
-
expect(result).toBe('first'); // Wrapped to first
|
|
732
|
-
});
|
|
733
|
-
it('selects with right arrow key', async () => {
|
|
734
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
735
|
-
if (event === 'keypress') {
|
|
736
|
-
setImmediate(() => {
|
|
737
|
-
handler('', { name: 'down' });
|
|
738
|
-
setImmediate(() => {
|
|
739
|
-
handler('', { name: 'right' }); // Right arrow to select
|
|
740
|
-
});
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
return process.stdin;
|
|
744
|
-
});
|
|
745
|
-
const result = await promptChoice('Choose:', [
|
|
746
|
-
{ label: 'First', value: 'first' },
|
|
747
|
-
{ label: 'Second', value: 'second' },
|
|
748
|
-
]);
|
|
749
|
-
expect(result).toBe('second');
|
|
750
|
-
});
|
|
751
|
-
it('rejects with UserNavigatedBack on left arrow', async () => {
|
|
752
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
753
|
-
if (event === 'keypress') {
|
|
754
|
-
setImmediate(() => {
|
|
755
|
-
handler('', { name: 'left' }); // Left arrow to go back
|
|
756
|
-
});
|
|
757
|
-
}
|
|
758
|
-
return process.stdin;
|
|
759
|
-
});
|
|
760
|
-
await expect(promptChoice('Choose:', [{ label: 'A', value: 'a' }])).rejects.toBeInstanceOf(UserNavigatedBack);
|
|
761
|
-
});
|
|
762
|
-
});
|
|
763
|
-
describe('promptChoiceIndex left/right arrow navigation', () => {
|
|
764
|
-
it('selects with right arrow key', async () => {
|
|
765
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
766
|
-
if (event === 'keypress') {
|
|
767
|
-
setImmediate(() => {
|
|
768
|
-
handler('', { name: 'down' });
|
|
769
|
-
setImmediate(() => {
|
|
770
|
-
handler('', { name: 'right' }); // Right arrow to select
|
|
771
|
-
});
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
return process.stdin;
|
|
775
|
-
});
|
|
776
|
-
const result = await promptChoiceIndex('Choose:', ['A', 'B', 'C']);
|
|
777
|
-
expect(result).toBe(2); // Second option (1-based)
|
|
778
|
-
});
|
|
779
|
-
it('rejects with UserNavigatedBack on left arrow', async () => {
|
|
780
|
-
mockStdinOn.mockImplementation((event, handler) => {
|
|
781
|
-
if (event === 'keypress') {
|
|
782
|
-
setImmediate(() => {
|
|
783
|
-
handler('', { name: 'left' }); // Left arrow to go back
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
return process.stdin;
|
|
787
|
-
});
|
|
788
|
-
await expect(promptChoiceIndex('Choose:', ['A', 'B'])).rejects.toBeInstanceOf(UserNavigatedBack);
|
|
789
|
-
});
|
|
790
|
-
});
|
|
791
|
-
});
|
|
792
|
-
describe('UserNavigatedBack', () => {
|
|
793
|
-
it('is an Error instance', () => {
|
|
794
|
-
const error = new UserNavigatedBack();
|
|
795
|
-
expect(error).toBeInstanceOf(Error);
|
|
796
|
-
});
|
|
797
|
-
it('has correct name', () => {
|
|
798
|
-
const error = new UserNavigatedBack();
|
|
799
|
-
expect(error.name).toBe('UserNavigatedBack');
|
|
800
|
-
});
|
|
801
|
-
it('has correct message', () => {
|
|
802
|
-
const error = new UserNavigatedBack();
|
|
803
|
-
expect(error.message).toBe('User navigated back');
|
|
804
|
-
});
|
|
805
|
-
});
|
|
806
|
-
});
|
|
807
|
-
//# sourceMappingURL=prompts.test.js.map
|