@camaradesuk/git-worktree-tools 1.8.0 → 1.10.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 +48 -27
- package/dist/cli/cleanpr.js +74 -53
- package/dist/cli/cleanpr.js.map +1 -1
- package/dist/cli/cleanpr.test.js +2 -0
- package/dist/cli/cleanpr.test.js.map +1 -1
- package/dist/cli/lswt.js +32 -56
- package/dist/cli/lswt.js.map +1 -1
- package/dist/cli/lswt.test.js +17 -27
- package/dist/cli/lswt.test.js.map +1 -1
- package/dist/cli/newpr.d.ts +13 -1
- package/dist/cli/newpr.d.ts.map +1 -1
- package/dist/cli/newpr.js +350 -151
- package/dist/cli/newpr.js.map +1 -1
- package/dist/cli/newpr.test.js +314 -5
- package/dist/cli/newpr.test.js.map +1 -1
- package/dist/cli/prs.d.ts +3 -10
- package/dist/cli/prs.d.ts.map +1 -1
- package/dist/cli/prs.js +6 -168
- package/dist/cli/prs.js.map +1 -1
- package/dist/cli/prs.test.js +55 -0
- package/dist/cli/prs.test.js.map +1 -1
- package/dist/cli/wt/clean.d.ts +6 -2
- package/dist/cli/wt/clean.d.ts.map +1 -1
- package/dist/cli/wt/clean.js +401 -20
- package/dist/cli/wt/clean.js.map +1 -1
- package/dist/cli/wt/clean.test.d.ts +8 -0
- package/dist/cli/wt/clean.test.d.ts.map +1 -0
- package/dist/cli/wt/clean.test.js +624 -0
- package/dist/cli/wt/clean.test.js.map +1 -0
- package/dist/cli/wt/completion.d.ts +3 -0
- package/dist/cli/wt/completion.d.ts.map +1 -1
- package/dist/cli/wt/completion.js +80 -9
- package/dist/cli/wt/completion.js.map +1 -1
- package/dist/cli/wt/completion.test.js +102 -0
- package/dist/cli/wt/completion.test.js.map +1 -1
- package/dist/cli/wt/config.d.ts +3 -1
- package/dist/cli/wt/config.d.ts.map +1 -1
- package/dist/cli/wt/config.js +323 -32
- package/dist/cli/wt/config.js.map +1 -1
- package/dist/cli/wt/config.test.d.ts +2 -0
- package/dist/cli/wt/config.test.d.ts.map +1 -1
- package/dist/cli/wt/config.test.js +206 -26
- package/dist/cli/wt/config.test.js.map +1 -1
- package/dist/cli/wt/interactive-menu.d.ts +2 -0
- package/dist/cli/wt/interactive-menu.d.ts.map +1 -1
- package/dist/cli/wt/interactive-menu.js +346 -73
- package/dist/cli/wt/interactive-menu.js.map +1 -1
- package/dist/cli/wt/interactive-menu.test.d.ts +4 -2
- package/dist/cli/wt/interactive-menu.test.d.ts.map +1 -1
- package/dist/cli/wt/interactive-menu.test.js +383 -323
- package/dist/cli/wt/interactive-menu.test.js.map +1 -1
- package/dist/cli/wt/link.d.ts +3 -1
- package/dist/cli/wt/link.d.ts.map +1 -1
- package/dist/cli/wt/link.js +125 -38
- package/dist/cli/wt/link.js.map +1 -1
- package/dist/cli/wt/list.d.ts +4 -1
- package/dist/cli/wt/list.d.ts.map +1 -1
- package/dist/cli/wt/list.js +85 -16
- package/dist/cli/wt/list.js.map +1 -1
- package/dist/cli/wt/list.test.d.ts +10 -0
- package/dist/cli/wt/list.test.d.ts.map +1 -0
- package/dist/cli/wt/list.test.js +157 -0
- package/dist/cli/wt/list.test.js.map +1 -0
- package/dist/cli/wt/new.d.ts +8 -2
- package/dist/cli/wt/new.d.ts.map +1 -1
- package/dist/cli/wt/new.js +91 -46
- package/dist/cli/wt/new.js.map +1 -1
- package/dist/cli/wt/prs.d.ts +2 -1
- package/dist/cli/wt/prs.d.ts.map +1 -1
- package/dist/cli/wt/prs.js +3 -164
- package/dist/cli/wt/prs.js.map +1 -1
- package/dist/cli/wt/run-command.d.ts +4 -2
- package/dist/cli/wt/run-command.d.ts.map +1 -1
- package/dist/cli/wt/run-command.js +6 -4
- package/dist/cli/wt/run-command.js.map +1 -1
- package/dist/cli/wt/state.d.ts +3 -1
- package/dist/cli/wt/state.d.ts.map +1 -1
- package/dist/cli/wt/state.js +74 -10
- package/dist/cli/wt/state.js.map +1 -1
- package/dist/cli/wt/state.test.d.ts +9 -0
- package/dist/cli/wt/state.test.d.ts.map +1 -0
- package/dist/cli/wt/state.test.js +127 -0
- package/dist/cli/wt/state.test.js.map +1 -0
- package/dist/cli/wt/wt.test.d.ts +2 -2
- package/dist/cli/wt/wt.test.js +430 -212
- package/dist/cli/wt/wt.test.js.map +1 -1
- package/dist/cli/wt.d.ts.map +1 -1
- package/dist/cli/wt.js +50 -36
- package/dist/cli/wt.js.map +1 -1
- package/dist/cli/wt.unit.test.js +16 -38
- package/dist/cli/wt.unit.test.js.map +1 -1
- package/dist/cli/wtconfig.d.ts +1 -0
- package/dist/cli/wtconfig.d.ts.map +1 -1
- package/dist/cli/wtconfig.js +213 -21
- package/dist/cli/wtconfig.js.map +1 -1
- package/dist/cli/wtconfig.test.js +3 -0
- package/dist/cli/wtconfig.test.js.map +1 -1
- package/dist/cli/wtlink.js +116 -73
- package/dist/cli/wtlink.js.map +1 -1
- package/dist/cli/wtstate.js +21 -2
- package/dist/cli/wtstate.js.map +1 -1
- package/dist/e2e/wt/interactive-menu.e2e.test.js +17 -17
- package/dist/e2e/wt/interactive-menu.e2e.test.js.map +1 -1
- package/dist/lib/ai/types.d.ts +12 -0
- package/dist/lib/ai/types.d.ts.map +1 -1
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/cleanpr/args.d.ts.map +1 -1
- package/dist/lib/cleanpr/args.js +20 -0
- package/dist/lib/cleanpr/args.js.map +1 -1
- package/dist/lib/cleanpr/types.d.ts +6 -0
- package/dist/lib/cleanpr/types.d.ts.map +1 -1
- package/dist/lib/cleanpr/worktree-info.d.ts.map +1 -1
- package/dist/lib/cleanpr/worktree-info.js +1 -6
- package/dist/lib/cleanpr/worktree-info.js.map +1 -1
- package/dist/lib/cleanpr/worktree-info.test.js +10 -13
- package/dist/lib/cleanpr/worktree-info.test.js.map +1 -1
- package/dist/lib/colors.d.ts +5 -0
- package/dist/lib/colors.d.ts.map +1 -1
- package/dist/lib/colors.js +13 -6
- package/dist/lib/colors.js.map +1 -1
- package/dist/lib/config-editor.d.ts.map +1 -1
- package/dist/lib/config-editor.js.map +1 -1
- package/dist/lib/config-migration/detector.d.ts +25 -0
- package/dist/lib/config-migration/detector.d.ts.map +1 -0
- package/dist/lib/config-migration/detector.js +372 -0
- package/dist/lib/config-migration/detector.js.map +1 -0
- package/dist/lib/config-migration/detector.test.d.ts +5 -0
- package/dist/lib/config-migration/detector.test.d.ts.map +1 -0
- package/dist/lib/config-migration/detector.test.js +201 -0
- package/dist/lib/config-migration/detector.test.js.map +1 -0
- package/dist/lib/config-migration/index.d.ts +29 -0
- package/dist/lib/config-migration/index.d.ts.map +1 -0
- package/dist/lib/config-migration/index.js +33 -0
- package/dist/lib/config-migration/index.js.map +1 -0
- package/dist/lib/config-migration/reporter.d.ts +53 -0
- package/dist/lib/config-migration/reporter.d.ts.map +1 -0
- package/dist/lib/config-migration/reporter.js +257 -0
- package/dist/lib/config-migration/reporter.js.map +1 -0
- package/dist/lib/config-migration/reporter.test.d.ts +5 -0
- package/dist/lib/config-migration/reporter.test.d.ts.map +1 -0
- package/dist/lib/config-migration/reporter.test.js +305 -0
- package/dist/lib/config-migration/reporter.test.js.map +1 -0
- package/dist/lib/config-migration/runner.d.ts +46 -0
- package/dist/lib/config-migration/runner.d.ts.map +1 -0
- package/dist/lib/config-migration/runner.js +364 -0
- package/dist/lib/config-migration/runner.js.map +1 -0
- package/dist/lib/config-migration/runner.test.d.ts +5 -0
- package/dist/lib/config-migration/runner.test.d.ts.map +1 -0
- package/dist/lib/config-migration/runner.test.js +235 -0
- package/dist/lib/config-migration/runner.test.js.map +1 -0
- package/dist/lib/config-migration/types.d.ts +120 -0
- package/dist/lib/config-migration/types.d.ts.map +1 -0
- package/dist/lib/config-migration/types.js +70 -0
- package/dist/lib/config-migration/types.js.map +1 -0
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config-validation.js +6 -0
- package/dist/lib/config-validation.js.map +1 -1
- package/dist/lib/config-validation.test.js +25 -0
- package/dist/lib/config-validation.test.js.map +1 -1
- package/dist/lib/config.d.ts +31 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +2 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/config.test.js +3 -15
- package/dist/lib/config.test.js.map +1 -1
- package/dist/lib/constants.d.ts +12 -4
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +24 -5
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/constants.test.js +88 -29
- package/dist/lib/constants.test.js.map +1 -1
- package/dist/lib/deprecation.d.ts +18 -0
- package/dist/lib/deprecation.d.ts.map +1 -0
- package/dist/lib/deprecation.js +28 -0
- package/dist/lib/deprecation.js.map +1 -0
- package/dist/lib/deprecation.test.d.ts +2 -0
- package/dist/lib/deprecation.test.d.ts.map +1 -0
- package/dist/lib/deprecation.test.js +71 -0
- package/dist/lib/deprecation.test.js.map +1 -0
- package/dist/lib/hooks/confirmation.d.ts +49 -0
- package/dist/lib/hooks/confirmation.d.ts.map +1 -0
- package/dist/lib/hooks/confirmation.js +147 -0
- package/dist/lib/hooks/confirmation.js.map +1 -0
- package/dist/lib/hooks/confirmation.test.d.ts +7 -0
- package/dist/lib/hooks/confirmation.test.d.ts.map +1 -0
- package/dist/lib/hooks/confirmation.test.js +300 -0
- package/dist/lib/hooks/confirmation.test.js.map +1 -0
- package/dist/lib/hooks/executor.d.ts +16 -1
- package/dist/lib/hooks/executor.d.ts.map +1 -1
- package/dist/lib/hooks/executor.js +53 -4
- package/dist/lib/hooks/executor.js.map +1 -1
- package/dist/lib/hooks/index.d.ts +4 -2
- package/dist/lib/hooks/index.d.ts.map +1 -1
- package/dist/lib/hooks/index.js +3 -2
- package/dist/lib/hooks/index.js.map +1 -1
- package/dist/lib/hooks/types.d.ts +16 -0
- package/dist/lib/hooks/types.d.ts.map +1 -1
- package/dist/lib/hooks/types.js +12 -0
- package/dist/lib/hooks/types.js.map +1 -1
- package/dist/lib/logger.d.ts +40 -155
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +349 -420
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/logger.test.d.ts +10 -1
- package/dist/lib/logger.test.d.ts.map +1 -1
- package/dist/lib/logger.test.js +658 -258
- package/dist/lib/logger.test.js.map +1 -1
- package/dist/lib/lswt/action-executors.d.ts +2 -0
- package/dist/lib/lswt/action-executors.d.ts.map +1 -1
- package/dist/lib/lswt/action-executors.js +4 -3
- package/dist/lib/lswt/action-executors.js.map +1 -1
- package/dist/lib/lswt/action-executors.test.js +7 -0
- package/dist/lib/lswt/action-executors.test.js.map +1 -1
- package/dist/lib/lswt/args.d.ts.map +1 -1
- package/dist/lib/lswt/args.js +15 -1
- package/dist/lib/lswt/args.js.map +1 -1
- package/dist/lib/lswt/environment.d.ts +21 -2
- package/dist/lib/lswt/environment.d.ts.map +1 -1
- package/dist/lib/lswt/environment.js +73 -32
- package/dist/lib/lswt/environment.js.map +1 -1
- package/dist/lib/lswt/environment.test.js +79 -1
- package/dist/lib/lswt/environment.test.js.map +1 -1
- package/dist/lib/lswt/index.d.ts +1 -0
- package/dist/lib/lswt/index.d.ts.map +1 -1
- package/dist/lib/lswt/index.js +2 -0
- package/dist/lib/lswt/index.js.map +1 -1
- package/dist/lib/lswt/table.d.ts +15 -0
- package/dist/lib/lswt/table.d.ts.map +1 -0
- package/dist/lib/lswt/table.js +61 -0
- package/dist/lib/lswt/table.js.map +1 -0
- package/dist/lib/lswt/table.test.d.ts +5 -0
- package/dist/lib/lswt/table.test.d.ts.map +1 -0
- package/dist/lib/lswt/table.test.js +262 -0
- package/dist/lib/lswt/table.test.js.map +1 -0
- package/dist/lib/lswt/types.d.ts +4 -0
- package/dist/lib/lswt/types.d.ts.map +1 -1
- package/dist/lib/lswt/worktree-info.d.ts.map +1 -1
- package/dist/lib/lswt/worktree-info.js +1 -6
- package/dist/lib/lswt/worktree-info.js.map +1 -1
- package/dist/lib/lswt/worktree-info.test.js +5 -17
- package/dist/lib/lswt/worktree-info.test.js.map +1 -1
- package/dist/lib/newpr/args.d.ts.map +1 -1
- package/dist/lib/newpr/args.js +36 -1
- package/dist/lib/newpr/args.js.map +1 -1
- package/dist/lib/newpr/hook-runner.d.ts +11 -0
- package/dist/lib/newpr/hook-runner.d.ts.map +1 -1
- package/dist/lib/newpr/hook-runner.js +49 -1
- package/dist/lib/newpr/hook-runner.js.map +1 -1
- package/dist/lib/newpr/hook-runner.test.js +121 -0
- package/dist/lib/newpr/hook-runner.test.js.map +1 -1
- package/dist/lib/newpr/plan-generator.d.ts +121 -0
- package/dist/lib/newpr/plan-generator.d.ts.map +1 -0
- package/dist/lib/newpr/plan-generator.js +185 -0
- package/dist/lib/newpr/plan-generator.js.map +1 -0
- package/dist/lib/newpr/plan-generator.test.d.ts +7 -0
- package/dist/lib/newpr/plan-generator.test.d.ts.map +1 -0
- package/dist/lib/newpr/plan-generator.test.js +387 -0
- package/dist/lib/newpr/plan-generator.test.js.map +1 -0
- package/dist/lib/newpr/types.d.ts +12 -0
- package/dist/lib/newpr/types.d.ts.map +1 -1
- package/dist/lib/prs/actions.d.ts +5 -1
- package/dist/lib/prs/actions.d.ts.map +1 -1
- package/dist/lib/prs/actions.js +12 -10
- package/dist/lib/prs/actions.js.map +1 -1
- package/dist/lib/prs/actions.test.js +48 -5
- package/dist/lib/prs/actions.test.js.map +1 -1
- package/dist/lib/prs/command.d.ts +21 -0
- package/dist/lib/prs/command.d.ts.map +1 -0
- package/dist/lib/prs/command.js +175 -0
- package/dist/lib/prs/command.js.map +1 -0
- package/dist/lib/prs/command.test.d.ts +11 -0
- package/dist/lib/prs/command.test.d.ts.map +1 -0
- package/dist/lib/prs/command.test.js +409 -0
- package/dist/lib/prs/command.test.js.map +1 -0
- package/dist/lib/prs/interactive.d.ts.map +1 -1
- package/dist/lib/prs/interactive.js +15 -2
- package/dist/lib/prs/interactive.js.map +1 -1
- package/dist/lib/prs/interactive.test.js +153 -0
- package/dist/lib/prs/interactive.test.js.map +1 -1
- package/dist/lib/prs/types.d.ts +15 -0
- package/dist/lib/prs/types.d.ts.map +1 -1
- package/dist/lib/ui/error.d.ts +31 -0
- package/dist/lib/ui/error.d.ts.map +1 -0
- package/dist/lib/ui/error.js +47 -0
- package/dist/lib/ui/error.js.map +1 -0
- package/dist/lib/ui/error.test.d.ts +2 -0
- package/dist/lib/ui/error.test.d.ts.map +1 -0
- package/dist/lib/ui/error.test.js +143 -0
- package/dist/lib/ui/error.test.js.map +1 -0
- package/dist/lib/ui/index.d.ts +15 -0
- package/dist/lib/ui/index.d.ts.map +1 -0
- package/dist/lib/ui/index.js +19 -0
- package/dist/lib/ui/index.js.map +1 -0
- package/dist/lib/ui/output.d.ts +18 -0
- package/dist/lib/ui/output.d.ts.map +1 -0
- package/dist/lib/ui/output.js +31 -0
- package/dist/lib/ui/output.js.map +1 -0
- package/dist/lib/ui/output.test.d.ts +2 -0
- package/dist/lib/ui/output.test.d.ts.map +1 -0
- package/dist/lib/ui/output.test.js +59 -0
- package/dist/lib/ui/output.test.js.map +1 -0
- package/dist/lib/ui/spinner.d.ts +10 -0
- package/dist/lib/ui/spinner.d.ts.map +1 -0
- package/dist/lib/ui/spinner.js +10 -0
- package/dist/lib/ui/spinner.js.map +1 -0
- package/dist/lib/ui/status.d.ts +65 -0
- package/dist/lib/ui/status.d.ts.map +1 -0
- package/dist/lib/ui/status.js +100 -0
- package/dist/lib/ui/status.js.map +1 -0
- package/dist/lib/ui/status.test.d.ts +2 -0
- package/dist/lib/ui/status.test.d.ts.map +1 -0
- package/dist/lib/ui/status.test.js +158 -0
- package/dist/lib/ui/status.test.js.map +1 -0
- package/dist/lib/ui/table.d.ts +39 -0
- package/dist/lib/ui/table.d.ts.map +1 -0
- package/dist/lib/ui/table.js +45 -0
- package/dist/lib/ui/table.js.map +1 -0
- package/dist/lib/ui/table.test.d.ts +2 -0
- package/dist/lib/ui/table.test.d.ts.map +1 -0
- package/dist/lib/ui/table.test.js +115 -0
- package/dist/lib/ui/table.test.js.map +1 -0
- package/dist/lib/ui/theme.d.ts +34 -0
- package/dist/lib/ui/theme.d.ts.map +1 -0
- package/dist/lib/ui/theme.js +37 -0
- package/dist/lib/ui/theme.js.map +1 -0
- package/dist/lib/ui/theme.test.d.ts +2 -0
- package/dist/lib/ui/theme.test.d.ts.map +1 -0
- package/dist/lib/ui/theme.test.js +76 -0
- package/dist/lib/ui/theme.test.js.map +1 -0
- package/dist/lib/wtconfig/environment.d.ts +18 -1
- package/dist/lib/wtconfig/environment.d.ts.map +1 -1
- package/dist/lib/wtconfig/environment.js +60 -24
- package/dist/lib/wtconfig/environment.js.map +1 -1
- package/dist/lib/wtconfig/environment.test.js +45 -1
- package/dist/lib/wtconfig/environment.test.js.map +1 -1
- package/dist/lib/wtlink/config-manifest.test.js +26 -0
- package/dist/lib/wtlink/config-manifest.test.js.map +1 -1
- package/dist/lib/wtlink/link-configs.js +7 -7
- package/dist/lib/wtlink/link-configs.js.map +1 -1
- package/dist/lib/wtlink/validate-manifest.d.ts.map +1 -1
- package/dist/lib/wtlink/validate-manifest.js +5 -5
- package/dist/lib/wtlink/validate-manifest.js.map +1 -1
- package/dist/lib/wtstate/args.d.ts.map +1 -1
- package/dist/lib/wtstate/args.js +2 -0
- package/dist/lib/wtstate/args.js.map +1 -1
- package/dist/mcp/server.d.ts +2 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +264 -44
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/server.test.js +111 -0
- package/dist/mcp/server.test.js.map +1 -1
- package/package.json +3 -1
- package/schemas/worktreerc.schema.json +23 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
|
+
import { printTable } from './table.js';
|
|
3
|
+
import { setJsonMode } from './output.js';
|
|
4
|
+
import { setColorEnabled } from '../colors.js';
|
|
5
|
+
describe('ui/table', () => {
|
|
6
|
+
let logSpy;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
9
|
+
setColorEnabled(true);
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
setJsonMode(false);
|
|
13
|
+
vi.restoreAllMocks();
|
|
14
|
+
});
|
|
15
|
+
it('prints formatted rows with labels and fields', () => {
|
|
16
|
+
printTable({
|
|
17
|
+
rows: [
|
|
18
|
+
{
|
|
19
|
+
label: 'PR #42',
|
|
20
|
+
fields: [
|
|
21
|
+
{ key: 'Branch', value: 'feat/test' },
|
|
22
|
+
{ key: 'Path', value: '/tmp/repo.pr42' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
const allOutput = logSpy.mock.calls.map((c) => c[0]);
|
|
28
|
+
expect(allOutput.some((line) => line.includes('PR #42'))).toBe(true);
|
|
29
|
+
expect(allOutput.some((line) => line.includes('Branch'))).toBe(true);
|
|
30
|
+
expect(allOutput.some((line) => line.includes('feat/test'))).toBe(true);
|
|
31
|
+
expect(allOutput.some((line) => line.includes('Path'))).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
it('prints title when provided', () => {
|
|
34
|
+
printTable({
|
|
35
|
+
title: 'myrepo worktrees:',
|
|
36
|
+
rows: [
|
|
37
|
+
{
|
|
38
|
+
label: 'main',
|
|
39
|
+
fields: [{ key: 'Branch', value: 'main' }],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
const allOutput = logSpy.mock.calls.map((c) => c[0]);
|
|
44
|
+
expect(allOutput.some((line) => line.includes('myrepo worktrees:'))).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
it('appends indicator to label when provided', () => {
|
|
47
|
+
printTable({
|
|
48
|
+
rows: [
|
|
49
|
+
{
|
|
50
|
+
label: 'PR #42',
|
|
51
|
+
indicator: ' *',
|
|
52
|
+
fields: [{ key: 'Branch', value: 'feat/test' }],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
const allOutput = logSpy.mock.calls.map((c) => c[0]);
|
|
57
|
+
const labelLine = allOutput.find((line) => line.includes('PR #42'));
|
|
58
|
+
expect(labelLine).toContain(' *');
|
|
59
|
+
});
|
|
60
|
+
it('prints nothing for empty rows', () => {
|
|
61
|
+
printTable({ rows: [] });
|
|
62
|
+
expect(logSpy).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
it('prints summary line when provided', () => {
|
|
65
|
+
printTable({
|
|
66
|
+
rows: [
|
|
67
|
+
{
|
|
68
|
+
label: 'main',
|
|
69
|
+
fields: [{ key: 'Branch', value: 'main' }],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
summary: '3 worktrees | 2 PRs | 1 open',
|
|
73
|
+
});
|
|
74
|
+
const allOutput = logSpy.mock.calls.map((c) => c[0]);
|
|
75
|
+
expect(allOutput.some((line) => line.includes('3 worktrees'))).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
it('aligns field keys across all rows', () => {
|
|
78
|
+
printTable({
|
|
79
|
+
rows: [
|
|
80
|
+
{
|
|
81
|
+
label: 'Row 1',
|
|
82
|
+
fields: [
|
|
83
|
+
{ key: 'Branch', value: 'main' },
|
|
84
|
+
{ key: 'Path', value: '/tmp/main' },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: 'Row 2',
|
|
89
|
+
fields: [
|
|
90
|
+
{ key: 'Branch', value: 'feat/x' },
|
|
91
|
+
{ key: 'Commit', value: 'abc123' },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
// All field lines should have consistent key padding
|
|
97
|
+
const fieldLines = logSpy.mock.calls
|
|
98
|
+
.map((c) => c[0])
|
|
99
|
+
.filter((line) => line.includes('Branch') || line.includes('Path') || line.includes('Commit'));
|
|
100
|
+
// Each field starts with 4 spaces of indent
|
|
101
|
+
for (const line of fieldLines) {
|
|
102
|
+
expect(line).toMatch(/^\s{4}/);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
it('no-ops when JSON mode is active', () => {
|
|
106
|
+
setJsonMode(true);
|
|
107
|
+
printTable({
|
|
108
|
+
title: 'Test',
|
|
109
|
+
rows: [{ label: 'item', fields: [{ key: 'k', value: 'v' }] }],
|
|
110
|
+
summary: 'summary',
|
|
111
|
+
});
|
|
112
|
+
expect(logSpy).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=table.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.test.js","sourceRoot":"","sources":["../../../src/lib/ui/table.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized theme constants for UI output.
|
|
3
|
+
*
|
|
4
|
+
* Provides raw icons and box-drawing characters used by all other ui/ modules.
|
|
5
|
+
* colors.ts still provides the semantic functions (success(), error(), etc.)
|
|
6
|
+
* that combine icon + color. theme.ts provides the raw constants for cases
|
|
7
|
+
* where you need just the icon or just the box-drawing chars.
|
|
8
|
+
*/
|
|
9
|
+
export declare const icons: {
|
|
10
|
+
readonly success: "✓";
|
|
11
|
+
readonly error: "✗";
|
|
12
|
+
readonly warning: "⚠";
|
|
13
|
+
readonly info: "ℹ";
|
|
14
|
+
readonly bullet: "•";
|
|
15
|
+
readonly arrow: "▶";
|
|
16
|
+
readonly change: "*";
|
|
17
|
+
};
|
|
18
|
+
export declare const box: {
|
|
19
|
+
readonly horizontal: "═";
|
|
20
|
+
readonly vertical: "║";
|
|
21
|
+
readonly topLeft: "╔";
|
|
22
|
+
readonly topRight: "╗";
|
|
23
|
+
readonly bottomLeft: "╚";
|
|
24
|
+
readonly bottomRight: "╝";
|
|
25
|
+
readonly line: "─";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Returns a compact change indicator: red " *" when changes exist, empty string otherwise.
|
|
29
|
+
*
|
|
30
|
+
* Standardizes the inconsistency where lswt uses `colors.red(' *')`
|
|
31
|
+
* and cleanpr uses `colors.red(' [has changes]')`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function changeIndicator(hasChanges: boolean): string;
|
|
34
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../src/lib/ui/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,KAAK;;;;;;;;CAQR,CAAC;AAEX,eAAO,MAAM,GAAG;;;;;;;;CAQN,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAE3D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized theme constants for UI output.
|
|
3
|
+
*
|
|
4
|
+
* Provides raw icons and box-drawing characters used by all other ui/ modules.
|
|
5
|
+
* colors.ts still provides the semantic functions (success(), error(), etc.)
|
|
6
|
+
* that combine icon + color. theme.ts provides the raw constants for cases
|
|
7
|
+
* where you need just the icon or just the box-drawing chars.
|
|
8
|
+
*/
|
|
9
|
+
import * as colors from '../colors.js';
|
|
10
|
+
export const icons = {
|
|
11
|
+
success: '\u2713',
|
|
12
|
+
error: '\u2717',
|
|
13
|
+
warning: '\u26A0',
|
|
14
|
+
info: '\u2139',
|
|
15
|
+
bullet: '\u2022',
|
|
16
|
+
arrow: '\u25B6',
|
|
17
|
+
change: '*',
|
|
18
|
+
};
|
|
19
|
+
export const box = {
|
|
20
|
+
horizontal: '\u2550',
|
|
21
|
+
vertical: '\u2551',
|
|
22
|
+
topLeft: '\u2554',
|
|
23
|
+
topRight: '\u2557',
|
|
24
|
+
bottomLeft: '\u255A',
|
|
25
|
+
bottomRight: '\u255D',
|
|
26
|
+
line: '\u2500',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Returns a compact change indicator: red " *" when changes exist, empty string otherwise.
|
|
30
|
+
*
|
|
31
|
+
* Standardizes the inconsistency where lswt uses `colors.red(' *')`
|
|
32
|
+
* and cleanpr uses `colors.red(' [has changes]')`.
|
|
33
|
+
*/
|
|
34
|
+
export function changeIndicator(hasChanges) {
|
|
35
|
+
return hasChanges ? colors.red(` ${icons.change}`) : '';
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../src/lib/ui/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAEvC,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,GAAG;CACH,CAAC;AAEX,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,QAAQ;IACpB,WAAW,EAAE,QAAQ;IACrB,IAAI,EAAE,QAAQ;CACN,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,UAAmB;IACjD,OAAO,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.d.ts","sourceRoot":"","sources":["../../../src/lib/ui/theme.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { icons, box, changeIndicator } from './theme.js';
|
|
3
|
+
import { setColorEnabled } from '../colors.js';
|
|
4
|
+
describe('ui/theme', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
// Enable colors for predictable output
|
|
7
|
+
setColorEnabled(true);
|
|
8
|
+
});
|
|
9
|
+
describe('icons', () => {
|
|
10
|
+
it('exports all expected icon constants', () => {
|
|
11
|
+
expect(icons.success).toBe('\u2713');
|
|
12
|
+
expect(icons.error).toBe('\u2717');
|
|
13
|
+
expect(icons.warning).toBe('\u26A0');
|
|
14
|
+
expect(icons.info).toBe('\u2139');
|
|
15
|
+
expect(icons.bullet).toBe('\u2022');
|
|
16
|
+
expect(icons.arrow).toBe('\u25B6');
|
|
17
|
+
expect(icons.change).toBe('*');
|
|
18
|
+
});
|
|
19
|
+
it('icons object is readonly', () => {
|
|
20
|
+
// TypeScript enforces this at compile time via `as const`,
|
|
21
|
+
// but verify the object has the right shape at runtime
|
|
22
|
+
expect(Object.keys(icons)).toEqual([
|
|
23
|
+
'success',
|
|
24
|
+
'error',
|
|
25
|
+
'warning',
|
|
26
|
+
'info',
|
|
27
|
+
'bullet',
|
|
28
|
+
'arrow',
|
|
29
|
+
'change',
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('box', () => {
|
|
34
|
+
it('exports all expected box-drawing constants', () => {
|
|
35
|
+
expect(box.horizontal).toBe('\u2550');
|
|
36
|
+
expect(box.vertical).toBe('\u2551');
|
|
37
|
+
expect(box.topLeft).toBe('\u2554');
|
|
38
|
+
expect(box.topRight).toBe('\u2557');
|
|
39
|
+
expect(box.bottomLeft).toBe('\u255A');
|
|
40
|
+
expect(box.bottomRight).toBe('\u255D');
|
|
41
|
+
expect(box.line).toBe('\u2500');
|
|
42
|
+
});
|
|
43
|
+
it('box object is readonly', () => {
|
|
44
|
+
expect(Object.keys(box)).toEqual([
|
|
45
|
+
'horizontal',
|
|
46
|
+
'vertical',
|
|
47
|
+
'topLeft',
|
|
48
|
+
'topRight',
|
|
49
|
+
'bottomLeft',
|
|
50
|
+
'bottomRight',
|
|
51
|
+
'line',
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('changeIndicator', () => {
|
|
56
|
+
it('returns a string containing * when hasChanges is true', () => {
|
|
57
|
+
const result = changeIndicator(true);
|
|
58
|
+
expect(result).toContain('*');
|
|
59
|
+
});
|
|
60
|
+
it('returns empty string when hasChanges is false', () => {
|
|
61
|
+
const result = changeIndicator(false);
|
|
62
|
+
expect(result).toBe('');
|
|
63
|
+
});
|
|
64
|
+
it('includes red ANSI code when changes exist and colors enabled', () => {
|
|
65
|
+
const result = changeIndicator(true);
|
|
66
|
+
// Should contain the red ANSI escape code
|
|
67
|
+
expect(result).toContain('\x1b[31m');
|
|
68
|
+
});
|
|
69
|
+
it('returns plain * without color when colors disabled', () => {
|
|
70
|
+
setColorEnabled(false);
|
|
71
|
+
const result = changeIndicator(true);
|
|
72
|
+
expect(result).toBe(' *');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=theme.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.js","sourceRoot":"","sources":["../../../src/lib/ui/theme.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
* Detects installed tools and environment configuration for the setup wizard.
|
|
5
5
|
*/
|
|
6
6
|
import type { EnvironmentInfo } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Dependencies for environment detection (injectable for testing)
|
|
9
|
+
*/
|
|
10
|
+
export interface EnvironmentDeps {
|
|
11
|
+
/** Check if a command exists in PATH */
|
|
12
|
+
commandExists: (command: string) => boolean;
|
|
13
|
+
/** Run a command and return output, or null on error */
|
|
14
|
+
runCommand: (command: string, args: string[]) => string | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create default environment dependencies
|
|
18
|
+
*/
|
|
19
|
+
export declare function createDefaultEnvironmentDeps(): EnvironmentDeps;
|
|
20
|
+
/**
|
|
21
|
+
* Reset environment deps to defaults (for testing)
|
|
22
|
+
*/
|
|
23
|
+
export declare function resetEnvironmentDeps(): void;
|
|
7
24
|
/**
|
|
8
25
|
* Detect default branch from git config or common conventions
|
|
9
26
|
*/
|
|
@@ -11,7 +28,7 @@ export declare function detectDefaultBranch(repoRoot?: string): string;
|
|
|
11
28
|
/**
|
|
12
29
|
* Detect full environment information
|
|
13
30
|
*/
|
|
14
|
-
export declare function detectEnvironment(cwd?: string): EnvironmentInfo;
|
|
31
|
+
export declare function detectEnvironment(cwd?: string, deps?: EnvironmentDeps): EnvironmentInfo;
|
|
15
32
|
/**
|
|
16
33
|
* Get install command for detected package manager
|
|
17
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../src/lib/wtconfig/environment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../src/lib/wtconfig/environment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,wDAAwD;IACxD,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;CAChE;AA6CD;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,eAAe,CAK9D;AAKD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAwID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAkC7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,eAAe,CAYvF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,eAAe,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAY3F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,EAC3B,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GACtC,MAAM,GAAG,IAAI,CASf"}
|
|
@@ -7,9 +7,9 @@ import { spawnSync } from 'child_process';
|
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
/**
|
|
10
|
-
* Check if a command exists in PATH
|
|
10
|
+
* Check if a command exists in PATH (implementation)
|
|
11
11
|
*/
|
|
12
|
-
function
|
|
12
|
+
function commandExistsImpl(command) {
|
|
13
13
|
try {
|
|
14
14
|
const isWindows = process.platform === 'win32';
|
|
15
15
|
if (isWindows) {
|
|
@@ -32,9 +32,9 @@ function commandExists(command) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Run a command and return output, or null on error
|
|
35
|
+
* Run a command and return output, or null on error (implementation)
|
|
36
36
|
*/
|
|
37
|
-
function
|
|
37
|
+
function runCommandImpl(command, args) {
|
|
38
38
|
try {
|
|
39
39
|
const result = spawnSync(command, args, {
|
|
40
40
|
encoding: 'utf8',
|
|
@@ -50,6 +50,23 @@ function runCommand(command, args) {
|
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Create default environment dependencies
|
|
55
|
+
*/
|
|
56
|
+
export function createDefaultEnvironmentDeps() {
|
|
57
|
+
return {
|
|
58
|
+
commandExists: commandExistsImpl,
|
|
59
|
+
runCommand: runCommandImpl,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Module-level deps instance (set by detectEnvironment)
|
|
63
|
+
let currentDeps = createDefaultEnvironmentDeps();
|
|
64
|
+
/**
|
|
65
|
+
* Reset environment deps to defaults (for testing)
|
|
66
|
+
*/
|
|
67
|
+
export function resetEnvironmentDeps() {
|
|
68
|
+
currentDeps = createDefaultEnvironmentDeps();
|
|
69
|
+
}
|
|
53
70
|
/**
|
|
54
71
|
* Detect operating system
|
|
55
72
|
*
|
|
@@ -71,7 +88,7 @@ function detectOS() {
|
|
|
71
88
|
* Detect git installation and configuration
|
|
72
89
|
*/
|
|
73
90
|
function detectGit() {
|
|
74
|
-
const version = runCommand('git', ['--version']);
|
|
91
|
+
const version = currentDeps.runCommand('git', ['--version']);
|
|
75
92
|
if (!version) {
|
|
76
93
|
return {
|
|
77
94
|
version: null,
|
|
@@ -83,8 +100,8 @@ function detectGit() {
|
|
|
83
100
|
// Extract version number (e.g., "git version 2.43.0" -> "2.43.0")
|
|
84
101
|
const versionMatch = version.match(/git version (\d+\.\d+\.\d+)/);
|
|
85
102
|
const versionNumber = versionMatch ? versionMatch[1] : version;
|
|
86
|
-
const user = runCommand('git', ['config', '--global', 'user.name']);
|
|
87
|
-
const email = runCommand('git', ['config', '--global', 'user.email']);
|
|
103
|
+
const user = currentDeps.runCommand('git', ['config', '--global', 'user.name']);
|
|
104
|
+
const email = currentDeps.runCommand('git', ['config', '--global', 'user.email']);
|
|
88
105
|
return {
|
|
89
106
|
version: versionNumber,
|
|
90
107
|
configured: !!(user && email),
|
|
@@ -96,7 +113,7 @@ function detectGit() {
|
|
|
96
113
|
* Detect GitHub CLI installation and authentication
|
|
97
114
|
*/
|
|
98
115
|
function detectGitHub() {
|
|
99
|
-
const installed = commandExists('gh');
|
|
116
|
+
const installed = currentDeps.commandExists('gh');
|
|
100
117
|
if (!installed) {
|
|
101
118
|
return {
|
|
102
119
|
installed: false,
|
|
@@ -105,13 +122,13 @@ function detectGitHub() {
|
|
|
105
122
|
};
|
|
106
123
|
}
|
|
107
124
|
// Check authentication status
|
|
108
|
-
const authStatus = runCommand('gh', ['auth', 'status']);
|
|
125
|
+
const authStatus = currentDeps.runCommand('gh', ['auth', 'status']);
|
|
109
126
|
const authenticated = authStatus !== null;
|
|
110
127
|
// Get authenticated user
|
|
111
128
|
let user = null;
|
|
112
129
|
if (authenticated) {
|
|
113
130
|
try {
|
|
114
|
-
const userJson = runCommand('gh', ['api', 'user', '-q', '.login']);
|
|
131
|
+
const userJson = currentDeps.runCommand('gh', ['api', 'user', '-q', '.login']);
|
|
115
132
|
user = userJson;
|
|
116
133
|
}
|
|
117
134
|
catch {
|
|
@@ -130,10 +147,10 @@ function detectGitHub() {
|
|
|
130
147
|
*/
|
|
131
148
|
function detectAI() {
|
|
132
149
|
return {
|
|
133
|
-
claudeCode: commandExists('claude'),
|
|
134
|
-
geminiCLI: commandExists('gemini'),
|
|
135
|
-
ollama: commandExists('ollama'),
|
|
136
|
-
codexCLI: commandExists('codex'),
|
|
150
|
+
claudeCode: currentDeps.commandExists('claude'),
|
|
151
|
+
geminiCLI: currentDeps.commandExists('gemini'),
|
|
152
|
+
ollama: currentDeps.commandExists('ollama'),
|
|
153
|
+
codexCLI: currentDeps.commandExists('codex'),
|
|
137
154
|
};
|
|
138
155
|
}
|
|
139
156
|
/**
|
|
@@ -155,13 +172,13 @@ function detectPackageManager(cwd) {
|
|
|
155
172
|
return 'npm';
|
|
156
173
|
}
|
|
157
174
|
// Check for installed package managers
|
|
158
|
-
if (commandExists('pnpm'))
|
|
175
|
+
if (currentDeps.commandExists('pnpm'))
|
|
159
176
|
return 'pnpm';
|
|
160
|
-
if (commandExists('yarn'))
|
|
177
|
+
if (currentDeps.commandExists('yarn'))
|
|
161
178
|
return 'yarn';
|
|
162
|
-
if (commandExists('bun'))
|
|
179
|
+
if (currentDeps.commandExists('bun'))
|
|
163
180
|
return 'bun';
|
|
164
|
-
if (commandExists('npm'))
|
|
181
|
+
if (currentDeps.commandExists('npm'))
|
|
165
182
|
return 'npm';
|
|
166
183
|
return null;
|
|
167
184
|
}
|
|
@@ -170,8 +187,8 @@ function detectPackageManager(cwd) {
|
|
|
170
187
|
*/
|
|
171
188
|
function detectIDE() {
|
|
172
189
|
return {
|
|
173
|
-
vscode: commandExists('code'),
|
|
174
|
-
cursor: commandExists('cursor'),
|
|
190
|
+
vscode: currentDeps.commandExists('code'),
|
|
191
|
+
cursor: currentDeps.commandExists('cursor'),
|
|
175
192
|
};
|
|
176
193
|
}
|
|
177
194
|
/**
|
|
@@ -179,16 +196,32 @@ function detectIDE() {
|
|
|
179
196
|
*/
|
|
180
197
|
export function detectDefaultBranch(repoRoot) {
|
|
181
198
|
// Try to get from git config
|
|
182
|
-
const initDefaultBranch = runCommand('git', [
|
|
199
|
+
const initDefaultBranch = currentDeps.runCommand('git', [
|
|
200
|
+
'config',
|
|
201
|
+
'--global',
|
|
202
|
+
'init.defaultBranch',
|
|
203
|
+
]);
|
|
183
204
|
if (initDefaultBranch) {
|
|
184
205
|
return initDefaultBranch;
|
|
185
206
|
}
|
|
186
207
|
// If in a repo, check what exists
|
|
187
208
|
if (repoRoot) {
|
|
188
|
-
const mainExists = runCommand('git', [
|
|
209
|
+
const mainExists = currentDeps.runCommand('git', [
|
|
210
|
+
'-C',
|
|
211
|
+
repoRoot,
|
|
212
|
+
'rev-parse',
|
|
213
|
+
'--verify',
|
|
214
|
+
'main',
|
|
215
|
+
]);
|
|
189
216
|
if (mainExists !== null)
|
|
190
217
|
return 'main';
|
|
191
|
-
const masterExists = runCommand('git', [
|
|
218
|
+
const masterExists = currentDeps.runCommand('git', [
|
|
219
|
+
'-C',
|
|
220
|
+
repoRoot,
|
|
221
|
+
'rev-parse',
|
|
222
|
+
'--verify',
|
|
223
|
+
'master',
|
|
224
|
+
]);
|
|
192
225
|
if (masterExists !== null)
|
|
193
226
|
return 'master';
|
|
194
227
|
}
|
|
@@ -198,7 +231,10 @@ export function detectDefaultBranch(repoRoot) {
|
|
|
198
231
|
/**
|
|
199
232
|
* Detect full environment information
|
|
200
233
|
*/
|
|
201
|
-
export function detectEnvironment(cwd) {
|
|
234
|
+
export function detectEnvironment(cwd, deps) {
|
|
235
|
+
if (deps) {
|
|
236
|
+
currentDeps = deps;
|
|
237
|
+
}
|
|
202
238
|
return {
|
|
203
239
|
os: detectOS(),
|
|
204
240
|
git: detectGit(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/lib/wtconfig/environment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/lib/wtconfig/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
6
|
import fs from 'fs';
|
|
7
|
-
import { detectEnvironment, detectDefaultBranch, getInstallCommand, getEditorCommand, } from './environment.js';
|
|
7
|
+
import { detectEnvironment, detectDefaultBranch, getInstallCommand, getEditorCommand, createDefaultEnvironmentDeps, resetEnvironmentDeps, } from './environment.js';
|
|
8
8
|
vi.mock('child_process');
|
|
9
9
|
vi.mock('fs');
|
|
10
10
|
describe('environment', () => {
|
|
@@ -13,6 +13,8 @@ describe('environment', () => {
|
|
|
13
13
|
beforeEach(() => {
|
|
14
14
|
vi.clearAllMocks();
|
|
15
15
|
process.env = { ...originalEnv };
|
|
16
|
+
// Reset module-level deps to defaults (uses mocked spawnSync)
|
|
17
|
+
resetEnvironmentDeps();
|
|
16
18
|
// Mock spawnSync to return not found by default
|
|
17
19
|
vi.mocked(spawnSync).mockReturnValue({
|
|
18
20
|
status: 1,
|
|
@@ -177,6 +179,39 @@ describe('environment', () => {
|
|
|
177
179
|
expect(result.ide.vscode).toBe(true);
|
|
178
180
|
expect(result.ide.cursor).toBe(true);
|
|
179
181
|
});
|
|
182
|
+
it('accepts mock deps for dependency injection', () => {
|
|
183
|
+
const mockDeps = {
|
|
184
|
+
commandExists: vi.fn().mockImplementation((cmd) => {
|
|
185
|
+
return cmd === 'code' || cmd === 'gh';
|
|
186
|
+
}),
|
|
187
|
+
runCommand: vi.fn().mockImplementation((cmd, args) => {
|
|
188
|
+
if (cmd === 'git' && args[0] === '--version') {
|
|
189
|
+
return 'git version 2.45.0';
|
|
190
|
+
}
|
|
191
|
+
if (cmd === 'git' && args[0] === 'config' && args[2] === 'user.name') {
|
|
192
|
+
return 'Mock User';
|
|
193
|
+
}
|
|
194
|
+
if (cmd === 'git' && args[0] === 'config' && args[2] === 'user.email') {
|
|
195
|
+
return 'mock@example.com';
|
|
196
|
+
}
|
|
197
|
+
if (cmd === 'gh' && args[0] === 'auth') {
|
|
198
|
+
return 'Logged in';
|
|
199
|
+
}
|
|
200
|
+
if (cmd === 'gh' && args[0] === 'api') {
|
|
201
|
+
return 'mockuser';
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}),
|
|
205
|
+
};
|
|
206
|
+
const result = detectEnvironment(undefined, mockDeps);
|
|
207
|
+
expect(result.git.version).toBe('2.45.0');
|
|
208
|
+
expect(result.git.user).toBe('Mock User');
|
|
209
|
+
expect(result.git.email).toBe('mock@example.com');
|
|
210
|
+
expect(result.github.installed).toBe(true);
|
|
211
|
+
expect(result.ide.vscode).toBe(true);
|
|
212
|
+
expect(mockDeps.commandExists).toHaveBeenCalled();
|
|
213
|
+
expect(mockDeps.runCommand).toHaveBeenCalled();
|
|
214
|
+
});
|
|
180
215
|
});
|
|
181
216
|
describe('detectDefaultBranch', () => {
|
|
182
217
|
it('returns main by default', () => {
|
|
@@ -211,6 +246,15 @@ describe('environment', () => {
|
|
|
211
246
|
expect(getInstallCommand(null)).toBe('npm install');
|
|
212
247
|
});
|
|
213
248
|
});
|
|
249
|
+
describe('createDefaultEnvironmentDeps', () => {
|
|
250
|
+
it('returns deps object with required functions', () => {
|
|
251
|
+
const deps = createDefaultEnvironmentDeps();
|
|
252
|
+
expect(deps).toHaveProperty('commandExists');
|
|
253
|
+
expect(deps).toHaveProperty('runCommand');
|
|
254
|
+
expect(typeof deps.commandExists).toBe('function');
|
|
255
|
+
expect(typeof deps.runCommand).toBe('function');
|
|
256
|
+
});
|
|
257
|
+
});
|
|
214
258
|
describe('getEditorCommand', () => {
|
|
215
259
|
it('returns cursor command when cursor preferred and available', () => {
|
|
216
260
|
const ide = { vscode: true, cursor: true };
|