@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.
Files changed (431) hide show
  1. package/README.md +4 -4
  2. package/dist/lib/config.d.ts +2 -1
  3. package/dist/lib/config.d.ts.map +1 -1
  4. package/dist/lib/config.js +11 -0
  5. package/dist/lib/config.js.map +1 -1
  6. package/package.json +12 -3
  7. package/schemas/worktreerc.schema.json +1 -1
  8. package/dist/api/list.test.d.ts +0 -5
  9. package/dist/api/list.test.d.ts.map +0 -1
  10. package/dist/api/list.test.js +0 -390
  11. package/dist/api/list.test.js.map +0 -1
  12. package/dist/cli/cleanpr.test.d.ts +0 -2
  13. package/dist/cli/cleanpr.test.d.ts.map +0 -1
  14. package/dist/cli/cleanpr.test.js +0 -954
  15. package/dist/cli/cleanpr.test.js.map +0 -1
  16. package/dist/cli/lswt.test.d.ts +0 -2
  17. package/dist/cli/lswt.test.d.ts.map +0 -1
  18. package/dist/cli/lswt.test.js +0 -376
  19. package/dist/cli/lswt.test.js.map +0 -1
  20. package/dist/cli/newpr.test.d.ts +0 -2
  21. package/dist/cli/newpr.test.d.ts.map +0 -1
  22. package/dist/cli/newpr.test.js +0 -1182
  23. package/dist/cli/newpr.test.js.map +0 -1
  24. package/dist/cli/prs.test.d.ts +0 -8
  25. package/dist/cli/prs.test.d.ts.map +0 -1
  26. package/dist/cli/prs.test.js +0 -463
  27. package/dist/cli/prs.test.js.map +0 -1
  28. package/dist/cli/wt/clean.test.d.ts +0 -8
  29. package/dist/cli/wt/clean.test.d.ts.map +0 -1
  30. package/dist/cli/wt/clean.test.js +0 -624
  31. package/dist/cli/wt/clean.test.js.map +0 -1
  32. package/dist/cli/wt/completion.test.d.ts +0 -5
  33. package/dist/cli/wt/completion.test.d.ts.map +0 -1
  34. package/dist/cli/wt/completion.test.js +0 -275
  35. package/dist/cli/wt/completion.test.js.map +0 -1
  36. package/dist/cli/wt/config.test.d.ts +0 -7
  37. package/dist/cli/wt/config.test.d.ts.map +0 -1
  38. package/dist/cli/wt/config.test.js +0 -440
  39. package/dist/cli/wt/config.test.js.map +0 -1
  40. package/dist/cli/wt/entry.test.d.ts +0 -8
  41. package/dist/cli/wt/entry.test.d.ts.map +0 -1
  42. package/dist/cli/wt/entry.test.js +0 -201
  43. package/dist/cli/wt/entry.test.js.map +0 -1
  44. package/dist/cli/wt/init.test.d.ts +0 -5
  45. package/dist/cli/wt/init.test.d.ts.map +0 -1
  46. package/dist/cli/wt/init.test.js +0 -165
  47. package/dist/cli/wt/init.test.js.map +0 -1
  48. package/dist/cli/wt/init.unit.test.d.ts +0 -5
  49. package/dist/cli/wt/init.unit.test.d.ts.map +0 -1
  50. package/dist/cli/wt/init.unit.test.js +0 -432
  51. package/dist/cli/wt/init.unit.test.js.map +0 -1
  52. package/dist/cli/wt/interactive-menu.test.d.ts +0 -12
  53. package/dist/cli/wt/interactive-menu.test.d.ts.map +0 -1
  54. package/dist/cli/wt/interactive-menu.test.js +0 -796
  55. package/dist/cli/wt/interactive-menu.test.js.map +0 -1
  56. package/dist/cli/wt/list.test.d.ts +0 -10
  57. package/dist/cli/wt/list.test.d.ts.map +0 -1
  58. package/dist/cli/wt/list.test.js +0 -157
  59. package/dist/cli/wt/list.test.js.map +0 -1
  60. package/dist/cli/wt/prs.test.d.ts +0 -5
  61. package/dist/cli/wt/prs.test.d.ts.map +0 -1
  62. package/dist/cli/wt/prs.test.js +0 -410
  63. package/dist/cli/wt/prs.test.js.map +0 -1
  64. package/dist/cli/wt/run-command.test.d.ts +0 -5
  65. package/dist/cli/wt/run-command.test.d.ts.map +0 -1
  66. package/dist/cli/wt/run-command.test.js +0 -88
  67. package/dist/cli/wt/run-command.test.js.map +0 -1
  68. package/dist/cli/wt/state.test.d.ts +0 -9
  69. package/dist/cli/wt/state.test.d.ts.map +0 -1
  70. package/dist/cli/wt/state.test.js +0 -127
  71. package/dist/cli/wt/state.test.js.map +0 -1
  72. package/dist/cli/wt/wt.test.d.ts +0 -8
  73. package/dist/cli/wt/wt.test.d.ts.map +0 -1
  74. package/dist/cli/wt/wt.test.js +0 -739
  75. package/dist/cli/wt/wt.test.js.map +0 -1
  76. package/dist/cli/wt.unit.test.d.ts +0 -7
  77. package/dist/cli/wt.unit.test.d.ts.map +0 -1
  78. package/dist/cli/wt.unit.test.js +0 -160
  79. package/dist/cli/wt.unit.test.js.map +0 -1
  80. package/dist/cli/wtconfig.test.d.ts +0 -5
  81. package/dist/cli/wtconfig.test.d.ts.map +0 -1
  82. package/dist/cli/wtconfig.test.js +0 -1289
  83. package/dist/cli/wtconfig.test.js.map +0 -1
  84. package/dist/cli/wtlink.test.d.ts +0 -2
  85. package/dist/cli/wtlink.test.d.ts.map +0 -1
  86. package/dist/cli/wtlink.test.js +0 -249
  87. package/dist/cli/wtlink.test.js.map +0 -1
  88. package/dist/cli/wtstate.test.d.ts +0 -5
  89. package/dist/cli/wtstate.test.d.ts.map +0 -1
  90. package/dist/cli/wtstate.test.js +0 -193
  91. package/dist/cli/wtstate.test.js.map +0 -1
  92. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts +0 -2
  93. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts.map +0 -1
  94. package/dist/e2e/cleanpr/cleanpr.e2e.test.js +0 -326
  95. package/dist/e2e/cleanpr/cleanpr.e2e.test.js.map +0 -1
  96. package/dist/e2e/cli.e2e.test.d.ts +0 -2
  97. package/dist/e2e/cli.e2e.test.d.ts.map +0 -1
  98. package/dist/e2e/cli.e2e.test.js +0 -417
  99. package/dist/e2e/cli.e2e.test.js.map +0 -1
  100. package/dist/e2e/lswt/lswt.e2e.test.d.ts +0 -2
  101. package/dist/e2e/lswt/lswt.e2e.test.d.ts.map +0 -1
  102. package/dist/e2e/lswt/lswt.e2e.test.js +0 -361
  103. package/dist/e2e/lswt/lswt.e2e.test.js.map +0 -1
  104. package/dist/e2e/newpr/newpr.e2e.test.d.ts +0 -2
  105. package/dist/e2e/newpr/newpr.e2e.test.d.ts.map +0 -1
  106. package/dist/e2e/newpr/newpr.e2e.test.js +0 -286
  107. package/dist/e2e/newpr/newpr.e2e.test.js.map +0 -1
  108. package/dist/e2e/newpr/scenarios.e2e.test.d.ts +0 -2
  109. package/dist/e2e/newpr/scenarios.e2e.test.d.ts.map +0 -1
  110. package/dist/e2e/newpr/scenarios.e2e.test.js +0 -426
  111. package/dist/e2e/newpr/scenarios.e2e.test.js.map +0 -1
  112. package/dist/e2e/newpr-full-flow.e2e.test.d.ts +0 -2
  113. package/dist/e2e/newpr-full-flow.e2e.test.d.ts.map +0 -1
  114. package/dist/e2e/newpr-full-flow.e2e.test.js +0 -280
  115. package/dist/e2e/newpr-full-flow.e2e.test.js.map +0 -1
  116. package/dist/e2e/prs/prs.e2e.test.d.ts +0 -7
  117. package/dist/e2e/prs/prs.e2e.test.d.ts.map +0 -1
  118. package/dist/e2e/prs/prs.e2e.test.js +0 -606
  119. package/dist/e2e/prs/prs.e2e.test.js.map +0 -1
  120. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts +0 -2
  121. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts.map +0 -1
  122. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js +0 -298
  123. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js.map +0 -1
  124. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts +0 -8
  125. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts.map +0 -1
  126. package/dist/e2e/wt/interactive-menu.e2e.test.js +0 -583
  127. package/dist/e2e/wt/interactive-menu.e2e.test.js.map +0 -1
  128. package/dist/e2e/wt/wt.e2e.test.d.ts +0 -9
  129. package/dist/e2e/wt/wt.e2e.test.d.ts.map +0 -1
  130. package/dist/e2e/wt/wt.e2e.test.js +0 -597
  131. package/dist/e2e/wt/wt.e2e.test.js.map +0 -1
  132. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts +0 -2
  133. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts.map +0 -1
  134. package/dist/e2e/wtlink/wtlink.e2e.test.js +0 -416
  135. package/dist/e2e/wtlink/wtlink.e2e.test.js.map +0 -1
  136. package/dist/integration/git.integration.test.d.ts +0 -2
  137. package/dist/integration/git.integration.test.d.ts.map +0 -1
  138. package/dist/integration/git.integration.test.js +0 -336
  139. package/dist/integration/git.integration.test.js.map +0 -1
  140. package/dist/integration/lswt-remote-pr.integration.test.d.ts +0 -2
  141. package/dist/integration/lswt-remote-pr.integration.test.d.ts.map +0 -1
  142. package/dist/integration/lswt-remote-pr.integration.test.js +0 -222
  143. package/dist/integration/lswt-remote-pr.integration.test.js.map +0 -1
  144. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts +0 -2
  145. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts.map +0 -1
  146. package/dist/integration/newpr-branchfrom-head.integration.test.js +0 -498
  147. package/dist/integration/newpr-branchfrom-head.integration.test.js.map +0 -1
  148. package/dist/integration/newpr.integration.test.d.ts +0 -2
  149. package/dist/integration/newpr.integration.test.d.ts.map +0 -1
  150. package/dist/integration/newpr.integration.test.js +0 -460
  151. package/dist/integration/newpr.integration.test.js.map +0 -1
  152. package/dist/integration/prs.integration.test.d.ts +0 -8
  153. package/dist/integration/prs.integration.test.d.ts.map +0 -1
  154. package/dist/integration/prs.integration.test.js +0 -478
  155. package/dist/integration/prs.integration.test.js.map +0 -1
  156. package/dist/lib/ai/base-provider.test.d.ts +0 -7
  157. package/dist/lib/ai/base-provider.test.d.ts.map +0 -1
  158. package/dist/lib/ai/base-provider.test.js +0 -319
  159. package/dist/lib/ai/base-provider.test.js.map +0 -1
  160. package/dist/lib/ai/cli-provider.test.d.ts +0 -5
  161. package/dist/lib/ai/cli-provider.test.d.ts.map +0 -1
  162. package/dist/lib/ai/cli-provider.test.js +0 -460
  163. package/dist/lib/ai/cli-provider.test.js.map +0 -1
  164. package/dist/lib/ai/fallback-provider.test.d.ts +0 -7
  165. package/dist/lib/ai/fallback-provider.test.d.ts.map +0 -1
  166. package/dist/lib/ai/fallback-provider.test.js +0 -165
  167. package/dist/lib/ai/fallback-provider.test.js.map +0 -1
  168. package/dist/lib/ai/generation-service.test.d.ts +0 -7
  169. package/dist/lib/ai/generation-service.test.d.ts.map +0 -1
  170. package/dist/lib/ai/generation-service.test.js +0 -213
  171. package/dist/lib/ai/generation-service.test.js.map +0 -1
  172. package/dist/lib/ai/provider-manager.test.d.ts +0 -5
  173. package/dist/lib/ai/provider-manager.test.d.ts.map +0 -1
  174. package/dist/lib/ai/provider-manager.test.js +0 -312
  175. package/dist/lib/ai/provider-manager.test.js.map +0 -1
  176. package/dist/lib/ai/repo-docs.test.d.ts +0 -5
  177. package/dist/lib/ai/repo-docs.test.d.ts.map +0 -1
  178. package/dist/lib/ai/repo-docs.test.js +0 -357
  179. package/dist/lib/ai/repo-docs.test.js.map +0 -1
  180. package/dist/lib/cleanpr/args.test.d.ts +0 -2
  181. package/dist/lib/cleanpr/args.test.d.ts.map +0 -1
  182. package/dist/lib/cleanpr/args.test.js +0 -269
  183. package/dist/lib/cleanpr/args.test.js.map +0 -1
  184. package/dist/lib/cleanpr/cleanup.test.d.ts +0 -2
  185. package/dist/lib/cleanpr/cleanup.test.d.ts.map +0 -1
  186. package/dist/lib/cleanpr/cleanup.test.js +0 -296
  187. package/dist/lib/cleanpr/cleanup.test.js.map +0 -1
  188. package/dist/lib/cleanpr/worktree-info.test.d.ts +0 -2
  189. package/dist/lib/cleanpr/worktree-info.test.d.ts.map +0 -1
  190. package/dist/lib/cleanpr/worktree-info.test.js +0 -228
  191. package/dist/lib/cleanpr/worktree-info.test.js.map +0 -1
  192. package/dist/lib/colors.test.d.ts +0 -2
  193. package/dist/lib/colors.test.d.ts.map +0 -1
  194. package/dist/lib/colors.test.js +0 -142
  195. package/dist/lib/colors.test.js.map +0 -1
  196. package/dist/lib/config-editor.test.d.ts +0 -11
  197. package/dist/lib/config-editor.test.d.ts.map +0 -1
  198. package/dist/lib/config-editor.test.js +0 -526
  199. package/dist/lib/config-editor.test.js.map +0 -1
  200. package/dist/lib/config-migration/detector.test.d.ts +0 -5
  201. package/dist/lib/config-migration/detector.test.d.ts.map +0 -1
  202. package/dist/lib/config-migration/detector.test.js +0 -201
  203. package/dist/lib/config-migration/detector.test.js.map +0 -1
  204. package/dist/lib/config-migration/reporter.test.d.ts +0 -5
  205. package/dist/lib/config-migration/reporter.test.d.ts.map +0 -1
  206. package/dist/lib/config-migration/reporter.test.js +0 -305
  207. package/dist/lib/config-migration/reporter.test.js.map +0 -1
  208. package/dist/lib/config-migration/runner.test.d.ts +0 -5
  209. package/dist/lib/config-migration/runner.test.d.ts.map +0 -1
  210. package/dist/lib/config-migration/runner.test.js +0 -235
  211. package/dist/lib/config-migration/runner.test.js.map +0 -1
  212. package/dist/lib/config-validation.test.d.ts +0 -5
  213. package/dist/lib/config-validation.test.d.ts.map +0 -1
  214. package/dist/lib/config-validation.test.js +0 -423
  215. package/dist/lib/config-validation.test.js.map +0 -1
  216. package/dist/lib/config.test.d.ts +0 -2
  217. package/dist/lib/config.test.d.ts.map +0 -1
  218. package/dist/lib/config.test.js +0 -554
  219. package/dist/lib/config.test.js.map +0 -1
  220. package/dist/lib/constants.test.d.ts +0 -5
  221. package/dist/lib/constants.test.d.ts.map +0 -1
  222. package/dist/lib/constants.test.js +0 -180
  223. package/dist/lib/constants.test.js.map +0 -1
  224. package/dist/lib/deprecation.test.d.ts +0 -2
  225. package/dist/lib/deprecation.test.d.ts.map +0 -1
  226. package/dist/lib/deprecation.test.js +0 -71
  227. package/dist/lib/deprecation.test.js.map +0 -1
  228. package/dist/lib/errors.test.d.ts +0 -2
  229. package/dist/lib/errors.test.d.ts.map +0 -1
  230. package/dist/lib/errors.test.js +0 -117
  231. package/dist/lib/errors.test.js.map +0 -1
  232. package/dist/lib/git.test.d.ts +0 -2
  233. package/dist/lib/git.test.d.ts.map +0 -1
  234. package/dist/lib/git.test.js +0 -608
  235. package/dist/lib/git.test.js.map +0 -1
  236. package/dist/lib/github.test.d.ts +0 -2
  237. package/dist/lib/github.test.d.ts.map +0 -1
  238. package/dist/lib/github.test.js +0 -441
  239. package/dist/lib/github.test.js.map +0 -1
  240. package/dist/lib/global-check.test.d.ts +0 -5
  241. package/dist/lib/global-check.test.d.ts.map +0 -1
  242. package/dist/lib/global-check.test.js +0 -150
  243. package/dist/lib/global-check.test.js.map +0 -1
  244. package/dist/lib/global-config.test.d.ts +0 -5
  245. package/dist/lib/global-config.test.d.ts.map +0 -1
  246. package/dist/lib/global-config.test.js +0 -282
  247. package/dist/lib/global-config.test.js.map +0 -1
  248. package/dist/lib/hooks/confirmation.test.d.ts +0 -7
  249. package/dist/lib/hooks/confirmation.test.d.ts.map +0 -1
  250. package/dist/lib/hooks/confirmation.test.js +0 -300
  251. package/dist/lib/hooks/confirmation.test.js.map +0 -1
  252. package/dist/lib/hooks/executor.test.d.ts +0 -5
  253. package/dist/lib/hooks/executor.test.d.ts.map +0 -1
  254. package/dist/lib/hooks/executor.test.js +0 -648
  255. package/dist/lib/hooks/executor.test.js.map +0 -1
  256. package/dist/lib/hooks/templates.test.d.ts +0 -5
  257. package/dist/lib/hooks/templates.test.d.ts.map +0 -1
  258. package/dist/lib/hooks/templates.test.js +0 -163
  259. package/dist/lib/hooks/templates.test.js.map +0 -1
  260. package/dist/lib/hooks/types.test.d.ts +0 -5
  261. package/dist/lib/hooks/types.test.d.ts.map +0 -1
  262. package/dist/lib/hooks/types.test.js +0 -132
  263. package/dist/lib/hooks/types.test.js.map +0 -1
  264. package/dist/lib/json-output.test.d.ts +0 -5
  265. package/dist/lib/json-output.test.d.ts.map +0 -1
  266. package/dist/lib/json-output.test.js +0 -261
  267. package/dist/lib/json-output.test.js.map +0 -1
  268. package/dist/lib/logger.test.d.ts +0 -14
  269. package/dist/lib/logger.test.d.ts.map +0 -1
  270. package/dist/lib/logger.test.js +0 -692
  271. package/dist/lib/logger.test.js.map +0 -1
  272. package/dist/lib/lswt/action-executors.test.d.ts +0 -2
  273. package/dist/lib/lswt/action-executors.test.d.ts.map +0 -1
  274. package/dist/lib/lswt/action-executors.test.js +0 -1127
  275. package/dist/lib/lswt/action-executors.test.js.map +0 -1
  276. package/dist/lib/lswt/actions.test.d.ts +0 -2
  277. package/dist/lib/lswt/actions.test.d.ts.map +0 -1
  278. package/dist/lib/lswt/actions.test.js +0 -497
  279. package/dist/lib/lswt/actions.test.js.map +0 -1
  280. package/dist/lib/lswt/args.test.d.ts +0 -2
  281. package/dist/lib/lswt/args.test.d.ts.map +0 -1
  282. package/dist/lib/lswt/args.test.js +0 -195
  283. package/dist/lib/lswt/args.test.js.map +0 -1
  284. package/dist/lib/lswt/environment.test.d.ts +0 -2
  285. package/dist/lib/lswt/environment.test.d.ts.map +0 -1
  286. package/dist/lib/lswt/environment.test.js +0 -544
  287. package/dist/lib/lswt/environment.test.js.map +0 -1
  288. package/dist/lib/lswt/formatters.test.d.ts +0 -2
  289. package/dist/lib/lswt/formatters.test.d.ts.map +0 -1
  290. package/dist/lib/lswt/formatters.test.js +0 -323
  291. package/dist/lib/lswt/formatters.test.js.map +0 -1
  292. package/dist/lib/lswt/fuzzy-search.test.d.ts +0 -5
  293. package/dist/lib/lswt/fuzzy-search.test.d.ts.map +0 -1
  294. package/dist/lib/lswt/fuzzy-search.test.js +0 -207
  295. package/dist/lib/lswt/fuzzy-search.test.js.map +0 -1
  296. package/dist/lib/lswt/interactive.test.d.ts +0 -2
  297. package/dist/lib/lswt/interactive.test.d.ts.map +0 -1
  298. package/dist/lib/lswt/interactive.test.js +0 -771
  299. package/dist/lib/lswt/interactive.test.js.map +0 -1
  300. package/dist/lib/lswt/table.test.d.ts +0 -5
  301. package/dist/lib/lswt/table.test.d.ts.map +0 -1
  302. package/dist/lib/lswt/table.test.js +0 -262
  303. package/dist/lib/lswt/table.test.js.map +0 -1
  304. package/dist/lib/lswt/worktree-info.test.d.ts +0 -2
  305. package/dist/lib/lswt/worktree-info.test.d.ts.map +0 -1
  306. package/dist/lib/lswt/worktree-info.test.js +0 -484
  307. package/dist/lib/lswt/worktree-info.test.js.map +0 -1
  308. package/dist/lib/newpr/action-deps.test.d.ts +0 -5
  309. package/dist/lib/newpr/action-deps.test.d.ts.map +0 -1
  310. package/dist/lib/newpr/action-deps.test.js +0 -111
  311. package/dist/lib/newpr/action-deps.test.js.map +0 -1
  312. package/dist/lib/newpr/actions.test.d.ts +0 -2
  313. package/dist/lib/newpr/actions.test.d.ts.map +0 -1
  314. package/dist/lib/newpr/actions.test.js +0 -254
  315. package/dist/lib/newpr/actions.test.js.map +0 -1
  316. package/dist/lib/newpr/args.test.d.ts +0 -2
  317. package/dist/lib/newpr/args.test.d.ts.map +0 -1
  318. package/dist/lib/newpr/args.test.js +0 -479
  319. package/dist/lib/newpr/args.test.js.map +0 -1
  320. package/dist/lib/newpr/hook-runner.test.d.ts +0 -7
  321. package/dist/lib/newpr/hook-runner.test.d.ts.map +0 -1
  322. package/dist/lib/newpr/hook-runner.test.js +0 -422
  323. package/dist/lib/newpr/hook-runner.test.js.map +0 -1
  324. package/dist/lib/newpr/plan-generator.test.d.ts +0 -7
  325. package/dist/lib/newpr/plan-generator.test.d.ts.map +0 -1
  326. package/dist/lib/newpr/plan-generator.test.js +0 -387
  327. package/dist/lib/newpr/plan-generator.test.js.map +0 -1
  328. package/dist/lib/newpr/scenario-handler.test.d.ts +0 -2
  329. package/dist/lib/newpr/scenario-handler.test.d.ts.map +0 -1
  330. package/dist/lib/newpr/scenario-handler.test.js +0 -256
  331. package/dist/lib/newpr/scenario-handler.test.js.map +0 -1
  332. package/dist/lib/prompts.test.d.ts +0 -2
  333. package/dist/lib/prompts.test.d.ts.map +0 -1
  334. package/dist/lib/prompts.test.js +0 -807
  335. package/dist/lib/prompts.test.js.map +0 -1
  336. package/dist/lib/prs/actions.test.d.ts +0 -5
  337. package/dist/lib/prs/actions.test.d.ts.map +0 -1
  338. package/dist/lib/prs/actions.test.js +0 -356
  339. package/dist/lib/prs/actions.test.js.map +0 -1
  340. package/dist/lib/prs/command.test.d.ts +0 -11
  341. package/dist/lib/prs/command.test.d.ts.map +0 -1
  342. package/dist/lib/prs/command.test.js +0 -409
  343. package/dist/lib/prs/command.test.js.map +0 -1
  344. package/dist/lib/prs/data.test.d.ts +0 -5
  345. package/dist/lib/prs/data.test.d.ts.map +0 -1
  346. package/dist/lib/prs/data.test.js +0 -417
  347. package/dist/lib/prs/data.test.js.map +0 -1
  348. package/dist/lib/prs/details.test.d.ts +0 -5
  349. package/dist/lib/prs/details.test.d.ts.map +0 -1
  350. package/dist/lib/prs/details.test.js +0 -325
  351. package/dist/lib/prs/details.test.js.map +0 -1
  352. package/dist/lib/prs/filters.test.d.ts +0 -5
  353. package/dist/lib/prs/filters.test.d.ts.map +0 -1
  354. package/dist/lib/prs/filters.test.js +0 -312
  355. package/dist/lib/prs/filters.test.js.map +0 -1
  356. package/dist/lib/prs/formatters.test.d.ts +0 -2
  357. package/dist/lib/prs/formatters.test.d.ts.map +0 -1
  358. package/dist/lib/prs/formatters.test.js +0 -387
  359. package/dist/lib/prs/formatters.test.js.map +0 -1
  360. package/dist/lib/prs/interactive.test.d.ts +0 -5
  361. package/dist/lib/prs/interactive.test.d.ts.map +0 -1
  362. package/dist/lib/prs/interactive.test.js +0 -517
  363. package/dist/lib/prs/interactive.test.js.map +0 -1
  364. package/dist/lib/schema.test.d.ts +0 -10
  365. package/dist/lib/schema.test.d.ts.map +0 -1
  366. package/dist/lib/schema.test.js +0 -309
  367. package/dist/lib/schema.test.js.map +0 -1
  368. package/dist/lib/state-detection.test.d.ts +0 -2
  369. package/dist/lib/state-detection.test.d.ts.map +0 -1
  370. package/dist/lib/state-detection.test.js +0 -451
  371. package/dist/lib/state-detection.test.js.map +0 -1
  372. package/dist/lib/ui/error.test.d.ts +0 -2
  373. package/dist/lib/ui/error.test.d.ts.map +0 -1
  374. package/dist/lib/ui/error.test.js +0 -143
  375. package/dist/lib/ui/error.test.js.map +0 -1
  376. package/dist/lib/ui/output.test.d.ts +0 -2
  377. package/dist/lib/ui/output.test.d.ts.map +0 -1
  378. package/dist/lib/ui/output.test.js +0 -59
  379. package/dist/lib/ui/output.test.js.map +0 -1
  380. package/dist/lib/ui/status.test.d.ts +0 -2
  381. package/dist/lib/ui/status.test.d.ts.map +0 -1
  382. package/dist/lib/ui/status.test.js +0 -158
  383. package/dist/lib/ui/status.test.js.map +0 -1
  384. package/dist/lib/ui/table.test.d.ts +0 -2
  385. package/dist/lib/ui/table.test.d.ts.map +0 -1
  386. package/dist/lib/ui/table.test.js +0 -115
  387. package/dist/lib/ui/table.test.js.map +0 -1
  388. package/dist/lib/ui/theme.test.d.ts +0 -2
  389. package/dist/lib/ui/theme.test.d.ts.map +0 -1
  390. package/dist/lib/ui/theme.test.js +0 -76
  391. package/dist/lib/ui/theme.test.js.map +0 -1
  392. package/dist/lib/wtconfig/config-manager.test.d.ts +0 -5
  393. package/dist/lib/wtconfig/config-manager.test.d.ts.map +0 -1
  394. package/dist/lib/wtconfig/config-manager.test.js +0 -501
  395. package/dist/lib/wtconfig/config-manager.test.js.map +0 -1
  396. package/dist/lib/wtconfig/environment.test.d.ts +0 -5
  397. package/dist/lib/wtconfig/environment.test.d.ts.map +0 -1
  398. package/dist/lib/wtconfig/environment.test.js +0 -285
  399. package/dist/lib/wtconfig/environment.test.js.map +0 -1
  400. package/dist/lib/wtlink/config-manifest.test.d.ts +0 -2
  401. package/dist/lib/wtlink/config-manifest.test.d.ts.map +0 -1
  402. package/dist/lib/wtlink/config-manifest.test.js +0 -486
  403. package/dist/lib/wtlink/config-manifest.test.js.map +0 -1
  404. package/dist/lib/wtlink/link-configs.test.d.ts +0 -2
  405. package/dist/lib/wtlink/link-configs.test.d.ts.map +0 -1
  406. package/dist/lib/wtlink/link-configs.test.js +0 -612
  407. package/dist/lib/wtlink/link-configs.test.js.map +0 -1
  408. package/dist/lib/wtlink/main-menu.test.d.ts +0 -5
  409. package/dist/lib/wtlink/main-menu.test.d.ts.map +0 -1
  410. package/dist/lib/wtlink/main-menu.test.js +0 -126
  411. package/dist/lib/wtlink/main-menu.test.js.map +0 -1
  412. package/dist/lib/wtlink/manage-manifest.test.d.ts +0 -2
  413. package/dist/lib/wtlink/manage-manifest.test.d.ts.map +0 -1
  414. package/dist/lib/wtlink/manage-manifest.test.js +0 -714
  415. package/dist/lib/wtlink/manage-manifest.test.js.map +0 -1
  416. package/dist/lib/wtlink/validate-manifest.test.d.ts +0 -2
  417. package/dist/lib/wtlink/validate-manifest.test.d.ts.map +0 -1
  418. package/dist/lib/wtlink/validate-manifest.test.js +0 -220
  419. package/dist/lib/wtlink/validate-manifest.test.js.map +0 -1
  420. package/dist/lib/wtstate/analyze.test.d.ts +0 -5
  421. package/dist/lib/wtstate/analyze.test.d.ts.map +0 -1
  422. package/dist/lib/wtstate/analyze.test.js +0 -282
  423. package/dist/lib/wtstate/analyze.test.js.map +0 -1
  424. package/dist/lib/wtstate/args.test.d.ts +0 -5
  425. package/dist/lib/wtstate/args.test.d.ts.map +0 -1
  426. package/dist/lib/wtstate/args.test.js +0 -120
  427. package/dist/lib/wtstate/args.test.js.map +0 -1
  428. package/dist/mcp/server.test.d.ts +0 -9
  429. package/dist/mcp/server.test.d.ts.map +0 -1
  430. package/dist/mcp/server.test.js +0 -550
  431. package/dist/mcp/server.test.js.map +0 -1
