@camaradesuk/git-worktree-tools 1.10.0 → 1.11.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 (426) hide show
  1. package/README.md +4 -4
  2. package/package.json +12 -3
  3. package/dist/api/list.test.d.ts +0 -5
  4. package/dist/api/list.test.d.ts.map +0 -1
  5. package/dist/api/list.test.js +0 -390
  6. package/dist/api/list.test.js.map +0 -1
  7. package/dist/cli/cleanpr.test.d.ts +0 -2
  8. package/dist/cli/cleanpr.test.d.ts.map +0 -1
  9. package/dist/cli/cleanpr.test.js +0 -954
  10. package/dist/cli/cleanpr.test.js.map +0 -1
  11. package/dist/cli/lswt.test.d.ts +0 -2
  12. package/dist/cli/lswt.test.d.ts.map +0 -1
  13. package/dist/cli/lswt.test.js +0 -376
  14. package/dist/cli/lswt.test.js.map +0 -1
  15. package/dist/cli/newpr.test.d.ts +0 -2
  16. package/dist/cli/newpr.test.d.ts.map +0 -1
  17. package/dist/cli/newpr.test.js +0 -1182
  18. package/dist/cli/newpr.test.js.map +0 -1
  19. package/dist/cli/prs.test.d.ts +0 -8
  20. package/dist/cli/prs.test.d.ts.map +0 -1
  21. package/dist/cli/prs.test.js +0 -463
  22. package/dist/cli/prs.test.js.map +0 -1
  23. package/dist/cli/wt/clean.test.d.ts +0 -8
  24. package/dist/cli/wt/clean.test.d.ts.map +0 -1
  25. package/dist/cli/wt/clean.test.js +0 -624
  26. package/dist/cli/wt/clean.test.js.map +0 -1
  27. package/dist/cli/wt/completion.test.d.ts +0 -5
  28. package/dist/cli/wt/completion.test.d.ts.map +0 -1
  29. package/dist/cli/wt/completion.test.js +0 -275
  30. package/dist/cli/wt/completion.test.js.map +0 -1
  31. package/dist/cli/wt/config.test.d.ts +0 -7
  32. package/dist/cli/wt/config.test.d.ts.map +0 -1
  33. package/dist/cli/wt/config.test.js +0 -440
  34. package/dist/cli/wt/config.test.js.map +0 -1
  35. package/dist/cli/wt/entry.test.d.ts +0 -8
  36. package/dist/cli/wt/entry.test.d.ts.map +0 -1
  37. package/dist/cli/wt/entry.test.js +0 -201
  38. package/dist/cli/wt/entry.test.js.map +0 -1
  39. package/dist/cli/wt/init.test.d.ts +0 -5
  40. package/dist/cli/wt/init.test.d.ts.map +0 -1
  41. package/dist/cli/wt/init.test.js +0 -165
  42. package/dist/cli/wt/init.test.js.map +0 -1
  43. package/dist/cli/wt/init.unit.test.d.ts +0 -5
  44. package/dist/cli/wt/init.unit.test.d.ts.map +0 -1
  45. package/dist/cli/wt/init.unit.test.js +0 -432
  46. package/dist/cli/wt/init.unit.test.js.map +0 -1
  47. package/dist/cli/wt/interactive-menu.test.d.ts +0 -12
  48. package/dist/cli/wt/interactive-menu.test.d.ts.map +0 -1
  49. package/dist/cli/wt/interactive-menu.test.js +0 -796
  50. package/dist/cli/wt/interactive-menu.test.js.map +0 -1
  51. package/dist/cli/wt/list.test.d.ts +0 -10
  52. package/dist/cli/wt/list.test.d.ts.map +0 -1
  53. package/dist/cli/wt/list.test.js +0 -157
  54. package/dist/cli/wt/list.test.js.map +0 -1
  55. package/dist/cli/wt/prs.test.d.ts +0 -5
  56. package/dist/cli/wt/prs.test.d.ts.map +0 -1
  57. package/dist/cli/wt/prs.test.js +0 -410
  58. package/dist/cli/wt/prs.test.js.map +0 -1
  59. package/dist/cli/wt/run-command.test.d.ts +0 -5
  60. package/dist/cli/wt/run-command.test.d.ts.map +0 -1
  61. package/dist/cli/wt/run-command.test.js +0 -88
  62. package/dist/cli/wt/run-command.test.js.map +0 -1
  63. package/dist/cli/wt/state.test.d.ts +0 -9
  64. package/dist/cli/wt/state.test.d.ts.map +0 -1
  65. package/dist/cli/wt/state.test.js +0 -127
  66. package/dist/cli/wt/state.test.js.map +0 -1
  67. package/dist/cli/wt/wt.test.d.ts +0 -8
  68. package/dist/cli/wt/wt.test.d.ts.map +0 -1
  69. package/dist/cli/wt/wt.test.js +0 -739
  70. package/dist/cli/wt/wt.test.js.map +0 -1
  71. package/dist/cli/wt.unit.test.d.ts +0 -7
  72. package/dist/cli/wt.unit.test.d.ts.map +0 -1
  73. package/dist/cli/wt.unit.test.js +0 -160
  74. package/dist/cli/wt.unit.test.js.map +0 -1
  75. package/dist/cli/wtconfig.test.d.ts +0 -5
  76. package/dist/cli/wtconfig.test.d.ts.map +0 -1
  77. package/dist/cli/wtconfig.test.js +0 -1289
  78. package/dist/cli/wtconfig.test.js.map +0 -1
  79. package/dist/cli/wtlink.test.d.ts +0 -2
  80. package/dist/cli/wtlink.test.d.ts.map +0 -1
  81. package/dist/cli/wtlink.test.js +0 -249
  82. package/dist/cli/wtlink.test.js.map +0 -1
  83. package/dist/cli/wtstate.test.d.ts +0 -5
  84. package/dist/cli/wtstate.test.d.ts.map +0 -1
  85. package/dist/cli/wtstate.test.js +0 -193
  86. package/dist/cli/wtstate.test.js.map +0 -1
  87. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts +0 -2
  88. package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts.map +0 -1
  89. package/dist/e2e/cleanpr/cleanpr.e2e.test.js +0 -326
  90. package/dist/e2e/cleanpr/cleanpr.e2e.test.js.map +0 -1
  91. package/dist/e2e/cli.e2e.test.d.ts +0 -2
  92. package/dist/e2e/cli.e2e.test.d.ts.map +0 -1
  93. package/dist/e2e/cli.e2e.test.js +0 -417
  94. package/dist/e2e/cli.e2e.test.js.map +0 -1
  95. package/dist/e2e/lswt/lswt.e2e.test.d.ts +0 -2
  96. package/dist/e2e/lswt/lswt.e2e.test.d.ts.map +0 -1
  97. package/dist/e2e/lswt/lswt.e2e.test.js +0 -361
  98. package/dist/e2e/lswt/lswt.e2e.test.js.map +0 -1
  99. package/dist/e2e/newpr/newpr.e2e.test.d.ts +0 -2
  100. package/dist/e2e/newpr/newpr.e2e.test.d.ts.map +0 -1
  101. package/dist/e2e/newpr/newpr.e2e.test.js +0 -286
  102. package/dist/e2e/newpr/newpr.e2e.test.js.map +0 -1
  103. package/dist/e2e/newpr/scenarios.e2e.test.d.ts +0 -2
  104. package/dist/e2e/newpr/scenarios.e2e.test.d.ts.map +0 -1
  105. package/dist/e2e/newpr/scenarios.e2e.test.js +0 -426
  106. package/dist/e2e/newpr/scenarios.e2e.test.js.map +0 -1
  107. package/dist/e2e/newpr-full-flow.e2e.test.d.ts +0 -2
  108. package/dist/e2e/newpr-full-flow.e2e.test.d.ts.map +0 -1
  109. package/dist/e2e/newpr-full-flow.e2e.test.js +0 -280
  110. package/dist/e2e/newpr-full-flow.e2e.test.js.map +0 -1
  111. package/dist/e2e/prs/prs.e2e.test.d.ts +0 -7
  112. package/dist/e2e/prs/prs.e2e.test.d.ts.map +0 -1
  113. package/dist/e2e/prs/prs.e2e.test.js +0 -606
  114. package/dist/e2e/prs/prs.e2e.test.js.map +0 -1
  115. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts +0 -2
  116. package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts.map +0 -1
  117. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js +0 -298
  118. package/dist/e2e/workflows/pr-lifecycle.e2e.test.js.map +0 -1
  119. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts +0 -8
  120. package/dist/e2e/wt/interactive-menu.e2e.test.d.ts.map +0 -1
  121. package/dist/e2e/wt/interactive-menu.e2e.test.js +0 -583
  122. package/dist/e2e/wt/interactive-menu.e2e.test.js.map +0 -1
  123. package/dist/e2e/wt/wt.e2e.test.d.ts +0 -9
  124. package/dist/e2e/wt/wt.e2e.test.d.ts.map +0 -1
  125. package/dist/e2e/wt/wt.e2e.test.js +0 -597
  126. package/dist/e2e/wt/wt.e2e.test.js.map +0 -1
  127. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts +0 -2
  128. package/dist/e2e/wtlink/wtlink.e2e.test.d.ts.map +0 -1
  129. package/dist/e2e/wtlink/wtlink.e2e.test.js +0 -416
  130. package/dist/e2e/wtlink/wtlink.e2e.test.js.map +0 -1
  131. package/dist/integration/git.integration.test.d.ts +0 -2
  132. package/dist/integration/git.integration.test.d.ts.map +0 -1
  133. package/dist/integration/git.integration.test.js +0 -336
  134. package/dist/integration/git.integration.test.js.map +0 -1
  135. package/dist/integration/lswt-remote-pr.integration.test.d.ts +0 -2
  136. package/dist/integration/lswt-remote-pr.integration.test.d.ts.map +0 -1
  137. package/dist/integration/lswt-remote-pr.integration.test.js +0 -222
  138. package/dist/integration/lswt-remote-pr.integration.test.js.map +0 -1
  139. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts +0 -2
  140. package/dist/integration/newpr-branchfrom-head.integration.test.d.ts.map +0 -1
  141. package/dist/integration/newpr-branchfrom-head.integration.test.js +0 -498
  142. package/dist/integration/newpr-branchfrom-head.integration.test.js.map +0 -1
  143. package/dist/integration/newpr.integration.test.d.ts +0 -2
  144. package/dist/integration/newpr.integration.test.d.ts.map +0 -1
  145. package/dist/integration/newpr.integration.test.js +0 -460
  146. package/dist/integration/newpr.integration.test.js.map +0 -1
  147. package/dist/integration/prs.integration.test.d.ts +0 -8
  148. package/dist/integration/prs.integration.test.d.ts.map +0 -1
  149. package/dist/integration/prs.integration.test.js +0 -478
  150. package/dist/integration/prs.integration.test.js.map +0 -1
  151. package/dist/lib/ai/base-provider.test.d.ts +0 -7
  152. package/dist/lib/ai/base-provider.test.d.ts.map +0 -1
  153. package/dist/lib/ai/base-provider.test.js +0 -319
  154. package/dist/lib/ai/base-provider.test.js.map +0 -1
  155. package/dist/lib/ai/cli-provider.test.d.ts +0 -5
  156. package/dist/lib/ai/cli-provider.test.d.ts.map +0 -1
  157. package/dist/lib/ai/cli-provider.test.js +0 -460
  158. package/dist/lib/ai/cli-provider.test.js.map +0 -1
  159. package/dist/lib/ai/fallback-provider.test.d.ts +0 -7
  160. package/dist/lib/ai/fallback-provider.test.d.ts.map +0 -1
  161. package/dist/lib/ai/fallback-provider.test.js +0 -165
  162. package/dist/lib/ai/fallback-provider.test.js.map +0 -1
  163. package/dist/lib/ai/generation-service.test.d.ts +0 -7
  164. package/dist/lib/ai/generation-service.test.d.ts.map +0 -1
  165. package/dist/lib/ai/generation-service.test.js +0 -213
  166. package/dist/lib/ai/generation-service.test.js.map +0 -1
  167. package/dist/lib/ai/provider-manager.test.d.ts +0 -5
  168. package/dist/lib/ai/provider-manager.test.d.ts.map +0 -1
  169. package/dist/lib/ai/provider-manager.test.js +0 -312
  170. package/dist/lib/ai/provider-manager.test.js.map +0 -1
  171. package/dist/lib/ai/repo-docs.test.d.ts +0 -5
  172. package/dist/lib/ai/repo-docs.test.d.ts.map +0 -1
  173. package/dist/lib/ai/repo-docs.test.js +0 -357
  174. package/dist/lib/ai/repo-docs.test.js.map +0 -1
  175. package/dist/lib/cleanpr/args.test.d.ts +0 -2
  176. package/dist/lib/cleanpr/args.test.d.ts.map +0 -1
  177. package/dist/lib/cleanpr/args.test.js +0 -269
  178. package/dist/lib/cleanpr/args.test.js.map +0 -1
  179. package/dist/lib/cleanpr/cleanup.test.d.ts +0 -2
  180. package/dist/lib/cleanpr/cleanup.test.d.ts.map +0 -1
  181. package/dist/lib/cleanpr/cleanup.test.js +0 -296
  182. package/dist/lib/cleanpr/cleanup.test.js.map +0 -1
  183. package/dist/lib/cleanpr/worktree-info.test.d.ts +0 -2
  184. package/dist/lib/cleanpr/worktree-info.test.d.ts.map +0 -1
  185. package/dist/lib/cleanpr/worktree-info.test.js +0 -228
  186. package/dist/lib/cleanpr/worktree-info.test.js.map +0 -1
  187. package/dist/lib/colors.test.d.ts +0 -2
  188. package/dist/lib/colors.test.d.ts.map +0 -1
  189. package/dist/lib/colors.test.js +0 -142
  190. package/dist/lib/colors.test.js.map +0 -1
  191. package/dist/lib/config-editor.test.d.ts +0 -11
  192. package/dist/lib/config-editor.test.d.ts.map +0 -1
  193. package/dist/lib/config-editor.test.js +0 -526
  194. package/dist/lib/config-editor.test.js.map +0 -1
  195. package/dist/lib/config-migration/detector.test.d.ts +0 -5
  196. package/dist/lib/config-migration/detector.test.d.ts.map +0 -1
  197. package/dist/lib/config-migration/detector.test.js +0 -201
  198. package/dist/lib/config-migration/detector.test.js.map +0 -1
  199. package/dist/lib/config-migration/reporter.test.d.ts +0 -5
  200. package/dist/lib/config-migration/reporter.test.d.ts.map +0 -1
  201. package/dist/lib/config-migration/reporter.test.js +0 -305
  202. package/dist/lib/config-migration/reporter.test.js.map +0 -1
  203. package/dist/lib/config-migration/runner.test.d.ts +0 -5
  204. package/dist/lib/config-migration/runner.test.d.ts.map +0 -1
  205. package/dist/lib/config-migration/runner.test.js +0 -235
  206. package/dist/lib/config-migration/runner.test.js.map +0 -1
  207. package/dist/lib/config-validation.test.d.ts +0 -5
  208. package/dist/lib/config-validation.test.d.ts.map +0 -1
  209. package/dist/lib/config-validation.test.js +0 -423
  210. package/dist/lib/config-validation.test.js.map +0 -1
  211. package/dist/lib/config.test.d.ts +0 -2
  212. package/dist/lib/config.test.d.ts.map +0 -1
  213. package/dist/lib/config.test.js +0 -554
  214. package/dist/lib/config.test.js.map +0 -1
  215. package/dist/lib/constants.test.d.ts +0 -5
  216. package/dist/lib/constants.test.d.ts.map +0 -1
  217. package/dist/lib/constants.test.js +0 -180
  218. package/dist/lib/constants.test.js.map +0 -1
  219. package/dist/lib/deprecation.test.d.ts +0 -2
  220. package/dist/lib/deprecation.test.d.ts.map +0 -1
  221. package/dist/lib/deprecation.test.js +0 -71
  222. package/dist/lib/deprecation.test.js.map +0 -1
  223. package/dist/lib/errors.test.d.ts +0 -2
  224. package/dist/lib/errors.test.d.ts.map +0 -1
  225. package/dist/lib/errors.test.js +0 -117
  226. package/dist/lib/errors.test.js.map +0 -1
  227. package/dist/lib/git.test.d.ts +0 -2
  228. package/dist/lib/git.test.d.ts.map +0 -1
  229. package/dist/lib/git.test.js +0 -608
  230. package/dist/lib/git.test.js.map +0 -1
  231. package/dist/lib/github.test.d.ts +0 -2
  232. package/dist/lib/github.test.d.ts.map +0 -1
  233. package/dist/lib/github.test.js +0 -441
  234. package/dist/lib/github.test.js.map +0 -1
  235. package/dist/lib/global-check.test.d.ts +0 -5
  236. package/dist/lib/global-check.test.d.ts.map +0 -1
  237. package/dist/lib/global-check.test.js +0 -150
  238. package/dist/lib/global-check.test.js.map +0 -1
  239. package/dist/lib/global-config.test.d.ts +0 -5
  240. package/dist/lib/global-config.test.d.ts.map +0 -1
  241. package/dist/lib/global-config.test.js +0 -282
  242. package/dist/lib/global-config.test.js.map +0 -1
  243. package/dist/lib/hooks/confirmation.test.d.ts +0 -7
  244. package/dist/lib/hooks/confirmation.test.d.ts.map +0 -1
  245. package/dist/lib/hooks/confirmation.test.js +0 -300
  246. package/dist/lib/hooks/confirmation.test.js.map +0 -1
  247. package/dist/lib/hooks/executor.test.d.ts +0 -5
  248. package/dist/lib/hooks/executor.test.d.ts.map +0 -1
  249. package/dist/lib/hooks/executor.test.js +0 -648
  250. package/dist/lib/hooks/executor.test.js.map +0 -1
  251. package/dist/lib/hooks/templates.test.d.ts +0 -5
  252. package/dist/lib/hooks/templates.test.d.ts.map +0 -1
  253. package/dist/lib/hooks/templates.test.js +0 -163
  254. package/dist/lib/hooks/templates.test.js.map +0 -1
  255. package/dist/lib/hooks/types.test.d.ts +0 -5
  256. package/dist/lib/hooks/types.test.d.ts.map +0 -1
  257. package/dist/lib/hooks/types.test.js +0 -132
  258. package/dist/lib/hooks/types.test.js.map +0 -1
  259. package/dist/lib/json-output.test.d.ts +0 -5
  260. package/dist/lib/json-output.test.d.ts.map +0 -1
  261. package/dist/lib/json-output.test.js +0 -261
  262. package/dist/lib/json-output.test.js.map +0 -1
  263. package/dist/lib/logger.test.d.ts +0 -14
  264. package/dist/lib/logger.test.d.ts.map +0 -1
  265. package/dist/lib/logger.test.js +0 -692
  266. package/dist/lib/logger.test.js.map +0 -1
  267. package/dist/lib/lswt/action-executors.test.d.ts +0 -2
  268. package/dist/lib/lswt/action-executors.test.d.ts.map +0 -1
  269. package/dist/lib/lswt/action-executors.test.js +0 -1127
  270. package/dist/lib/lswt/action-executors.test.js.map +0 -1
  271. package/dist/lib/lswt/actions.test.d.ts +0 -2
  272. package/dist/lib/lswt/actions.test.d.ts.map +0 -1
  273. package/dist/lib/lswt/actions.test.js +0 -497
  274. package/dist/lib/lswt/actions.test.js.map +0 -1
  275. package/dist/lib/lswt/args.test.d.ts +0 -2
  276. package/dist/lib/lswt/args.test.d.ts.map +0 -1
  277. package/dist/lib/lswt/args.test.js +0 -195
  278. package/dist/lib/lswt/args.test.js.map +0 -1
  279. package/dist/lib/lswt/environment.test.d.ts +0 -2
  280. package/dist/lib/lswt/environment.test.d.ts.map +0 -1
  281. package/dist/lib/lswt/environment.test.js +0 -544
  282. package/dist/lib/lswt/environment.test.js.map +0 -1
  283. package/dist/lib/lswt/formatters.test.d.ts +0 -2
  284. package/dist/lib/lswt/formatters.test.d.ts.map +0 -1
  285. package/dist/lib/lswt/formatters.test.js +0 -323
  286. package/dist/lib/lswt/formatters.test.js.map +0 -1
  287. package/dist/lib/lswt/fuzzy-search.test.d.ts +0 -5
  288. package/dist/lib/lswt/fuzzy-search.test.d.ts.map +0 -1
  289. package/dist/lib/lswt/fuzzy-search.test.js +0 -207
  290. package/dist/lib/lswt/fuzzy-search.test.js.map +0 -1
  291. package/dist/lib/lswt/interactive.test.d.ts +0 -2
  292. package/dist/lib/lswt/interactive.test.d.ts.map +0 -1
  293. package/dist/lib/lswt/interactive.test.js +0 -771
  294. package/dist/lib/lswt/interactive.test.js.map +0 -1
  295. package/dist/lib/lswt/table.test.d.ts +0 -5
  296. package/dist/lib/lswt/table.test.d.ts.map +0 -1
  297. package/dist/lib/lswt/table.test.js +0 -262
  298. package/dist/lib/lswt/table.test.js.map +0 -1
  299. package/dist/lib/lswt/worktree-info.test.d.ts +0 -2
  300. package/dist/lib/lswt/worktree-info.test.d.ts.map +0 -1
  301. package/dist/lib/lswt/worktree-info.test.js +0 -484
  302. package/dist/lib/lswt/worktree-info.test.js.map +0 -1
  303. package/dist/lib/newpr/action-deps.test.d.ts +0 -5
  304. package/dist/lib/newpr/action-deps.test.d.ts.map +0 -1
  305. package/dist/lib/newpr/action-deps.test.js +0 -111
  306. package/dist/lib/newpr/action-deps.test.js.map +0 -1
  307. package/dist/lib/newpr/actions.test.d.ts +0 -2
  308. package/dist/lib/newpr/actions.test.d.ts.map +0 -1
  309. package/dist/lib/newpr/actions.test.js +0 -254
  310. package/dist/lib/newpr/actions.test.js.map +0 -1
  311. package/dist/lib/newpr/args.test.d.ts +0 -2
  312. package/dist/lib/newpr/args.test.d.ts.map +0 -1
  313. package/dist/lib/newpr/args.test.js +0 -479
  314. package/dist/lib/newpr/args.test.js.map +0 -1
  315. package/dist/lib/newpr/hook-runner.test.d.ts +0 -7
  316. package/dist/lib/newpr/hook-runner.test.d.ts.map +0 -1
  317. package/dist/lib/newpr/hook-runner.test.js +0 -422
  318. package/dist/lib/newpr/hook-runner.test.js.map +0 -1
  319. package/dist/lib/newpr/plan-generator.test.d.ts +0 -7
  320. package/dist/lib/newpr/plan-generator.test.d.ts.map +0 -1
  321. package/dist/lib/newpr/plan-generator.test.js +0 -387
  322. package/dist/lib/newpr/plan-generator.test.js.map +0 -1
  323. package/dist/lib/newpr/scenario-handler.test.d.ts +0 -2
  324. package/dist/lib/newpr/scenario-handler.test.d.ts.map +0 -1
  325. package/dist/lib/newpr/scenario-handler.test.js +0 -256
  326. package/dist/lib/newpr/scenario-handler.test.js.map +0 -1
  327. package/dist/lib/prompts.test.d.ts +0 -2
  328. package/dist/lib/prompts.test.d.ts.map +0 -1
  329. package/dist/lib/prompts.test.js +0 -807
  330. package/dist/lib/prompts.test.js.map +0 -1
  331. package/dist/lib/prs/actions.test.d.ts +0 -5
  332. package/dist/lib/prs/actions.test.d.ts.map +0 -1
  333. package/dist/lib/prs/actions.test.js +0 -356
  334. package/dist/lib/prs/actions.test.js.map +0 -1
  335. package/dist/lib/prs/command.test.d.ts +0 -11
  336. package/dist/lib/prs/command.test.d.ts.map +0 -1
  337. package/dist/lib/prs/command.test.js +0 -409
  338. package/dist/lib/prs/command.test.js.map +0 -1
  339. package/dist/lib/prs/data.test.d.ts +0 -5
  340. package/dist/lib/prs/data.test.d.ts.map +0 -1
  341. package/dist/lib/prs/data.test.js +0 -417
  342. package/dist/lib/prs/data.test.js.map +0 -1
  343. package/dist/lib/prs/details.test.d.ts +0 -5
  344. package/dist/lib/prs/details.test.d.ts.map +0 -1
  345. package/dist/lib/prs/details.test.js +0 -325
  346. package/dist/lib/prs/details.test.js.map +0 -1
  347. package/dist/lib/prs/filters.test.d.ts +0 -5
  348. package/dist/lib/prs/filters.test.d.ts.map +0 -1
  349. package/dist/lib/prs/filters.test.js +0 -312
  350. package/dist/lib/prs/filters.test.js.map +0 -1
  351. package/dist/lib/prs/formatters.test.d.ts +0 -2
  352. package/dist/lib/prs/formatters.test.d.ts.map +0 -1
  353. package/dist/lib/prs/formatters.test.js +0 -387
  354. package/dist/lib/prs/formatters.test.js.map +0 -1
  355. package/dist/lib/prs/interactive.test.d.ts +0 -5
  356. package/dist/lib/prs/interactive.test.d.ts.map +0 -1
  357. package/dist/lib/prs/interactive.test.js +0 -517
  358. package/dist/lib/prs/interactive.test.js.map +0 -1
  359. package/dist/lib/schema.test.d.ts +0 -10
  360. package/dist/lib/schema.test.d.ts.map +0 -1
  361. package/dist/lib/schema.test.js +0 -309
  362. package/dist/lib/schema.test.js.map +0 -1
  363. package/dist/lib/state-detection.test.d.ts +0 -2
  364. package/dist/lib/state-detection.test.d.ts.map +0 -1
  365. package/dist/lib/state-detection.test.js +0 -451
  366. package/dist/lib/state-detection.test.js.map +0 -1
  367. package/dist/lib/ui/error.test.d.ts +0 -2
  368. package/dist/lib/ui/error.test.d.ts.map +0 -1
  369. package/dist/lib/ui/error.test.js +0 -143
  370. package/dist/lib/ui/error.test.js.map +0 -1
  371. package/dist/lib/ui/output.test.d.ts +0 -2
  372. package/dist/lib/ui/output.test.d.ts.map +0 -1
  373. package/dist/lib/ui/output.test.js +0 -59
  374. package/dist/lib/ui/output.test.js.map +0 -1
  375. package/dist/lib/ui/status.test.d.ts +0 -2
  376. package/dist/lib/ui/status.test.d.ts.map +0 -1
  377. package/dist/lib/ui/status.test.js +0 -158
  378. package/dist/lib/ui/status.test.js.map +0 -1
  379. package/dist/lib/ui/table.test.d.ts +0 -2
  380. package/dist/lib/ui/table.test.d.ts.map +0 -1
  381. package/dist/lib/ui/table.test.js +0 -115
  382. package/dist/lib/ui/table.test.js.map +0 -1
  383. package/dist/lib/ui/theme.test.d.ts +0 -2
  384. package/dist/lib/ui/theme.test.d.ts.map +0 -1
  385. package/dist/lib/ui/theme.test.js +0 -76
  386. package/dist/lib/ui/theme.test.js.map +0 -1
  387. package/dist/lib/wtconfig/config-manager.test.d.ts +0 -5
  388. package/dist/lib/wtconfig/config-manager.test.d.ts.map +0 -1
  389. package/dist/lib/wtconfig/config-manager.test.js +0 -501
  390. package/dist/lib/wtconfig/config-manager.test.js.map +0 -1
  391. package/dist/lib/wtconfig/environment.test.d.ts +0 -5
  392. package/dist/lib/wtconfig/environment.test.d.ts.map +0 -1
  393. package/dist/lib/wtconfig/environment.test.js +0 -285
  394. package/dist/lib/wtconfig/environment.test.js.map +0 -1
  395. package/dist/lib/wtlink/config-manifest.test.d.ts +0 -2
  396. package/dist/lib/wtlink/config-manifest.test.d.ts.map +0 -1
  397. package/dist/lib/wtlink/config-manifest.test.js +0 -486
  398. package/dist/lib/wtlink/config-manifest.test.js.map +0 -1
  399. package/dist/lib/wtlink/link-configs.test.d.ts +0 -2
  400. package/dist/lib/wtlink/link-configs.test.d.ts.map +0 -1
  401. package/dist/lib/wtlink/link-configs.test.js +0 -612
  402. package/dist/lib/wtlink/link-configs.test.js.map +0 -1
  403. package/dist/lib/wtlink/main-menu.test.d.ts +0 -5
  404. package/dist/lib/wtlink/main-menu.test.d.ts.map +0 -1
  405. package/dist/lib/wtlink/main-menu.test.js +0 -126
  406. package/dist/lib/wtlink/main-menu.test.js.map +0 -1
  407. package/dist/lib/wtlink/manage-manifest.test.d.ts +0 -2
  408. package/dist/lib/wtlink/manage-manifest.test.d.ts.map +0 -1
  409. package/dist/lib/wtlink/manage-manifest.test.js +0 -714
  410. package/dist/lib/wtlink/manage-manifest.test.js.map +0 -1
  411. package/dist/lib/wtlink/validate-manifest.test.d.ts +0 -2
  412. package/dist/lib/wtlink/validate-manifest.test.d.ts.map +0 -1
  413. package/dist/lib/wtlink/validate-manifest.test.js +0 -220
  414. package/dist/lib/wtlink/validate-manifest.test.js.map +0 -1
  415. package/dist/lib/wtstate/analyze.test.d.ts +0 -5
  416. package/dist/lib/wtstate/analyze.test.d.ts.map +0 -1
  417. package/dist/lib/wtstate/analyze.test.js +0 -282
  418. package/dist/lib/wtstate/analyze.test.js.map +0 -1
  419. package/dist/lib/wtstate/args.test.d.ts +0 -5
  420. package/dist/lib/wtstate/args.test.d.ts.map +0 -1
  421. package/dist/lib/wtstate/args.test.js +0 -120
  422. package/dist/lib/wtstate/args.test.js.map +0 -1
  423. package/dist/mcp/server.test.d.ts +0 -9
  424. package/dist/mcp/server.test.d.ts.map +0 -1
  425. package/dist/mcp/server.test.js +0 -550
  426. package/dist/mcp/server.test.js.map +0 -1
@@ -1,608 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { spawnSync, execSync, spawn, } from 'child_process';
3
- import * as path from 'path';
4
- import { EventEmitter } from 'stream';
5
- import * as git from './git.js';
6
- // Mock child_process
7
- vi.mock('child_process', () => ({
8
- spawnSync: vi.fn(),
9
- execSync: vi.fn(),
10
- spawn: vi.fn(),
11
- }));
12
- const mockSpawnSync = vi.mocked(spawnSync);
13
- const mockExecSync = vi.mocked(execSync);
14
- const mockSpawn = vi.mocked(spawn);
15
- /**
16
- * Helper to create a successful spawnSync result
17
- */
18
- function mockSpawnSuccess(stdout) {
19
- return {
20
- status: 0,
21
- signal: null,
22
- output: ['', stdout, ''],
23
- pid: 123,
24
- stdout,
25
- stderr: '',
26
- error: undefined,
27
- };
28
- }
29
- /**
30
- * Helper to create a failed spawnSync result
31
- */
32
- function mockSpawnFailure(stderr) {
33
- return {
34
- status: 1,
35
- signal: null,
36
- output: ['', '', stderr],
37
- pid: 123,
38
- stdout: '',
39
- stderr,
40
- error: undefined,
41
- };
42
- }
43
- describe('git', () => {
44
- beforeEach(() => {
45
- vi.clearAllMocks();
46
- });
47
- describe('exec', () => {
48
- it('executes git command and returns output with trailing whitespace trimmed', () => {
49
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output with trailing whitespace \n'));
50
- const result = git.exec(['status']);
51
- // Leading whitespace is preserved (important for git status), trailing is trimmed
52
- expect(result).toBe('output with trailing whitespace');
53
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['status'], expect.any(Object));
54
- });
55
- it('preserves leading whitespace in output', () => {
56
- // Leading spaces are significant in git status --porcelain output
57
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M file.txt\n'));
58
- const result = git.exec(['status', '--porcelain']);
59
- expect(result).toBe(' M file.txt');
60
- });
61
- it('passes cwd option correctly', () => {
62
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output'));
63
- git.exec(['status'], { cwd: '/some/path' });
64
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['status'], expect.objectContaining({ cwd: '/some/path' }));
65
- });
66
- it('throws error with stderr message on failure', () => {
67
- mockSpawnSync.mockReturnValue(mockSpawnFailure('fatal: not a git repository'));
68
- expect(() => git.exec(['status'])).toThrow('Git command failed');
69
- });
70
- });
71
- describe('execSafe', () => {
72
- it('returns output on success', () => {
73
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('output'));
74
- const result = git.execSafe(['status']);
75
- expect(result).toBe('output');
76
- });
77
- it('returns null on failure', () => {
78
- mockSpawnSync.mockReturnValue(mockSpawnFailure('Command failed'));
79
- const result = git.execSafe(['status']);
80
- expect(result).toBeNull();
81
- });
82
- });
83
- describe('getRepoRoot', () => {
84
- it('returns normalized path from git rev-parse', () => {
85
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('/home/user/repo\n'));
86
- const result = git.getRepoRoot();
87
- expect(result).toContain('repo');
88
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['rev-parse', '--show-toplevel'], expect.any(Object));
89
- });
90
- });
91
- describe('getRepoName', () => {
92
- it('extracts name from SSH remote URL', () => {
93
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('git@github.com:org/my-repo.git'));
94
- const result = git.getRepoName('/repo');
95
- expect(result).toBe('my-repo');
96
- });
97
- it('extracts name from HTTPS remote URL', () => {
98
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('https://github.com/org/my-repo.git'));
99
- const result = git.getRepoName('/repo');
100
- expect(result).toBe('my-repo');
101
- });
102
- it('extracts name from URL without .git suffix', () => {
103
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('https://github.com/org/my-repo'));
104
- const result = git.getRepoName('/repo');
105
- expect(result).toBe('my-repo');
106
- });
107
- it('falls back to directory name when no remote', () => {
108
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No remote'));
109
- const result = git.getRepoName('/home/user/my-project');
110
- expect(result).toBe('my-project');
111
- });
112
- it('extracts name from Unix local path with .git suffix', () => {
113
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('/path/to/my-repo.git'));
114
- const result = git.getRepoName('/repo');
115
- expect(result).toBe('my-repo');
116
- });
117
- it('extracts name from Windows local path with .git suffix', () => {
118
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\test\\repos\\my-repo.git'));
119
- const result = git.getRepoName('/repo');
120
- expect(result).toBe('my-repo');
121
- });
122
- it('extracts name from Windows local path without .git suffix', () => {
123
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\test\\repos\\my-repo'));
124
- const result = git.getRepoName('/repo');
125
- expect(result).toBe('my-repo');
126
- });
127
- it('extracts name from Windows short path format', () => {
128
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\main-repo.git'));
129
- const result = git.getRepoName('/repo');
130
- expect(result).toBe('main-repo');
131
- });
132
- });
133
- describe('getCurrentBranch', () => {
134
- it('returns branch name', () => {
135
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('feature/my-branch'));
136
- const result = git.getCurrentBranch();
137
- expect(result).toBe('feature/my-branch');
138
- });
139
- it('returns null for detached HEAD', () => {
140
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('HEAD'));
141
- const result = git.getCurrentBranch();
142
- expect(result).toBeNull();
143
- });
144
- });
145
- describe('isDetachedHead', () => {
146
- it('returns true when in detached HEAD state', () => {
147
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('HEAD'));
148
- expect(git.isDetachedHead()).toBe(true);
149
- });
150
- it('returns false when on a branch', () => {
151
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('main'));
152
- expect(git.isDetachedHead()).toBe(false);
153
- });
154
- });
155
- describe('getWorkingTreeStatus', () => {
156
- it('returns clean for empty status', () => {
157
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
158
- expect(git.getWorkingTreeStatus()).toBe('clean');
159
- });
160
- it('returns staged_only for staged changes', () => {
161
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M file.txt'));
162
- expect(git.getWorkingTreeStatus()).toBe('staged_only');
163
- });
164
- it('returns unstaged_only for unstaged changes', () => {
165
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M file.txt'));
166
- expect(git.getWorkingTreeStatus()).toBe('unstaged_only');
167
- });
168
- it('returns unstaged_only for untracked files', () => {
169
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('?? newfile.txt'));
170
- expect(git.getWorkingTreeStatus()).toBe('unstaged_only');
171
- });
172
- it('returns both for staged and unstaged changes', () => {
173
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('MM file.txt'));
174
- expect(git.getWorkingTreeStatus()).toBe('both');
175
- });
176
- it('returns both for staged changes and untracked files', () => {
177
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M staged.txt\n?? untracked.txt'));
178
- expect(git.getWorkingTreeStatus()).toBe('both');
179
- });
180
- });
181
- describe('getStagedFiles', () => {
182
- it('returns list of staged files', () => {
183
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('file1.txt\nfile2.txt\n'));
184
- const result = git.getStagedFiles();
185
- expect(result).toEqual(['file1.txt', 'file2.txt']);
186
- });
187
- it('returns empty array when nothing staged', () => {
188
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No staged files'));
189
- const result = git.getStagedFiles();
190
- expect(result).toEqual([]);
191
- });
192
- });
193
- describe('getUnstagedFiles', () => {
194
- it('returns list of unstaged and untracked files', () => {
195
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(' M modified.txt\n?? untracked.txt'));
196
- const result = git.getUnstagedFiles();
197
- expect(result).toEqual(['modified.txt', 'untracked.txt']);
198
- });
199
- it('excludes staged-only files', () => {
200
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('M staged.txt\n M both.txt'));
201
- const result = git.getUnstagedFiles();
202
- expect(result).toEqual(['both.txt']);
203
- });
204
- it('returns empty array when working tree is clean', () => {
205
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
206
- const result = git.getUnstagedFiles();
207
- expect(result).toEqual([]);
208
- });
209
- });
210
- describe('listWorktrees', () => {
211
- it('parses worktree list porcelain output', () => {
212
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo\n' +
213
- 'HEAD abc123def456\n' +
214
- 'branch refs/heads/main\n' +
215
- '\n' +
216
- 'worktree /home/user/repo.pr42\n' +
217
- 'HEAD def456abc123\n' +
218
- 'branch refs/heads/feature/test\n' +
219
- '\n'));
220
- const result = git.listWorktrees();
221
- expect(result).toHaveLength(2);
222
- expect(result[0]).toEqual({
223
- path: '/home/user/repo',
224
- commit: 'abc123def456',
225
- branch: 'main',
226
- isMain: true,
227
- isBare: false,
228
- isLocked: false,
229
- isPrunable: false,
230
- });
231
- expect(result[1]).toEqual({
232
- path: '/home/user/repo.pr42',
233
- commit: 'def456abc123',
234
- branch: 'feature/test',
235
- isMain: false,
236
- isBare: false,
237
- isLocked: false,
238
- isPrunable: false,
239
- });
240
- });
241
- it('handles bare repository', () => {
242
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo.git\n' + 'bare\n' + '\n'));
243
- const result = git.listWorktrees();
244
- expect(result[0].isBare).toBe(true);
245
- expect(result[0].isMain).toBe(true);
246
- });
247
- it('handles locked and prunable worktrees', () => {
248
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo.pr1\n' +
249
- 'HEAD abc123\n' +
250
- 'branch refs/heads/test\n' +
251
- 'locked\n' +
252
- 'prunable\n' +
253
- '\n'));
254
- const result = git.listWorktrees();
255
- expect(result[0].isLocked).toBe(true);
256
- expect(result[0].isPrunable).toBe(true);
257
- });
258
- it('handles detached HEAD in worktree', () => {
259
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('worktree /home/user/repo\n' + 'HEAD abc123\n' + 'detached\n' + '\n'));
260
- const result = git.listWorktrees();
261
- expect(result[0].branch).toBeNull();
262
- });
263
- });
264
- describe('getCommitRelationship', () => {
265
- it('returns same when HEAD equals base', () => {
266
- mockSpawnSync
267
- .mockReturnValueOnce(mockSpawnSuccess('abc123')) // getHeadCommit
268
- .mockReturnValueOnce(mockSpawnSuccess('abc123')); // getRefCommit
269
- const result = git.getCommitRelationship('main');
270
- expect(result).toBe('same');
271
- });
272
- it('returns divergent when base branch does not exist', () => {
273
- mockSpawnSync
274
- .mockReturnValueOnce(mockSpawnSuccess('abc123')) // getHeadCommit
275
- .mockReturnValueOnce(mockSpawnFailure('unknown revision')); // getRefCommit fails
276
- const result = git.getCommitRelationship('main');
277
- expect(result).toBe('divergent');
278
- });
279
- });
280
- describe('getCommitsAhead', () => {
281
- it('returns list of commits ahead of base', () => {
282
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123 First commit\ndef456 Second commit'));
283
- const result = git.getCommitsAhead('main');
284
- expect(result).toEqual(['abc123 First commit', 'def456 Second commit']);
285
- });
286
- it('returns empty array when not ahead', () => {
287
- mockSpawnSync.mockReturnValue(mockSpawnFailure('No commits'));
288
- const result = git.getCommitsAhead('main');
289
- expect(result).toEqual([]);
290
- });
291
- });
292
- describe('addWorktree', () => {
293
- it('creates worktree with existing branch', () => {
294
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
295
- git.addWorktree('/path/to/worktree', 'feature-branch');
296
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '/path/to/worktree', 'feature-branch'], expect.any(Object));
297
- });
298
- it('creates worktree with new branch', () => {
299
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
300
- git.addWorktree('/path/to/worktree', 'new-branch', { createBranch: true });
301
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree'], expect.any(Object));
302
- });
303
- it('creates worktree with new branch from start point', () => {
304
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
305
- git.addWorktree('/path/to/worktree', 'new-branch', {
306
- createBranch: true,
307
- startPoint: 'origin/main',
308
- });
309
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree', 'origin/main'], expect.any(Object));
310
- });
311
- });
312
- describe('removeWorktree', () => {
313
- it('removes worktree', () => {
314
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
315
- git.removeWorktree('/path/to/worktree');
316
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'remove', '/path/to/worktree'], expect.any(Object));
317
- });
318
- it('force removes worktree', () => {
319
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
320
- git.removeWorktree('/path/to/worktree', { force: true });
321
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['worktree', 'remove', '--force', '/path/to/worktree'], expect.any(Object));
322
- });
323
- });
324
- describe('createBranch', () => {
325
- it('creates branch from HEAD', () => {
326
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
327
- git.createBranch('new-branch');
328
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', 'new-branch'], expect.any(Object));
329
- });
330
- it('creates branch from start point', () => {
331
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
332
- git.createBranch('new-branch', 'origin/main');
333
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', 'new-branch', 'origin/main'], expect.any(Object));
334
- });
335
- });
336
- describe('deleteBranch', () => {
337
- it('deletes branch with -d flag', () => {
338
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
339
- git.deleteBranch('old-branch');
340
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', '-d', 'old-branch'], expect.any(Object));
341
- });
342
- it('force deletes branch with -D flag', () => {
343
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
344
- git.deleteBranch('old-branch', { force: true });
345
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['branch', '-D', 'old-branch'], expect.any(Object));
346
- });
347
- });
348
- describe('commit', () => {
349
- it('creates commit with message', () => {
350
- mockSpawnSync
351
- .mockReturnValueOnce(mockSpawnSuccess('')) // commit
352
- .mockReturnValueOnce(mockSpawnSuccess('abc123')); // getHeadCommit
353
- const result = git.commit({ message: 'Test commit' });
354
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '-m', 'Test commit'], expect.any(Object));
355
- expect(result).toBe('abc123');
356
- });
357
- it('creates commit with all flag', () => {
358
- mockSpawnSync
359
- .mockReturnValueOnce(mockSpawnSuccess(''))
360
- .mockReturnValueOnce(mockSpawnSuccess('abc123'));
361
- git.commit({ message: 'Test commit', all: true });
362
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '-a', '-m', 'Test commit'], expect.any(Object));
363
- });
364
- it('creates empty commit when allowed', () => {
365
- mockSpawnSync
366
- .mockReturnValueOnce(mockSpawnSuccess(''))
367
- .mockReturnValueOnce(mockSpawnSuccess('abc123'));
368
- git.commit({ message: 'Empty commit', allowEmpty: true });
369
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['commit', '--allow-empty', '-m', 'Empty commit'], expect.any(Object));
370
- });
371
- });
372
- describe('push', () => {
373
- it('pushes to remote', () => {
374
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
375
- git.push();
376
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push'], expect.any(Object));
377
- });
378
- it('pushes with upstream flag', () => {
379
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
380
- git.push({ setUpstream: true, remote: 'origin', branch: 'feature' });
381
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push', '-u', 'origin', 'feature'], expect.any(Object));
382
- });
383
- it('force pushes', () => {
384
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
385
- git.push({ force: true });
386
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['push', '--force'], expect.any(Object));
387
- });
388
- });
389
- describe('stash', () => {
390
- it('creates stash and returns reference', () => {
391
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved working directory'));
392
- const result = git.stash();
393
- expect(result).toBe('stash@{0}');
394
- });
395
- it('returns null when nothing to stash', () => {
396
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('No local changes to save'));
397
- const result = git.stash();
398
- expect(result).toBeNull();
399
- });
400
- it('stashes with keep-index flag', () => {
401
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
402
- git.stash({ keepIndex: true });
403
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '--keep-index'], expect.any(Object));
404
- });
405
- it('stashes with message', () => {
406
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
407
- git.stash({ message: 'WIP: feature' });
408
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '-m', 'WIP: feature'], expect.any(Object));
409
- });
410
- it('stashes untracked files', () => {
411
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('Saved'));
412
- git.stash({ includeUntracked: true });
413
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['stash', 'push', '--include-untracked'], expect.any(Object));
414
- });
415
- });
416
- describe('branchExists', () => {
417
- it('returns true when branch exists', () => {
418
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
419
- expect(git.branchExists('main')).toBe(true);
420
- });
421
- it('returns false when branch does not exist', () => {
422
- mockSpawnSync.mockReturnValue(mockSpawnFailure('unknown revision'));
423
- expect(git.branchExists('nonexistent')).toBe(false);
424
- });
425
- });
426
- describe('remoteBranchExists', () => {
427
- it('returns true when remote branch exists', () => {
428
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
429
- expect(git.remoteBranchExists('main')).toBe(true);
430
- });
431
- it('returns false when remote branch does not exist', () => {
432
- mockSpawnSync.mockReturnValue(mockSpawnFailure('unknown revision'));
433
- expect(git.remoteBranchExists('nonexistent')).toBe(false);
434
- });
435
- it('checks specific remote', () => {
436
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('abc123'));
437
- git.remoteBranchExists('main', 'upstream');
438
- expect(mockSpawnSync).toHaveBeenCalledWith('git', ['rev-parse', '--verify', 'refs/remotes/upstream/main'], expect.any(Object));
439
- });
440
- });
441
- describe('getMainWorktreeRoot', () => {
442
- it('returns repo root when in main worktree', () => {
443
- // Use path.join to create platform-appropriate paths
444
- const repoPath = path.join('/home', 'user', 'repo');
445
- const gitDir = path.join(repoPath, '.git');
446
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(gitDir));
447
- const result = git.getMainWorktreeRoot(repoPath);
448
- expect(result).toBe(path.resolve(repoPath));
449
- });
450
- it('returns main worktree root when in linked worktree', () => {
451
- const mainRepo = path.join('/home', 'user', 'main-repo');
452
- const worktreeGitDir = path.join(mainRepo, '.git', 'worktrees', 'feature-branch');
453
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(worktreeGitDir));
454
- const result = git.getMainWorktreeRoot(path.join('/home', 'user', 'main-repo.pr42'));
455
- expect(result).toBe(path.resolve(mainRepo));
456
- });
457
- it('falls back to getRepoRoot when commonDir is null', () => {
458
- const fallbackPath = path.join('/fallback', 'root');
459
- // First call (git-common-dir) fails, second call (show-toplevel) succeeds
460
- mockSpawnSync
461
- .mockReturnValueOnce(mockSpawnFailure('failed'))
462
- .mockReturnValueOnce(mockSpawnSuccess(fallbackPath));
463
- const result = git.getMainWorktreeRoot();
464
- expect(result).toContain('fallback');
465
- });
466
- });
467
- describe('isGitIgnored', () => {
468
- it('returns true when file is ignored', () => {
469
- mockSpawnSync.mockReturnValue(mockSpawnSuccess('node_modules/'));
470
- expect(git.isGitIgnored('node_modules/')).toBe(true);
471
- });
472
- it('returns false when file is not ignored', () => {
473
- mockSpawnSync.mockReturnValue(mockSpawnFailure('no output for unignored files'));
474
- expect(git.isGitIgnored('src/index.ts')).toBe(false);
475
- });
476
- it('returns false when check-ignore returns empty', () => {
477
- mockSpawnSync.mockReturnValue(mockSpawnSuccess(''));
478
- expect(git.isGitIgnored('src/index.ts')).toBe(false);
479
- });
480
- });
481
- describe('checkGitInstalled', () => {
482
- it('returns true when git is installed', () => {
483
- mockExecSync.mockReturnValue('git version 2.39.0');
484
- expect(git.checkGitInstalled()).toBe(true);
485
- });
486
- it('returns false when git is not installed', () => {
487
- mockExecSync.mockImplementation(() => {
488
- throw new Error('command not found: git');
489
- });
490
- expect(git.checkGitInstalled()).toBe(false);
491
- });
492
- });
493
- // ============================================================================
494
- // Async function tests
495
- // ============================================================================
496
- /**
497
- * Helper to create a mock child process for async spawn
498
- */
499
- function createMockChildProcess(stdout, stderr, exitCode) {
500
- const child = new EventEmitter();
501
- // Create mock readable streams
502
- const mockStdout = new EventEmitter();
503
- const mockStderr = new EventEmitter();
504
- child.stdout = mockStdout;
505
- child.stderr = mockStderr;
506
- // Emit data and close event on next tick
507
- process.nextTick(() => {
508
- if (stdout) {
509
- child.stdout?.emit('data', Buffer.from(stdout));
510
- }
511
- if (stderr) {
512
- child.stderr?.emit('data', Buffer.from(stderr));
513
- }
514
- child.emit('close', exitCode);
515
- });
516
- return child;
517
- }
518
- describe('execAsync', () => {
519
- it('executes git command and returns output', async () => {
520
- mockSpawn.mockReturnValue(createMockChildProcess('output\n', '', 0));
521
- const result = await git.execAsync(['status']);
522
- expect(result).toBe('output');
523
- expect(mockSpawn).toHaveBeenCalledWith('git', ['status'], expect.any(Object));
524
- });
525
- it('rejects on non-zero exit code', async () => {
526
- mockSpawn.mockReturnValue(createMockChildProcess('', 'fatal: error', 1));
527
- await expect(git.execAsync(['invalid'])).rejects.toThrow('Git command failed');
528
- });
529
- it('rejects on spawn error', async () => {
530
- const child = new EventEmitter();
531
- child.stdout = new EventEmitter();
532
- child.stderr = new EventEmitter();
533
- mockSpawn.mockReturnValue(child);
534
- const promise = git.execAsync(['status']);
535
- process.nextTick(() => {
536
- child.emit('error', new Error('spawn failed'));
537
- });
538
- await expect(promise).rejects.toThrow('spawn failed');
539
- });
540
- it('passes cwd option correctly', async () => {
541
- mockSpawn.mockReturnValue(createMockChildProcess('output', '', 0));
542
- await git.execAsync(['status'], { cwd: '/some/path' });
543
- expect(mockSpawn).toHaveBeenCalledWith('git', ['status'], expect.objectContaining({ cwd: '/some/path' }));
544
- });
545
- });
546
- describe('fetchAsync', () => {
547
- it('fetches from remote', async () => {
548
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
549
- await git.fetchAsync('origin');
550
- expect(mockSpawn).toHaveBeenCalledWith('git', ['fetch', 'origin'], expect.any(Object));
551
- });
552
- it('uses default remote', async () => {
553
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
554
- await git.fetchAsync();
555
- expect(mockSpawn).toHaveBeenCalledWith('git', ['fetch', 'origin'], expect.any(Object));
556
- });
557
- });
558
- describe('addWorktreeAsync', () => {
559
- it('creates worktree with existing branch', async () => {
560
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
561
- await git.addWorktreeAsync('/path/to/worktree', 'feature-branch');
562
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '/path/to/worktree', 'feature-branch'], expect.any(Object));
563
- });
564
- it('creates worktree with new branch', async () => {
565
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
566
- await git.addWorktreeAsync('/path/to/worktree', 'new-branch', { createBranch: true });
567
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree'], expect.any(Object));
568
- });
569
- it('creates worktree with new branch from start point', async () => {
570
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
571
- await git.addWorktreeAsync('/path/to/worktree', 'new-branch', {
572
- createBranch: true,
573
- startPoint: 'origin/main',
574
- });
575
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'add', '-b', 'new-branch', '/path/to/worktree', 'origin/main'], expect.any(Object));
576
- });
577
- });
578
- describe('removeWorktreeAsync', () => {
579
- it('removes worktree', async () => {
580
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
581
- await git.removeWorktreeAsync('/path/to/worktree');
582
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'remove', '/path/to/worktree'], expect.any(Object));
583
- });
584
- it('force removes worktree', async () => {
585
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
586
- await git.removeWorktreeAsync('/path/to/worktree', { force: true });
587
- expect(mockSpawn).toHaveBeenCalledWith('git', ['worktree', 'remove', '--force', '/path/to/worktree'], expect.any(Object));
588
- });
589
- });
590
- describe('pushAsync', () => {
591
- it('pushes to remote', async () => {
592
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
593
- await git.pushAsync();
594
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push'], expect.any(Object));
595
- });
596
- it('pushes with upstream flag', async () => {
597
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
598
- await git.pushAsync({ setUpstream: true, remote: 'origin', branch: 'feature' });
599
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push', '-u', 'origin', 'feature'], expect.any(Object));
600
- });
601
- it('force pushes', async () => {
602
- mockSpawn.mockReturnValue(createMockChildProcess('', '', 0));
603
- await git.pushAsync({ force: true });
604
- expect(mockSpawn).toHaveBeenCalledWith('git', ['push', '--force'], expect.any(Object));
605
- });
606
- });
607
- });
608
- //# sourceMappingURL=git.test.js.map