@@ -1,624 +0,0 @@
1
- /**
2
- * Tests for wt clean command handler
3
- *
4
- * Exercises the handler through different code paths to cover internal
5
- * helper functions: outputJsonResult, outputJsonError, resultToCleanedInfo, printWorktree.
6
- */
7
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
8
- // Mock all dependencies before imports
9
- vi.mock('child_process', () => ({
10
- execSync: vi.fn(),
11
- }));
12
- vi.mock('../../lib/git.js', () => ({
13
- getRepoRoot: vi.fn().mockReturnValue('/fake/repo'),
14
- getMainWorktreeRoot: vi.fn().mockReturnValue('/fake/repo'),
15
- removeWorktree: vi.fn(),
16
- pruneWorktrees: vi.fn(),
17
- }));
18
- vi.mock('../../lib/github.js', () => ({
19
- isGhInstalled: vi.fn().mockReturnValue(true),
20
- }));
21
- vi.mock('../../lib/prompts.js', () => ({
22
- withSpinner: vi.fn((_msg, fn) => fn()),
23
- promptChoice: vi.fn(),
24
- promptConfirm: vi.fn(),
25
- }));
26
- vi.mock('../../lib/config.js', () => ({
27
- loadConfig: vi.fn().mockReturnValue({
28
- worktreePattern: '{repo}.pr{number}',
29
- baseBranch: 'main',
30
- }),
31
- }));
32
- vi.mock('../../lib/logger.js', () => ({
33
- logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
34
- }));
35
- vi.mock('../../lib/colors.js', () => ({
36
- error: vi.fn((s) => s),
37
- dim: vi.fn((s) => s),
38
- success: vi.fn((s) => s),
39
- info: vi.fn((s) => s),
40
- cyan: vi.fn((s) => s),
41
- yellow: vi.fn((s) => s),
42
- red: vi.fn((s) => s),
43
- green: vi.fn((s) => s),
44
- bold: vi.fn((s) => s),
45
- warning: vi.fn((s) => s),
46
- }));
47
- vi.mock('../../lib/cleanpr/index.js', () => ({
48
- gatherPrWorktreeInfo: vi.fn().mockResolvedValue([]),
49
- createDefaultDeps: vi.fn().mockReturnValue({}),
50
- groupWorktreesByState: vi.fn().mockReturnValue({ merged: [], closed: [], open: [], unknown: [] }),
51
- getCleanableWorktrees: vi.fn().mockReturnValue([]),
52
- findWorktreeByPrNumber: vi.fn().mockReturnValue(null),
53
- cleanWorktree: vi.fn().mockReturnValue({
54
- success: true,
55
- prNumber: 42,
56
- message: 'Cleaned PR #42',
57
- localBranchDeleted: true,
58
- remoteBranchDeleted: false,
59
- }),
60
- summarizeResults: vi.fn().mockReturnValue({ cleaned: 0, total: 0, failed: 0 }),
61
- }));
62
- vi.mock('../../lib/ui/index.js', () => ({
63
- setJsonMode: vi.fn(),
64
- isJsonMode: vi.fn().mockReturnValue(false),
65
- printStatus: vi.fn(),
66
- printDim: vi.fn(),
67
- printError: vi.fn(),
68
- printHeader: vi.fn(),
69
- printNextSteps: vi.fn(),
70
- changeIndicator: vi.fn().mockReturnValue(''),
71
- errorToDisplay: vi.fn().mockReturnValue({ title: 'error' }),
72
- }));
73
- vi.mock('../../lib/json-output.js', async (importOriginal) => {
74
- const actual = await importOriginal();
75
- return {
76
- ...actual,
77
- createSuccessResult: vi.fn().mockReturnValue({ success: true }),
78
- createErrorResult: vi.fn().mockReturnValue({ success: false }),
79
- formatJsonResult: vi.fn().mockReturnValue('{}'),
80
- };
81
- });
82
- // Import the command under test
83
- import { cleanCommand } from './clean.js';
84
- // Import mocked modules for assertions and setup
85
- import * as git from '../../lib/git.js';
86
- import * as github from '../../lib/github.js';
87
- import { gatherPrWorktreeInfo, getCleanableWorktrees, findWorktreeByPrNumber, cleanWorktree, summarizeResults, groupWorktreesByState, } from '../../lib/cleanpr/index.js';
88
- import { setJsonMode, printError, printStatus, printDim, printNextSteps, changeIndicator, } from '../../lib/ui/index.js';
89
- import { createSuccessResult, createErrorResult, formatJsonResult, ErrorCode, } from '../../lib/json-output.js';
90
- // Mock process.exit - throws to halt execution (mimics real exit behavior)
91
- class ExitError extends Error {
92
- code;
93
- constructor(code) {
94
- super(`process.exit(${code})`);
95
- this.code = code;
96
- }
97
- }
98
- const mockExit = vi.spyOn(process, 'exit').mockImplementation((code) => {
99
- throw new ExitError(code);
100
- });
101
- // Capture console.log output for JSON assertions
102
- const mockConsoleLog = vi.spyOn(console, 'log').mockImplementation(() => { });
103
- function makeWorktree(overrides = {}) {
104
- return {
105
- path: '/fake/repo.pr42',
106
- branch: 'feat/thing',
107
- commit: 'abc1234',
108
- prNumber: 42,
109
- prState: 'MERGED',
110
- hasChanges: false,
111
- ...overrides,
112
- };
113
- }
114
- function makeCleanupResult(overrides = {}) {
115
- return {
116
- success: true,
117
- prNumber: 42,
118
- message: 'Cleaned PR #42',
119
- localBranchDeleted: true,
120
- remoteBranchDeleted: false,
121
- ...overrides,
122
- };
123
- }
124
- describe('wt clean handler', () => {
125
- beforeEach(() => {
126
- vi.clearAllMocks();
127
- // Restore default mock return values
128
- vi.mocked(git.getRepoRoot).mockReturnValue('/fake/repo');
129
- vi.mocked(github.isGhInstalled).mockReturnValue(true);
130
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
131
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
132
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(undefined);
133
- vi.mocked(changeIndicator).mockReturnValue('');
134
- });
135
- afterEach(() => {
136
- mockExit.mockClear();
137
- mockConsoleLog.mockClear();
138
- });
139
- // =========================================================================
140
- // Error paths with JSON output
141
- // =========================================================================
142
- describe('prerequisite errors with --json', () => {
143
- it('outputs JSON error when gh is not installed', async () => {
144
- vi.mocked(github.isGhInstalled).mockReturnValue(false);
145
- await expect(cleanCommand.handler({
146
- all: true,
147
- 'dry-run': false,
148
- force: false,
149
- json: true,
150
- })).rejects.toThrow(ExitError);
151
- expect(setJsonMode).toHaveBeenCalledWith(true);
152
- expect(createErrorResult).toHaveBeenCalledWith('cleanpr', ErrorCode.GH_NOT_INSTALLED, expect.stringContaining('GitHub CLI'));
153
- expect(formatJsonResult).toHaveBeenCalled();
154
- expect(mockConsoleLog).toHaveBeenCalledWith('{}');
155
- expect(mockExit).toHaveBeenCalledWith(1);
156
- });
157
- it('outputs JSON error when not in a git repo', async () => {
158
- vi.mocked(git.getRepoRoot).mockReturnValue(null);
159
- await expect(cleanCommand.handler({
160
- all: true,
161
- 'dry-run': false,
162
- force: false,
163
- json: true,
164
- })).rejects.toThrow(ExitError);
165
- expect(createErrorResult).toHaveBeenCalledWith('cleanpr', ErrorCode.NOT_GIT_REPO, expect.stringContaining('git repository'));
166
- expect(formatJsonResult).toHaveBeenCalled();
167
- expect(mockExit).toHaveBeenCalledWith(1);
168
- });
169
- });
170
- // =========================================================================
171
- // --all --json: no worktrees found
172
- // =========================================================================
173
- describe('--all --json with no worktrees', () => {
174
- it('outputs JSON success with zero cleaned message', async () => {
175
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
176
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
177
- await cleanCommand.handler({
178
- all: true,
179
- 'dry-run': false,
180
- force: false,
181
- json: true,
182
- });
183
- // cleanAll path: no cleanable worktrees, json mode -> outputs success JSON directly
184
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
185
- totalCleaned: 0,
186
- totalSkipped: 0,
187
- message: expect.stringContaining('No merged or closed'),
188
- }));
189
- expect(formatJsonResult).toHaveBeenCalled();
190
- expect(mockConsoleLog).toHaveBeenCalledWith('{}');
191
- });
192
- });
193
- // =========================================================================
194
- // --all --json: cleanable worktrees found (exercises outputJsonResult non-dry-run)
195
- // =========================================================================
196
- describe('--all --json with cleanable worktrees', () => {
197
- it('outputs JSON result with cleaned worktrees', async () => {
198
- const wt1 = makeWorktree({
199
- prNumber: 10,
200
- branch: 'feat/a',
201
- path: '/fake/repo.pr10',
202
- prState: 'MERGED',
203
- });
204
- const wt2 = makeWorktree({
205
- prNumber: 20,
206
- branch: 'feat/b',
207
- path: '/fake/repo.pr20',
208
- prState: 'CLOSED',
209
- });
210
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1, wt2]);
211
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1, wt2]);
212
- vi.mocked(cleanWorktree)
213
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 10, message: 'Cleaned PR #10' }))
214
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 20, message: 'Cleaned PR #20' }));
215
- await cleanCommand.handler({
216
- all: true,
217
- 'dry-run': false,
218
- force: false,
219
- json: true,
220
- });
221
- // outputJsonResult called for non-dry-run path
222
- expect(cleanWorktree).toHaveBeenCalledTimes(2);
223
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
224
- totalCleaned: 2,
225
- totalSkipped: 0,
226
- }));
227
- // printStatus should NOT be called in json mode
228
- expect(printStatus).not.toHaveBeenCalled();
229
- });
230
- it('includes skipped entries for failed cleanups', async () => {
231
- const wt1 = makeWorktree({ prNumber: 10, path: '/fake/repo.pr10' });
232
- const wt2 = makeWorktree({ prNumber: 20, path: '/fake/repo.pr20' });
233
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1, wt2]);
234
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1, wt2]);
235
- vi.mocked(cleanWorktree)
236
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 10, success: true }))
237
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 20, success: false, message: 'Has uncommitted changes' }));
238
- await cleanCommand.handler({
239
- all: true,
240
- 'dry-run': false,
241
- force: false,
242
- json: true,
243
- });
244
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
245
- totalCleaned: 1,
246
- totalSkipped: 1,
247
- }));
248
- });
249
- });
250
- // =========================================================================
251
- // --all --json --dry-run: exercises outputJsonResult dry-run branch
252
- // =========================================================================
253
- describe('--all --json --dry-run with cleanable worktrees', () => {
254
- it('outputs dry-run JSON with wouldClean entries', async () => {
255
- const wt1 = makeWorktree({
256
- prNumber: 10,
257
- branch: 'feat/a',
258
- path: '/fake/repo.pr10',
259
- prState: 'MERGED',
260
- });
261
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1]);
262
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1]);
263
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 10, success: true, dryRun: true }));
264
- await cleanCommand.handler({
265
- all: true,
266
- 'dry-run': true,
267
- force: false,
268
- json: true,
269
- });
270
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
271
- wouldClean: expect.arrayContaining([
272
- expect.objectContaining({ prNumber: 10, branch: 'feat/a' }),
273
- ]),
274
- totalWouldClean: 1,
275
- message: expect.stringContaining('Would clean 1 PR worktree'),
276
- }));
277
- });
278
- it('outputs dry-run JSON with zero wouldClean when all fail', async () => {
279
- const wt1 = makeWorktree({ prNumber: 10, path: '/fake/repo.pr10' });
280
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1]);
281
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1]);
282
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 10, success: false, message: 'Failed' }));
283
- await cleanCommand.handler({
284
- all: true,
285
- 'dry-run': true,
286
- force: false,
287
- json: true,
288
- });
289
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
290
- wouldClean: [],
291
- totalWouldClean: 0,
292
- message: expect.stringContaining('No PR worktrees would be cleaned'),
293
- }));
294
- });
295
- });
296
- // =========================================================================
297
- // Specific PR number path (cleanSpecific)
298
- // =========================================================================
299
- describe('specific PR number', () => {
300
- it('cleans specific PR and outputs JSON result', async () => {
301
- const wt = makeWorktree({ prNumber: 42, branch: 'feat/thing', path: '/fake/repo.pr42' });
302
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
303
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(wt);
304
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 42 }));
305
- await cleanCommand.handler({
306
- prNumber: 42,
307
- all: false,
308
- 'dry-run': false,
309
- force: false,
310
- json: true,
311
- });
312
- expect(findWorktreeByPrNumber).toHaveBeenCalled();
313
- expect(cleanWorktree).toHaveBeenCalledTimes(1);
314
- // JSON output via outputJsonResult
315
- expect(createSuccessResult).toHaveBeenCalledWith('cleanpr', expect.objectContaining({
316
- totalCleaned: 1,
317
- }));
318
- });
319
- it('outputs JSON error when specific PR not found', async () => {
320
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
321
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(undefined);
322
- await expect(cleanCommand.handler({
323
- prNumber: 999,
324
- all: false,
325
- 'dry-run': false,
326
- force: false,
327
- json: true,
328
- })).rejects.toThrow(ExitError);
329
- // outputJsonError path
330
- expect(createErrorResult).toHaveBeenCalledWith('cleanpr', ErrorCode.PR_NOT_FOUND, expect.stringContaining('No worktree found for PR #999'));
331
- expect(mockExit).toHaveBeenCalledWith(1);
332
- });
333
- it('prints error display when specific PR not found without --json', async () => {
334
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
335
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(undefined);
336
- await expect(cleanCommand.handler({
337
- prNumber: 999,
338
- all: false,
339
- 'dry-run': false,
340
- force: false,
341
- json: false,
342
- })).rejects.toThrow(ExitError);
343
- expect(printError).toHaveBeenCalledWith(expect.objectContaining({
344
- title: expect.stringContaining('No worktree found for PR #999'),
345
- }));
346
- expect(mockExit).toHaveBeenCalledWith(1);
347
- });
348
- it('prints success status for non-json specific PR cleanup', async () => {
349
- const wt = makeWorktree({ prNumber: 42 });
350
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
351
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(wt);
352
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 42, success: true }));
353
- await cleanCommand.handler({
354
- prNumber: 42,
355
- all: false,
356
- 'dry-run': false,
357
- force: false,
358
- json: false,
359
- });
360
- expect(printStatus).toHaveBeenCalledWith('info', expect.stringContaining('Cleaning PR #42'));
361
- expect(printDim).toHaveBeenCalled();
362
- expect(printStatus).toHaveBeenCalledWith('success', expect.stringContaining('PR #42 worktree cleaned up successfully'));
363
- expect(printNextSteps).toHaveBeenCalled();
364
- });
365
- it('prints dry-run info status for specific PR', async () => {
366
- const wt = makeWorktree({ prNumber: 42 });
367
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
368
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(wt);
369
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 42, success: true, message: 'Would clean PR #42' }));
370
- await cleanCommand.handler({
371
- prNumber: 42,
372
- all: false,
373
- 'dry-run': true,
374
- force: false,
375
- json: false,
376
- });
377
- expect(printStatus).toHaveBeenCalledWith('info', expect.stringContaining('Would clean'));
378
- });
379
- it('prints warning and exits 1 on failed specific PR cleanup', async () => {
380
- const wt = makeWorktree({ prNumber: 42 });
381
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
382
- vi.mocked(findWorktreeByPrNumber).mockReturnValue(wt);
383
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 42, success: false, message: 'Has uncommitted changes' }));
384
- await expect(cleanCommand.handler({
385
- prNumber: 42,
386
- all: false,
387
- 'dry-run': false,
388
- force: false,
389
- json: false,
390
- })).rejects.toThrow(ExitError);
391
- expect(printStatus).toHaveBeenCalledWith('warning', 'Has uncommitted changes');
392
- expect(mockExit).toHaveBeenCalledWith(1);
393
- });
394
- });
395
- // =========================================================================
396
- // --all without --json: text output paths
397
- // =========================================================================
398
- describe('--all without --json (text output)', () => {
399
- it('prints info when no cleanable worktrees found', async () => {
400
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
401
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
402
- await cleanCommand.handler({
403
- all: true,
404
- 'dry-run': false,
405
- force: false,
406
- json: false,
407
- });
408
- expect(printStatus).toHaveBeenCalledWith('info', expect.stringContaining('No merged or closed'));
409
- });
410
- it('prints success/warning per worktree and summary', async () => {
411
- const wt1 = makeWorktree({ prNumber: 10 });
412
- const wt2 = makeWorktree({ prNumber: 20 });
413
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1, wt2]);
414
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1, wt2]);
415
- vi.mocked(cleanWorktree)
416
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 10, success: true, message: 'Cleaned #10' }))
417
- .mockReturnValueOnce(makeCleanupResult({ prNumber: 20, success: false, message: 'Failed #20' }));
418
- vi.mocked(summarizeResults).mockReturnValue({ cleaned: 1, total: 2, failed: 1 });
419
- await cleanCommand.handler({
420
- all: true,
421
- 'dry-run': false,
422
- force: false,
423
- json: false,
424
- });
425
- expect(printStatus).toHaveBeenCalledWith('success', 'Cleaned #10');
426
- expect(printStatus).toHaveBeenCalledWith('warning', 'Failed #20');
427
- expect(printStatus).toHaveBeenCalledWith('success', expect.stringContaining('Cleaned 1 of 2'));
428
- });
429
- it('prints dry-run summary for text output', async () => {
430
- const wt1 = makeWorktree({ prNumber: 10 });
431
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1]);
432
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1]);
433
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 10, success: true, message: 'Would clean' }));
434
- vi.mocked(summarizeResults).mockReturnValue({ cleaned: 1, total: 1, failed: 0 });
435
- await cleanCommand.handler({
436
- all: true,
437
- 'dry-run': true,
438
- force: false,
439
- json: false,
440
- });
441
- expect(printStatus).toHaveBeenCalledWith('info', expect.stringContaining('Would clean 1 of 1'));
442
- });
443
- it('shows next steps when worktrees were cleaned', async () => {
444
- const wt1 = makeWorktree({ prNumber: 10 });
445
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt1]);
446
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt1]);
447
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult({ prNumber: 10, success: true }));
448
- vi.mocked(summarizeResults).mockReturnValue({ cleaned: 1, total: 1, failed: 0 });
449
- await cleanCommand.handler({
450
- all: true,
451
- 'dry-run': false,
452
- force: false,
453
- json: false,
454
- });
455
- expect(printNextSteps).toHaveBeenCalled();
456
- });
457
- });
458
- // =========================================================================
459
- // Interactive mode with --json (not supported)
460
- // =========================================================================
461
- describe('interactive mode with --json', () => {
462
- it('outputs JSON error for interactive + json combination', async () => {
463
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
464
- await expect(cleanCommand.handler({
465
- all: false,
466
- 'dry-run': false,
467
- force: false,
468
- json: true,
469
- // prNumber is undefined -> interactive mode
470
- })).rejects.toThrow(ExitError);
471
- expect(createErrorResult).toHaveBeenCalledWith('cleanpr', ErrorCode.INVALID_ARGUMENT, expect.stringContaining('Interactive mode not supported'));
472
- expect(mockExit).toHaveBeenCalledWith(1);
473
- });
474
- });
475
- // =========================================================================
476
- // printWorktree coverage (via interactiveClean path)
477
- // =========================================================================
478
- describe('interactive mode (non-json)', () => {
479
- it('prints grouped worktrees and shows no-cleanable message', async () => {
480
- const openWt = makeWorktree({ prNumber: 10, prState: 'OPEN', branch: 'feat/open' });
481
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([openWt]);
482
- vi.mocked(groupWorktreesByState).mockReturnValue({
483
- merged: [],
484
- closed: [],
485
- open: [openWt],
486
- unknown: [],
487
- });
488
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
489
- await cleanCommand.handler({
490
- all: false,
491
- 'dry-run': false,
492
- force: false,
493
- json: false,
494
- });
495
- // printWorktree is called for open worktrees
496
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #10: feat/open'));
497
- expect(printStatus).toHaveBeenCalledWith('info', expect.stringContaining('No merged or closed PRs to clean'));
498
- });
499
- it('prints all four groups when all states present', async () => {
500
- const merged = makeWorktree({ prNumber: 1, prState: 'MERGED', branch: 'feat/merged' });
501
- const closed = makeWorktree({ prNumber: 2, prState: 'CLOSED', branch: 'feat/closed' });
502
- const open = makeWorktree({ prNumber: 3, prState: 'OPEN', branch: 'feat/open' });
503
- const unknown = makeWorktree({ prNumber: 4, prState: 'UNKNOWN', branch: 'feat/unknown' });
504
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([merged, closed, open, unknown]);
505
- vi.mocked(groupWorktreesByState).mockReturnValue({
506
- merged: [merged],
507
- closed: [closed],
508
- open: [open],
509
- unknown: [unknown],
510
- });
511
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
512
- await cleanCommand.handler({
513
- all: false,
514
- 'dry-run': false,
515
- force: false,
516
- json: false,
517
- });
518
- // Each group header is printed
519
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('Merged (1)'));
520
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('Closed (1)'));
521
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('Open (1)'));
522
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('Unknown (1)'));
523
- // printWorktree called for each
524
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #1: feat/merged'));
525
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #2: feat/closed'));
526
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #3: feat/open'));
527
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #4: feat/unknown'));
528
- });
529
- it('prints "No PR worktrees found" when list is empty', async () => {
530
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([]);
531
- await cleanCommand.handler({
532
- all: false,
533
- 'dry-run': false,
534
- force: false,
535
- json: false,
536
- });
537
- expect(printStatus).toHaveBeenCalledWith('info', 'No PR worktrees found.');
538
- });
539
- });
540
- // =========================================================================
541
- // printWorktree with changes indicator
542
- // =========================================================================
543
- describe('printWorktree with changes', () => {
544
- it('includes change indicator in output', async () => {
545
- const wt = makeWorktree({ prNumber: 55, branch: 'feat/dirty', hasChanges: true });
546
- vi.mocked(changeIndicator).mockReturnValue(' [modified]');
547
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
548
- vi.mocked(groupWorktreesByState).mockReturnValue({
549
- merged: [wt],
550
- closed: [],
551
- open: [],
552
- unknown: [],
553
- });
554
- vi.mocked(getCleanableWorktrees).mockReturnValue([]);
555
- await cleanCommand.handler({
556
- all: false,
557
- 'dry-run': false,
558
- force: false,
559
- json: false,
560
- });
561
- expect(changeIndicator).toHaveBeenCalledWith(true);
562
- expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('PR #55: feat/dirty [modified]'));
563
- });
564
- });
565
- // =========================================================================
566
- // Options mapping
567
- // =========================================================================
568
- describe('options mapping', () => {
569
- it('maps --delete-remote to options.deleteRemote', async () => {
570
- const wt = makeWorktree({ prNumber: 42 });
571
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
572
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt]);
573
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult());
574
- await cleanCommand.handler({
575
- all: true,
576
- 'dry-run': false,
577
- force: false,
578
- 'delete-remote': true,
579
- json: false,
580
- });
581
- expect(cleanWorktree).toHaveBeenCalledWith(wt, expect.objectContaining({ deleteRemote: true }), expect.any(Object));
582
- });
583
- it('maps --force to options.force', async () => {
584
- const wt = makeWorktree({ prNumber: 42 });
585
- vi.mocked(gatherPrWorktreeInfo).mockResolvedValue([wt]);
586
- vi.mocked(getCleanableWorktrees).mockReturnValue([wt]);
587
- vi.mocked(cleanWorktree).mockReturnValue(makeCleanupResult());
588
- await cleanCommand.handler({
589
- all: true,
590
- 'dry-run': false,
591
- force: true,
592
- json: false,
593
- });
594
- expect(cleanWorktree).toHaveBeenCalledWith(wt, expect.objectContaining({ force: true }), expect.any(Object));
595
- });
596
- });
597
- // =========================================================================
598
- // JSON mode skips spinner
599
- // =========================================================================
600
- describe('spinner behavior', () => {
601
- it('skips spinner in json mode and calls gatherPrWorktreeInfo directly', async () => {
602
- const { withSpinner } = await import('../../lib/prompts.js');
603
- await cleanCommand.handler({
604
- all: true,
605
- 'dry-run': false,
606
- force: false,
607
- json: true,
608
- });
609
- expect(withSpinner).not.toHaveBeenCalled();
610
- expect(gatherPrWorktreeInfo).toHaveBeenCalled();
611
- });
612
- it('uses spinner in non-json mode', async () => {
613
- const { withSpinner } = await import('../../lib/prompts.js');
614
- await cleanCommand.handler({
615
- all: true,
616
- 'dry-run': false,
617
- force: false,
618
- json: false,
619
- });
620
- expect(withSpinner).toHaveBeenCalledWith('Scanning worktrees...', expect.any(Function));
621
- });
622
- });
623
- });
624
- //# sourceMappingURL=clean.test.js.map