intershell 0.3.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 (357) hide show
  1. package/README.md +301 -0
  2. package/dist/commands/ci/act.d.ts +13 -0
  3. package/dist/commands/ci/act.d.ts.map +1 -0
  4. package/dist/commands/ci/act.js +89 -0
  5. package/dist/commands/ci/act.js.map +1 -0
  6. package/dist/commands/ci/attach-affected.d.ts +12 -0
  7. package/dist/commands/ci/attach-affected.d.ts.map +1 -0
  8. package/dist/commands/ci/attach-affected.js +83 -0
  9. package/dist/commands/ci/attach-affected.js.map +1 -0
  10. package/dist/commands/ci/attach-service-ports.d.ts +10 -0
  11. package/dist/commands/ci/attach-service-ports.d.ts.map +1 -0
  12. package/dist/commands/ci/attach-service-ports.js +25 -0
  13. package/dist/commands/ci/attach-service-ports.js.map +1 -0
  14. package/dist/commands/commit-check.d.ts +13 -0
  15. package/dist/commands/commit-check.d.ts.map +1 -0
  16. package/dist/commands/commit-check.js +110 -0
  17. package/dist/commands/commit-check.js.map +1 -0
  18. package/dist/commands/commit.d.ts +16 -0
  19. package/dist/commands/commit.d.ts.map +1 -0
  20. package/dist/commands/commit.js +91 -0
  21. package/dist/commands/commit.js.map +1 -0
  22. package/dist/commands/dev/check.d.ts +13 -0
  23. package/dist/commands/dev/check.d.ts.map +1 -0
  24. package/dist/commands/dev/check.js +91 -0
  25. package/dist/commands/dev/check.js.map +1 -0
  26. package/dist/commands/dev/cleanup.d.ts +10 -0
  27. package/dist/commands/dev/cleanup.d.ts.map +1 -0
  28. package/dist/commands/dev/cleanup.js +28 -0
  29. package/dist/commands/dev/cleanup.js.map +1 -0
  30. package/dist/commands/dev/rm.d.ts +12 -0
  31. package/dist/commands/dev/rm.d.ts.map +1 -0
  32. package/dist/commands/dev/rm.js +49 -0
  33. package/dist/commands/dev/rm.js.map +1 -0
  34. package/dist/commands/dev/setup.d.ts +10 -0
  35. package/dist/commands/dev/setup.d.ts.map +1 -0
  36. package/dist/commands/dev/setup.js +40 -0
  37. package/dist/commands/dev/setup.js.map +1 -0
  38. package/dist/commands/local/cleanup.d.ts +12 -0
  39. package/dist/commands/local/cleanup.d.ts.map +1 -0
  40. package/dist/commands/local/cleanup.js +62 -0
  41. package/dist/commands/local/cleanup.js.map +1 -0
  42. package/dist/commands/local/setup.d.ts +11 -0
  43. package/dist/commands/local/setup.d.ts.map +1 -0
  44. package/dist/commands/local/setup.js +55 -0
  45. package/dist/commands/local/setup.js.map +1 -0
  46. package/dist/commands/local/vscode.d.ts +17 -0
  47. package/dist/commands/local/vscode.d.ts.map +1 -0
  48. package/dist/commands/local/vscode.js +94 -0
  49. package/dist/commands/local/vscode.js.map +1 -0
  50. package/dist/commands/update-package-json.d.ts +12 -0
  51. package/dist/commands/update-package-json.d.ts.map +1 -0
  52. package/dist/commands/update-package-json.js +82 -0
  53. package/dist/commands/update-package-json.js.map +1 -0
  54. package/dist/commands/version/apply.d.ts +16 -0
  55. package/dist/commands/version/apply.d.ts.map +1 -0
  56. package/dist/commands/version/apply.js +120 -0
  57. package/dist/commands/version/apply.js.map +1 -0
  58. package/dist/commands/version/ci.d.ts +12 -0
  59. package/dist/commands/version/ci.d.ts.map +1 -0
  60. package/dist/commands/version/ci.js +67 -0
  61. package/dist/commands/version/ci.js.map +1 -0
  62. package/dist/commands/version/prepare.d.ts +19 -0
  63. package/dist/commands/version/prepare.d.ts.map +1 -0
  64. package/dist/commands/version/prepare.js +153 -0
  65. package/dist/commands/version/prepare.js.map +1 -0
  66. package/dist/core/colorify.d.ts +21 -0
  67. package/dist/core/colorify.d.ts.map +1 -0
  68. package/dist/core/colorify.js +56 -0
  69. package/dist/core/colorify.js.map +1 -0
  70. package/dist/core/index.d.ts +4 -0
  71. package/dist/core/index.d.ts.map +1 -0
  72. package/dist/core/index.js +3 -0
  73. package/dist/core/index.js.map +1 -0
  74. package/dist/core/types.d.ts +181 -0
  75. package/dist/core/types.d.ts.map +1 -0
  76. package/dist/core/types.js +5 -0
  77. package/dist/core/types.js.map +1 -0
  78. package/dist/core/wrapshell.d.ts +19 -0
  79. package/dist/core/wrapshell.d.ts.map +1 -0
  80. package/dist/core/wrapshell.js +323 -0
  81. package/dist/core/wrapshell.js.map +1 -0
  82. package/dist/entities/affected/affected.d.ts +4 -0
  83. package/dist/entities/affected/affected.d.ts.map +1 -0
  84. package/dist/entities/affected/affected.js +20 -0
  85. package/dist/entities/affected/affected.js.map +1 -0
  86. package/dist/entities/affected/affected.test.d.ts +2 -0
  87. package/dist/entities/affected/affected.test.d.ts.map +1 -0
  88. package/dist/entities/affected/affected.test.js +305 -0
  89. package/dist/entities/affected/affected.test.js.map +1 -0
  90. package/dist/entities/affected/index.d.ts +2 -0
  91. package/dist/entities/affected/index.d.ts.map +1 -0
  92. package/dist/entities/affected/index.js +2 -0
  93. package/dist/entities/affected/index.js.map +1 -0
  94. package/dist/entities/branch/branch.d.ts +8 -0
  95. package/dist/entities/branch/branch.d.ts.map +1 -0
  96. package/dist/entities/branch/branch.js +74 -0
  97. package/dist/entities/branch/branch.js.map +1 -0
  98. package/dist/entities/branch/branch.test.d.ts +2 -0
  99. package/dist/entities/branch/branch.test.d.ts.map +1 -0
  100. package/dist/entities/branch/branch.test.js +316 -0
  101. package/dist/entities/branch/branch.test.js.map +1 -0
  102. package/dist/entities/branch/branch.types.d.ts +6 -0
  103. package/dist/entities/branch/branch.types.d.ts.map +1 -0
  104. package/dist/entities/branch/branch.types.js +2 -0
  105. package/dist/entities/branch/branch.types.js.map +1 -0
  106. package/dist/entities/branch/index.d.ts +3 -0
  107. package/dist/entities/branch/index.d.ts.map +1 -0
  108. package/dist/entities/branch/index.js +3 -0
  109. package/dist/entities/branch/index.js.map +1 -0
  110. package/dist/entities/commit/commit.d.ts +15 -0
  111. package/dist/entities/commit/commit.d.ts.map +1 -0
  112. package/dist/entities/commit/commit.js +196 -0
  113. package/dist/entities/commit/commit.js.map +1 -0
  114. package/dist/entities/commit/commit.test.d.ts +26 -0
  115. package/dist/entities/commit/commit.test.d.ts.map +1 -0
  116. package/dist/entities/commit/commit.test.js +550 -0
  117. package/dist/entities/commit/commit.test.js.map +1 -0
  118. package/dist/entities/commit/commit.types.d.ts +49 -0
  119. package/dist/entities/commit/commit.types.d.ts.map +1 -0
  120. package/dist/entities/commit/commit.types.js +31 -0
  121. package/dist/entities/commit/commit.types.js.map +1 -0
  122. package/dist/entities/commit/index.d.ts +3 -0
  123. package/dist/entities/commit/index.d.ts.map +1 -0
  124. package/dist/entities/commit/index.js +3 -0
  125. package/dist/entities/commit/index.js.map +1 -0
  126. package/dist/entities/commit/pr.d.ts +11 -0
  127. package/dist/entities/commit/pr.d.ts.map +1 -0
  128. package/dist/entities/commit/pr.js +201 -0
  129. package/dist/entities/commit/pr.js.map +1 -0
  130. package/dist/entities/commit/pr.test.d.ts +2 -0
  131. package/dist/entities/commit/pr.test.d.ts.map +1 -0
  132. package/dist/entities/commit/pr.test.js +782 -0
  133. package/dist/entities/commit/pr.test.js.map +1 -0
  134. package/dist/entities/compose/compose.d.ts +18 -0
  135. package/dist/entities/compose/compose.d.ts.map +1 -0
  136. package/dist/entities/compose/compose.js +197 -0
  137. package/dist/entities/compose/compose.js.map +1 -0
  138. package/dist/entities/compose/compose.test.d.ts +2 -0
  139. package/dist/entities/compose/compose.test.d.ts.map +1 -0
  140. package/dist/entities/compose/compose.test.js +406 -0
  141. package/dist/entities/compose/compose.test.js.map +1 -0
  142. package/dist/entities/compose/compose.types.d.ts +77 -0
  143. package/dist/entities/compose/compose.types.d.ts.map +1 -0
  144. package/dist/entities/compose/compose.types.js +2 -0
  145. package/dist/entities/compose/compose.types.js.map +1 -0
  146. package/dist/entities/compose/index.d.ts +3 -0
  147. package/dist/entities/compose/index.d.ts.map +1 -0
  148. package/dist/entities/compose/index.js +3 -0
  149. package/dist/entities/compose/index.js.map +1 -0
  150. package/dist/entities/entities.shell.d.ts +29 -0
  151. package/dist/entities/entities.shell.d.ts.map +1 -0
  152. package/dist/entities/entities.shell.js +27 -0
  153. package/dist/entities/entities.shell.js.map +1 -0
  154. package/dist/entities/entities.shell.test.d.ts +2 -0
  155. package/dist/entities/entities.shell.test.d.ts.map +1 -0
  156. package/dist/entities/entities.shell.test.js +23 -0
  157. package/dist/entities/entities.shell.test.js.map +1 -0
  158. package/dist/entities/index.d.ts +12 -0
  159. package/dist/entities/index.d.ts.map +1 -0
  160. package/dist/entities/index.js +12 -0
  161. package/dist/entities/index.js.map +1 -0
  162. package/dist/entities/intershell-config/intershell-config.d.ts +11 -0
  163. package/dist/entities/intershell-config/intershell-config.d.ts.map +1 -0
  164. package/dist/entities/intershell-config/intershell-config.default.d.ts +188 -0
  165. package/dist/entities/intershell-config/intershell-config.default.d.ts.map +1 -0
  166. package/dist/entities/intershell-config/intershell-config.default.js +225 -0
  167. package/dist/entities/intershell-config/intershell-config.default.js.map +1 -0
  168. package/dist/entities/intershell-config/intershell-config.js +132 -0
  169. package/dist/entities/intershell-config/intershell-config.js.map +1 -0
  170. package/dist/entities/intershell-config/intershell-config.test.d.ts +2 -0
  171. package/dist/entities/intershell-config/intershell-config.test.d.ts.map +1 -0
  172. package/dist/entities/intershell-config/intershell-config.test.js +102 -0
  173. package/dist/entities/intershell-config/intershell-config.test.js.map +1 -0
  174. package/dist/entities/intershell-config/intershell-config.types.d.ts +103 -0
  175. package/dist/entities/intershell-config/intershell-config.types.d.ts.map +1 -0
  176. package/dist/entities/intershell-config/intershell-config.types.js +2 -0
  177. package/dist/entities/intershell-config/intershell-config.types.js.map +1 -0
  178. package/dist/entities/package/index.d.ts +4 -0
  179. package/dist/entities/package/index.d.ts.map +1 -0
  180. package/dist/entities/package/index.js +4 -0
  181. package/dist/entities/package/index.js.map +1 -0
  182. package/dist/entities/package/package.d.ts +49 -0
  183. package/dist/entities/package/package.d.ts.map +1 -0
  184. package/dist/entities/package/package.js +234 -0
  185. package/dist/entities/package/package.js.map +1 -0
  186. package/dist/entities/package/package.shell.d.ts +48 -0
  187. package/dist/entities/package/package.shell.d.ts.map +1 -0
  188. package/dist/entities/package/package.shell.js +118 -0
  189. package/dist/entities/package/package.shell.js.map +1 -0
  190. package/dist/entities/package/package.test.d.ts +23 -0
  191. package/dist/entities/package/package.test.d.ts.map +1 -0
  192. package/dist/entities/package/package.test.js +637 -0
  193. package/dist/entities/package/package.test.js.map +1 -0
  194. package/dist/entities/package/package.types.d.ts +48 -0
  195. package/dist/entities/package/package.types.d.ts.map +1 -0
  196. package/dist/entities/package/package.types.js +2 -0
  197. package/dist/entities/package/package.types.js.map +1 -0
  198. package/dist/entities/package-changelog/index.d.ts +4 -0
  199. package/dist/entities/package-changelog/index.d.ts.map +1 -0
  200. package/dist/entities/package-changelog/index.js +4 -0
  201. package/dist/entities/package-changelog/index.js.map +1 -0
  202. package/dist/entities/package-changelog/package-changelog.d.ts +20 -0
  203. package/dist/entities/package-changelog/package-changelog.d.ts.map +1 -0
  204. package/dist/entities/package-changelog/package-changelog.js +59 -0
  205. package/dist/entities/package-changelog/package-changelog.js.map +1 -0
  206. package/dist/entities/package-changelog/package-changelog.types.d.ts +25 -0
  207. package/dist/entities/package-changelog/package-changelog.types.d.ts.map +1 -0
  208. package/dist/entities/package-changelog/package-changelog.types.js +2 -0
  209. package/dist/entities/package-changelog/package-changelog.types.js.map +1 -0
  210. package/dist/entities/package-changelog/template.d.ts +20 -0
  211. package/dist/entities/package-changelog/template.d.ts.map +1 -0
  212. package/dist/entities/package-changelog/template.default.d.ts +10 -0
  213. package/dist/entities/package-changelog/template.default.d.ts.map +1 -0
  214. package/dist/entities/package-changelog/template.default.js +85 -0
  215. package/dist/entities/package-changelog/template.default.js.map +1 -0
  216. package/dist/entities/package-changelog/template.js +90 -0
  217. package/dist/entities/package-changelog/template.js.map +1 -0
  218. package/dist/entities/package-commits/dependency-analyzer.d.ts +35 -0
  219. package/dist/entities/package-commits/dependency-analyzer.d.ts.map +1 -0
  220. package/dist/entities/package-commits/dependency-analyzer.js +169 -0
  221. package/dist/entities/package-commits/dependency-analyzer.js.map +1 -0
  222. package/dist/entities/package-commits/dependency-analyzer.test.d.ts +2 -0
  223. package/dist/entities/package-commits/dependency-analyzer.test.d.ts.map +1 -0
  224. package/dist/entities/package-commits/dependency-analyzer.test.js +25 -0
  225. package/dist/entities/package-commits/dependency-analyzer.test.js.map +1 -0
  226. package/dist/entities/package-commits/index.d.ts +3 -0
  227. package/dist/entities/package-commits/index.d.ts.map +1 -0
  228. package/dist/entities/package-commits/index.js +3 -0
  229. package/dist/entities/package-commits/index.js.map +1 -0
  230. package/dist/entities/package-commits/package-commits.d.ts +33 -0
  231. package/dist/entities/package-commits/package-commits.d.ts.map +1 -0
  232. package/dist/entities/package-commits/package-commits.js +149 -0
  233. package/dist/entities/package-commits/package-commits.js.map +1 -0
  234. package/dist/entities/package-commits/package-commits.test.d.ts +2 -0
  235. package/dist/entities/package-commits/package-commits.test.d.ts.map +1 -0
  236. package/dist/entities/package-commits/package-commits.test.js +40 -0
  237. package/dist/entities/package-commits/package-commits.test.js.map +1 -0
  238. package/dist/entities/package-tags/index.d.ts +2 -0
  239. package/dist/entities/package-tags/index.d.ts.map +1 -0
  240. package/dist/entities/package-tags/index.js +2 -0
  241. package/dist/entities/package-tags/index.js.map +1 -0
  242. package/dist/entities/package-tags/package-tags.d.ts +24 -0
  243. package/dist/entities/package-tags/package-tags.d.ts.map +1 -0
  244. package/dist/entities/package-tags/package-tags.js +197 -0
  245. package/dist/entities/package-tags/package-tags.js.map +1 -0
  246. package/dist/entities/package-tags/package-tags.test.d.ts +2 -0
  247. package/dist/entities/package-tags/package-tags.test.d.ts.map +1 -0
  248. package/dist/entities/package-tags/package-tags.test.js +60 -0
  249. package/dist/entities/package-tags/package-tags.test.js.map +1 -0
  250. package/dist/entities/package-version/index.d.ts +3 -0
  251. package/dist/entities/package-version/index.d.ts.map +1 -0
  252. package/dist/entities/package-version/index.js +3 -0
  253. package/dist/entities/package-version/index.js.map +1 -0
  254. package/dist/entities/package-version/package-version.d.ts +16 -0
  255. package/dist/entities/package-version/package-version.d.ts.map +1 -0
  256. package/dist/entities/package-version/package-version.js +166 -0
  257. package/dist/entities/package-version/package-version.js.map +1 -0
  258. package/dist/entities/package-version/package-version.test.d.ts +2 -0
  259. package/dist/entities/package-version/package-version.test.d.ts.map +1 -0
  260. package/dist/entities/package-version/package-version.test.js +113 -0
  261. package/dist/entities/package-version/package-version.test.js.map +1 -0
  262. package/dist/entities/package-version/package-version.types.d.ts +31 -0
  263. package/dist/entities/package-version/package-version.types.d.ts.map +1 -0
  264. package/dist/entities/package-version/package-version.types.js +2 -0
  265. package/dist/entities/package-version/package-version.types.js.map +1 -0
  266. package/dist/entities/tag/index.d.ts +3 -0
  267. package/dist/entities/tag/index.d.ts.map +1 -0
  268. package/dist/entities/tag/index.js +3 -0
  269. package/dist/entities/tag/index.js.map +1 -0
  270. package/dist/entities/tag/tag.d.ts +24 -0
  271. package/dist/entities/tag/tag.d.ts.map +1 -0
  272. package/dist/entities/tag/tag.js +168 -0
  273. package/dist/entities/tag/tag.js.map +1 -0
  274. package/dist/entities/tag/tag.test.d.ts +2 -0
  275. package/dist/entities/tag/tag.test.d.ts.map +1 -0
  276. package/dist/entities/tag/tag.test.js +638 -0
  277. package/dist/entities/tag/tag.test.js.map +1 -0
  278. package/dist/entities/tag/tag.types.d.ts +35 -0
  279. package/dist/entities/tag/tag.types.d.ts.map +1 -0
  280. package/dist/entities/tag/tag.types.js +2 -0
  281. package/dist/entities/tag/tag.types.js.map +1 -0
  282. package/dist/index.d.ts +3 -0
  283. package/dist/index.d.ts.map +1 -0
  284. package/dist/index.js +6 -0
  285. package/dist/index.js.map +1 -0
  286. package/package.json +73 -0
  287. package/src/commands/ci/act.ts +95 -0
  288. package/src/commands/ci/attach-affected.ts +93 -0
  289. package/src/commands/ci/attach-service-ports.ts +31 -0
  290. package/src/commands/commit-check.ts +124 -0
  291. package/src/commands/commit.ts +103 -0
  292. package/src/commands/dev/check.ts +117 -0
  293. package/src/commands/dev/cleanup.ts +34 -0
  294. package/src/commands/dev/rm.ts +66 -0
  295. package/src/commands/dev/setup.ts +48 -0
  296. package/src/commands/local/cleanup.ts +74 -0
  297. package/src/commands/local/setup.ts +68 -0
  298. package/src/commands/local/vscode.ts +118 -0
  299. package/src/commands/update-package-json.ts +104 -0
  300. package/src/commands/version/apply.ts +156 -0
  301. package/src/commands/version/ci.ts +85 -0
  302. package/src/commands/version/prepare.ts +217 -0
  303. package/src/core/colorify.ts +61 -0
  304. package/src/core/index.ts +3 -0
  305. package/src/core/types.ts +262 -0
  306. package/src/core/wrapshell.ts +388 -0
  307. package/src/entities/affected/affected.test.ts +427 -0
  308. package/src/entities/affected/affected.ts +22 -0
  309. package/src/entities/affected/index.ts +1 -0
  310. package/src/entities/branch/branch.test.ts +348 -0
  311. package/src/entities/branch/branch.ts +89 -0
  312. package/src/entities/branch/branch.types.ts +5 -0
  313. package/src/entities/branch/index.ts +2 -0
  314. package/src/entities/commit/commit.test.ts +769 -0
  315. package/src/entities/commit/commit.ts +245 -0
  316. package/src/entities/commit/commit.types.ts +81 -0
  317. package/src/entities/commit/index.ts +2 -0
  318. package/src/entities/commit/pr.test.ts +860 -0
  319. package/src/entities/commit/pr.ts +241 -0
  320. package/src/entities/compose/compose.test.ts +496 -0
  321. package/src/entities/compose/compose.ts +251 -0
  322. package/src/entities/compose/compose.types.ts +88 -0
  323. package/src/entities/compose/index.ts +2 -0
  324. package/src/entities/entities.shell.test.ts +35 -0
  325. package/src/entities/entities.shell.ts +81 -0
  326. package/src/entities/index.ts +11 -0
  327. package/src/entities/intershell-config/intershell-config.default.ts +229 -0
  328. package/src/entities/intershell-config/intershell-config.test.ts +117 -0
  329. package/src/entities/intershell-config/intershell-config.ts +143 -0
  330. package/src/entities/intershell-config/intershell-config.types.ts +118 -0
  331. package/src/entities/package/index.ts +3 -0
  332. package/src/entities/package/package.shell.ts +124 -0
  333. package/src/entities/package/package.test.ts +830 -0
  334. package/src/entities/package/package.ts +267 -0
  335. package/src/entities/package/package.types.ts +49 -0
  336. package/src/entities/package-changelog/index.ts +3 -0
  337. package/src/entities/package-changelog/package-changelog.ts +81 -0
  338. package/src/entities/package-changelog/package-changelog.types.ts +30 -0
  339. package/src/entities/package-changelog/template.default.ts +109 -0
  340. package/src/entities/package-changelog/template.ts +118 -0
  341. package/src/entities/package-commits/dependency-analyzer.test.ts +29 -0
  342. package/src/entities/package-commits/dependency-analyzer.ts +194 -0
  343. package/src/entities/package-commits/index.ts +2 -0
  344. package/src/entities/package-commits/package-commits.test.ts +44 -0
  345. package/src/entities/package-commits/package-commits.ts +191 -0
  346. package/src/entities/package-tags/index.ts +1 -0
  347. package/src/entities/package-tags/package-tags.test.ts +73 -0
  348. package/src/entities/package-tags/package-tags.ts +234 -0
  349. package/src/entities/package-version/index.ts +2 -0
  350. package/src/entities/package-version/package-version.test.ts +141 -0
  351. package/src/entities/package-version/package-version.ts +234 -0
  352. package/src/entities/package-version/package-version.types.ts +35 -0
  353. package/src/entities/tag/index.ts +2 -0
  354. package/src/entities/tag/tag.test.ts +844 -0
  355. package/src/entities/tag/tag.ts +208 -0
  356. package/src/entities/tag/tag.types.ts +37 -0
  357. package/src/index.ts +7 -0
@@ -0,0 +1,860 @@
1
+ import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
2
+ import type { $ } from "bun";
3
+ import type { IConfig } from "../intershell-config/intershell-config.types";
4
+ import { createMockCommit } from "./commit.test";
5
+ import type { ParsedCommitData } from "./commit.types";
6
+
7
+ const { EntityPr } = await import("./pr");
8
+
9
+ describe("EntityPr", () => {
10
+ let entityPr: InstanceType<typeof EntityPr>;
11
+ let mockConfig: IConfig;
12
+ let mockParseByHash: (hash: string) => Promise<ParsedCommitData>;
13
+
14
+ // Store original methods to restore after tests
15
+ let originalEntitiesShellGitLogHashes: (args: string[]) => $.ShellPromise;
16
+
17
+ beforeEach(async () => {
18
+ // Store original methods if not already stored
19
+ const { entitiesShell } = await import("../entities.shell");
20
+ if (!originalEntitiesShellGitLogHashes) {
21
+ originalEntitiesShellGitLogHashes = entitiesShell.gitLogHashes;
22
+ }
23
+ mockConfig = {
24
+ commit: {
25
+ conventional: {
26
+ type: {
27
+ list: [],
28
+ },
29
+ },
30
+ },
31
+ branch: {
32
+ defaultBranch: "main",
33
+ prefixes: [],
34
+ name: {
35
+ minLength: 1,
36
+ maxLength: 100,
37
+ allowedCharacters: /^[a-zA-Z0-9\-_]+$/,
38
+ noConsecutiveSeparators: false,
39
+ noLeadingTrailingSeparators: false,
40
+ },
41
+ },
42
+ package: {
43
+ selectiveVersioning: {
44
+ enabled: true,
45
+ description: "Selective versioning",
46
+ },
47
+ semanticVersioning: {
48
+ enabled: true,
49
+ description: "Semantic versioning",
50
+ },
51
+ description: {
52
+ enabled: true,
53
+ description: "Package description",
54
+ },
55
+ },
56
+ tag: {
57
+ name: {
58
+ enabled: true,
59
+ description: "Tag validation",
60
+ minLength: 1,
61
+ maxLength: 100,
62
+ allowedCharacters: /^[a-zA-Z0-9\-_.]+$/,
63
+ noSpaces: true,
64
+ noSpecialChars: true,
65
+ },
66
+ },
67
+ } as IConfig;
68
+
69
+ entityPr = new EntityPr(mockConfig);
70
+
71
+ mockParseByHash = mock(async (hash: string) =>
72
+ createMockCommit({ message: { type: "feat" }, info: { hash } }),
73
+ );
74
+ });
75
+
76
+ afterEach(async () => {
77
+ // Restore original methods
78
+ if (originalEntitiesShellGitLogHashes) {
79
+ const { entitiesShell } = await import("../entities.shell");
80
+ entitiesShell.gitLogHashes = originalEntitiesShellGitLogHashes;
81
+ }
82
+ });
83
+
84
+ describe("constructor", () => {
85
+ it("should initialize with config", () => {
86
+ expect(entityPr).toBeInstanceOf(EntityPr);
87
+ });
88
+
89
+ it("should handle config without defaultBranch", () => {
90
+ const configWithoutBranch = {
91
+ commit: {
92
+ conventional: {
93
+ type: {
94
+ list: [],
95
+ },
96
+ },
97
+ },
98
+ branch: {
99
+ defaultBranch: "main",
100
+ prefixes: [],
101
+ name: {
102
+ minLength: 1,
103
+ maxLength: 100,
104
+ allowedCharacters: /^[a-zA-Z0-9\-_]+$/,
105
+ noConsecutiveSeparators: false,
106
+ noLeadingTrailingSeparators: false,
107
+ },
108
+ },
109
+ package: {
110
+ selectiveVersioning: {
111
+ enabled: true,
112
+ description: "Selective versioning",
113
+ },
114
+ semanticVersioning: {
115
+ enabled: true,
116
+ description: "Semantic versioning",
117
+ },
118
+ description: {
119
+ enabled: true,
120
+ description: "Package description",
121
+ },
122
+ },
123
+ tag: {
124
+ name: {
125
+ enabled: true,
126
+ description: "Tag validation",
127
+ minLength: 1,
128
+ maxLength: 100,
129
+ allowedCharacters: /^[a-zA-Z0-9\-_.]+$/,
130
+ noSpaces: true,
131
+ noSpecialChars: true,
132
+ },
133
+ },
134
+ } as IConfig;
135
+ const entityPrWithoutBranch = new EntityPr(configWithoutBranch);
136
+ expect(entityPrWithoutBranch).toBeInstanceOf(EntityPr);
137
+ });
138
+ });
139
+
140
+ describe("getPRInfo", () => {
141
+ it("should handle various PR scenarios and edge cases", async () => {
142
+ const testCases = [
143
+ {
144
+ name: "return undefined for non-PR commits",
145
+ message: createMockCommit().message,
146
+ parseByHash: mockParseByHash,
147
+ expectedResult: undefined,
148
+ expectedAssertions: (result: ParsedCommitData) => {
149
+ expect(result).toBeUndefined();
150
+ },
151
+ },
152
+ {
153
+ name: "return undefined for messages without PR numbers",
154
+ message: createMockCommit({
155
+ message: {
156
+ type: "feat",
157
+ subject: "add new feature",
158
+ description: "add new feature description",
159
+ },
160
+ }).message,
161
+ parseByHash: mockParseByHash,
162
+ expectedResult: undefined,
163
+ expectedAssertions: (result: ParsedCommitData) => {
164
+ expect(result).toBeUndefined();
165
+ },
166
+ },
167
+ {
168
+ name: "extract PR number from merge pull request message",
169
+ message: createMockCommit({
170
+ message: {
171
+ isMerge: true,
172
+ type: "merge",
173
+ subject: "Merge pull request #123 from feature-branch",
174
+ description: "Merge pull request #123 from feature-branch",
175
+ },
176
+ }).message,
177
+ parseByHash: mockParseByHash,
178
+ expectedResult: "123",
179
+ expectedAssertions: (result: ParsedCommitData) => {
180
+ expect(result?.pr?.prNumber).toBe("123");
181
+ expect(result?.pr?.prCategory).toBeDefined();
182
+ expect(result?.pr?.prStats).toBeDefined();
183
+ expect(result?.pr?.prCommits).toBeDefined();
184
+ expect(result?.pr?.prBranchName).toBeDefined();
185
+ },
186
+ },
187
+ {
188
+ name: "extract PR number from merge PR message",
189
+ message: createMockCommit({
190
+ message: {
191
+ isMerge: true,
192
+ type: "merge",
193
+ subject: "Merge pull request #456 from feature-branch",
194
+ description: "Merge pull request #456 from feature-branch",
195
+ },
196
+ }).message,
197
+ parseByHash: mockParseByHash,
198
+ expectedResult: "456",
199
+ expectedAssertions: (result: ParsedCommitData) => {
200
+ expect(result?.pr?.prNumber).toBe("456");
201
+ },
202
+ },
203
+ {
204
+ name: "extract PR number from merge with hash message",
205
+ message: createMockCommit({
206
+ message: {
207
+ isMerge: true,
208
+ type: "merge",
209
+ subject: "Merge pull request #789 from feature-branch",
210
+ description: "Merge pull request #789 from feature-branch",
211
+ },
212
+ }).message,
213
+ parseByHash: mockParseByHash,
214
+ expectedResult: "789",
215
+ expectedAssertions: (result: ParsedCommitData) => {
216
+ expect(result?.pr?.prNumber).toBe("789");
217
+ },
218
+ },
219
+ {
220
+ name: "handle errors gracefully",
221
+ message: createMockCommit({
222
+ message: {
223
+ isMerge: true,
224
+ type: "merge",
225
+ subject: "Merge pull request #123 from feature-branch",
226
+ description: "Merge pull request #123 from feature-branch",
227
+ },
228
+ }).message,
229
+ parseByHash: mock(async () => {
230
+ throw new Error("Parse failed");
231
+ }),
232
+ expectedResult: "123",
233
+ expectedAssertions: (result: ParsedCommitData) => {
234
+ // The function handles errors gracefully and still returns PR info
235
+ // but with empty commits array
236
+ expect(result).toBeDefined();
237
+ expect(result?.pr?.prNumber).toBe("123");
238
+ expect(result?.pr?.prCommits).toEqual([]);
239
+ },
240
+ },
241
+ ];
242
+
243
+ for (const testCase of testCases) {
244
+ const result = await entityPr.getPRInfo(testCase.parseByHash, "abc123", testCase.message);
245
+ if (result) {
246
+ testCase.expectedAssertions({
247
+ message: testCase.message,
248
+ pr: result,
249
+ info: { hash: "abc123" },
250
+ files: [],
251
+ });
252
+ } else {
253
+ // Some test cases expect undefined result (no PR number found)
254
+ expect(result).toBeUndefined();
255
+ }
256
+ }
257
+ });
258
+ });
259
+
260
+ describe("getPrBranch", () => {
261
+ it("should return default branch for non-merge commits", () => {
262
+ const result = entityPr.getPrBranch({
263
+ message: createMockCommit().message,
264
+ });
265
+
266
+ expect(result.name).toBe("main");
267
+ expect(result.fullName).toBe("main");
268
+ });
269
+
270
+ it("should return default branch for merge commits without 'from' in body", () => {
271
+ const message = createMockCommit({
272
+ message: {
273
+ type: "merge",
274
+ subject: "Merge pull request #123",
275
+ description: "Merge pull request #123",
276
+ bodyLines: ["Some merge message"],
277
+ isBreaking: false,
278
+ isMerge: true,
279
+ isDependency: false,
280
+ },
281
+ }).message;
282
+
283
+ const result = entityPr.getPrBranch({ message });
284
+
285
+ expect(result.name).toBe("main");
286
+ expect(result.fullName).toBe("main");
287
+ });
288
+
289
+ it("should extract branch name from merge commit with 'from' in body", () => {
290
+ const message = createMockCommit({
291
+ message: {
292
+ type: "merge",
293
+ subject: "Merge pull request #123",
294
+ description: "Merge pull request #123",
295
+ bodyLines: ["Merge branch 'feature-branch' from origin/feature-branch"],
296
+ isBreaking: false,
297
+ isMerge: true,
298
+ isDependency: false,
299
+ },
300
+ }).message;
301
+
302
+ const result = entityPr.getPrBranch({ message });
303
+
304
+ expect(result.name).toBe("origin/feature-branch");
305
+ expect(result.fullName).toBe("origin/feature-branch");
306
+ });
307
+
308
+ it("should handle config without defaultBranch", () => {
309
+ const entityPrWithoutBranch = new EntityPr({
310
+ commit: {
311
+ conventional: {
312
+ type: {
313
+ list: [
314
+ {
315
+ type: "feat",
316
+ label: "Features",
317
+ description: "New features",
318
+ category: "features",
319
+ emoji: "",
320
+ badgeColor: "",
321
+ breakingAllowed: false,
322
+ },
323
+ {
324
+ type: "fix",
325
+ label: "Bug Fixes",
326
+ description: "Bug fixes",
327
+ category: "other",
328
+ emoji: "",
329
+ badgeColor: "",
330
+ breakingAllowed: false,
331
+ },
332
+ ],
333
+ },
334
+ scopes: { list: [] },
335
+ description: { minLength: 3, maxLength: 100 },
336
+ bodyLines: { minLength: 0, maxLength: 100 },
337
+ isBreaking: {},
338
+ },
339
+ },
340
+ branch: {
341
+ defaultBranch: "",
342
+ prefixes: ["feature", "fix", "chore"],
343
+ name: {
344
+ minLength: 3,
345
+ maxLength: 50,
346
+ allowedCharacters: /^[a-z0-9-]+$/,
347
+ noConsecutiveSeparators: false,
348
+ noLeadingTrailingSeparators: false,
349
+ },
350
+ },
351
+ package: {
352
+ selectiveVersioning: {
353
+ enabled: true,
354
+ description: "Selective versioning",
355
+ },
356
+ semanticVersioning: {
357
+ enabled: true,
358
+ description: "Semantic versioning",
359
+ },
360
+ description: { enabled: true, description: "Package description" },
361
+ },
362
+ tag: {
363
+ name: {
364
+ enabled: true,
365
+ description: "Tag name validation",
366
+ minLength: 0,
367
+ maxLength: 0,
368
+ allowedCharacters: /^[a-zA-Z0-9\-_.]+$/,
369
+ noSpaces: false,
370
+ noSpecialChars: false,
371
+ },
372
+ },
373
+ });
374
+ const message = createMockCommit().message;
375
+
376
+ const result = entityPrWithoutBranch.getPrBranch({ message });
377
+
378
+ expect(result.name).toBe("");
379
+ expect(result.fullName).toBe("");
380
+ });
381
+ });
382
+
383
+ describe("PR number extraction", () => {
384
+ it("should extract PR numbers from various merge message formats", async () => {
385
+ const testCases = [
386
+ {
387
+ message: "Merge pull request #123 from feature-branch",
388
+ expected: "123",
389
+ },
390
+ {
391
+ message: "Merge PR #456 into main",
392
+ expected: "456",
393
+ },
394
+ {
395
+ message: "Merge branch 'feature' into main #789",
396
+ expected: "789",
397
+ },
398
+ ];
399
+
400
+ for (const testCase of testCases) {
401
+ const message = createMockCommit({
402
+ message: {
403
+ type: "merge",
404
+ subject: testCase.message,
405
+ description: testCase.message,
406
+ isMerge: true,
407
+ },
408
+ }).message;
409
+
410
+ const result = await entityPr.getPRInfo(mockParseByHash, "abc123", message);
411
+ expect(result?.prNumber).toBe(testCase.expected);
412
+ }
413
+ });
414
+ });
415
+
416
+ describe("PR categorization", () => {
417
+ it("should categorize as dependencies for renovate/dependabot PRs", async () => {
418
+ const message = createMockCommit({
419
+ message: {
420
+ type: "merge",
421
+ subject: "Merge pull request #123",
422
+ description: "Merge pull request #123 from renovate/dependencies",
423
+ bodyLines: ["Update dependencies"],
424
+ isMerge: true,
425
+ },
426
+ }).message;
427
+
428
+ const result = await entityPr.getPRInfo(mockParseByHash, "abc123", message);
429
+
430
+ // The categorization depends on git command execution which we can't easily mock
431
+ // But we can verify the structure is correct
432
+ expect(result?.prCategory).toBeDefined();
433
+ expect(typeof result?.prCategory).toBe("string");
434
+ });
435
+
436
+ it("should categorize based on commit types", async () => {
437
+ const message = createMockCommit({
438
+ message: {
439
+ type: "merge",
440
+ subject: "Merge pull request #123",
441
+ description: "Merge pull request #123",
442
+ isMerge: true,
443
+ },
444
+ }).message;
445
+
446
+ const result = await entityPr.getPRInfo(mockParseByHash, "abc123", message);
447
+
448
+ // The actual categorization depends on git command execution
449
+ // which we can't easily mock, so we test that categorization exists
450
+ expect(result?.prCategory).toBeDefined();
451
+ expect(typeof result?.prCategory).toBe("string");
452
+ });
453
+ });
454
+
455
+ describe("PR stats", () => {
456
+ it("should return commit count in stats", async () => {
457
+ const message = createMockCommit({
458
+ message: {
459
+ type: "merge",
460
+ subject: "Merge pull request #123",
461
+ description: "Merge pull request #123",
462
+ isMerge: true,
463
+ },
464
+ }).message;
465
+
466
+ const result = await entityPr.getPRInfo(mockParseByHash, "abc123", message);
467
+
468
+ expect(result?.prStats.commitCount).toBeDefined();
469
+ expect(typeof result?.prStats.commitCount).toBe("number");
470
+ });
471
+ });
472
+
473
+ describe("PR commits handling", () => {
474
+ it("should handle various commit scenarios and edge cases", async () => {
475
+ const testCases = [
476
+ {
477
+ name: "multiple commits in regular merge",
478
+ gitLogOutput: "commit1\ncommit2\ncommit3",
479
+ gitLogExitCode: 0,
480
+ parseByHash: mock(async (hash: string) =>
481
+ createMockCommit({
482
+ message: {
483
+ type: "feat",
484
+ subject: `feature ${hash}`,
485
+ description: `feature description ${hash}`,
486
+ },
487
+ info: { hash },
488
+ }),
489
+ ),
490
+ expectedCommitCount: 3,
491
+ expectedDescription: undefined,
492
+ },
493
+ {
494
+ name: "single commit (squash merge)",
495
+ gitLogOutput: "squashed123",
496
+ parseByHash: mock(async (hash: string) =>
497
+ createMockCommit({
498
+ message: {
499
+ type: "feat",
500
+ subject: "squashed feature",
501
+ description: "squashed feature description",
502
+ },
503
+ info: { hash },
504
+ }),
505
+ ),
506
+ expectedCommitCount: 1,
507
+ expectedDescription: "Squashed changes from PR",
508
+ },
509
+ {
510
+ name: "git log range with multiple commits of different types",
511
+ gitLogOutput: "hash1\nhash2\nhash3",
512
+ parseByHash: mock(async (hash: string) => {
513
+ const types = ["feat", "fix", "docs"];
514
+ const typeIndex = Number.parseInt(hash.slice(-1), 10) - 1;
515
+ return createMockCommit({
516
+ message: {
517
+ type: types[typeIndex] || "feat",
518
+ subject: `${types[typeIndex] || "feat"} ${hash}`,
519
+ description: `${types[typeIndex] || "feat"} description ${hash}`,
520
+ },
521
+ info: { hash },
522
+ });
523
+ }),
524
+ expectedCommitCount: 3,
525
+ expectedDescription: undefined,
526
+ },
527
+ {
528
+ name: "parseByHash failures gracefully",
529
+ gitLogOutput: "commit1\nfail123\ncommit3",
530
+ parseByHash: mock(async (hash: string) => {
531
+ if (hash === "fail123") {
532
+ throw new Error("Parse failed");
533
+ }
534
+ return createMockCommit({
535
+ message: {
536
+ type: "feat",
537
+ subject: "successful feature",
538
+ description: "successful feature description",
539
+ },
540
+ info: { hash },
541
+ });
542
+ }),
543
+ expectedCommitCount: undefined, // Just verify it doesn't crash
544
+ expectedDescription: undefined,
545
+ },
546
+ {
547
+ name: "git log failure gracefully",
548
+ gitLogOutput: "error: git log failed",
549
+ gitLogExitCode: 1,
550
+ parseByHash: mockParseByHash,
551
+ expectedCommitCount: 0,
552
+ expectedDescription: undefined,
553
+ },
554
+ {
555
+ name: "empty git log result",
556
+ gitLogOutput: "",
557
+ gitLogExitCode: 0,
558
+ parseByHash: mockParseByHash,
559
+ expectedCommitCount: 0,
560
+ expectedDescription: undefined,
561
+ },
562
+ {
563
+ name: "squashed commit parsing failure",
564
+ gitLogOutput: "squashed123",
565
+ gitLogExitCode: 0,
566
+ parseByHash: mock(async (hash: string) => {
567
+ if (hash === "squashed123") {
568
+ throw new Error("Squashed commit parse failed");
569
+ }
570
+ return createMockCommit({
571
+ message: {
572
+ type: "feat",
573
+ subject: "successful feature",
574
+ description: "successful feature description",
575
+ },
576
+ info: { hash },
577
+ });
578
+ }),
579
+ expectedCommitCount: 0,
580
+ expectedDescription: undefined,
581
+ },
582
+ ];
583
+
584
+ for (const testCase of testCases) {
585
+ // Mock gitLogHashes based on test case
586
+ const mockGitLogHashes = mock(async () => ({
587
+ exitCode: testCase.gitLogExitCode || 0,
588
+ text: () => testCase.gitLogOutput,
589
+ })) as unknown as (args: string[]) => $.ShellPromise;
590
+
591
+ // Assign the mock to entitiesShell
592
+ const { entitiesShell } = await import("../entities.shell");
593
+ entitiesShell.gitLogHashes = mockGitLogHashes;
594
+
595
+ const message = createMockCommit({
596
+ message: {
597
+ type: "merge",
598
+ subject: "Merge pull request #123",
599
+ description: "Merge pull request #123",
600
+ isMerge: true,
601
+ },
602
+ }).message;
603
+
604
+ const result = await entityPr.getPRInfo(testCase.parseByHash, "abc123", message);
605
+
606
+ expect(result).toBeDefined();
607
+ expect(result?.prCommits).toBeDefined();
608
+
609
+ // Verify commit count if specified
610
+ if (testCase.expectedCommitCount !== undefined) {
611
+ expect(result?.prCommits.length).toBe(testCase.expectedCommitCount);
612
+ }
613
+
614
+ // Verify description content if specified
615
+ if (testCase.expectedDescription && result?.prCommits && result.prCommits.length > 0) {
616
+ expect(result.prCommits[0].message.description).toContain(testCase.expectedDescription);
617
+ }
618
+
619
+ // Verify commit info for multi-commit scenarios
620
+ if (testCase.expectedCommitCount && testCase.expectedCommitCount > 1 && result?.prCommits) {
621
+ result.prCommits.forEach((commit) => {
622
+ expect(commit.info?.hash).toBeDefined();
623
+ expect(commit.message.description).toBeDefined();
624
+ });
625
+ }
626
+ }
627
+ });
628
+ });
629
+
630
+ describe("PR categorization edge cases", () => {
631
+ it("should categorize PRs based on commit types and content", async () => {
632
+ const testCases = [
633
+ {
634
+ name: "dependencies when bodyLines contain dependency",
635
+ message: createMockCommit({
636
+ message: {
637
+ type: "merge",
638
+ subject: "Merge pull request #123",
639
+ description: "Merge pull request #123",
640
+ bodyLines: ["This PR updates dependencies", "Other changes"],
641
+ isMerge: true,
642
+ },
643
+ }).message,
644
+ parseByHash: mockParseByHash,
645
+ },
646
+ {
647
+ name: "infrastructure for CI/build commits",
648
+ message: createMockCommit({
649
+ message: {
650
+ type: "merge",
651
+ subject: "Merge pull request #123",
652
+ description: "Merge pull request #123",
653
+ isMerge: true,
654
+ },
655
+ }).message,
656
+ parseByHash: mock(async (hash: string) =>
657
+ createMockCommit({
658
+ message: {
659
+ type: "ci",
660
+ subject: "update CI",
661
+ description: "update CI configuration",
662
+ },
663
+ info: { hash },
664
+ }),
665
+ ),
666
+ },
667
+ {
668
+ name: "bugfixes when fix commits dominate",
669
+ message: createMockCommit({
670
+ message: {
671
+ type: "merge",
672
+ subject: "Merge pull request #123",
673
+ description: "Merge pull request #123",
674
+ isMerge: true,
675
+ },
676
+ }).message,
677
+ parseByHash: mock(async (hash: string) =>
678
+ createMockCommit({
679
+ message: {
680
+ type: "fix",
681
+ subject: "fix bug",
682
+ description: "fix critical bug",
683
+ },
684
+ info: { hash },
685
+ }),
686
+ ),
687
+ },
688
+ {
689
+ name: "documentation for docs commits",
690
+ message: createMockCommit({
691
+ message: {
692
+ type: "merge",
693
+ subject: "Merge pull request #123",
694
+ description: "Merge pull request #123",
695
+ isMerge: true,
696
+ },
697
+ }).message,
698
+ parseByHash: mock(async (hash: string) =>
699
+ createMockCommit({
700
+ message: {
701
+ type: "docs",
702
+ subject: "update docs",
703
+ description: "update documentation",
704
+ },
705
+ info: { hash },
706
+ }),
707
+ ),
708
+ },
709
+ {
710
+ name: "refactoring for refactor/style/perf commits",
711
+ message: createMockCommit({
712
+ message: {
713
+ type: "merge",
714
+ subject: "Merge pull request #123",
715
+ description: "Merge pull request #123",
716
+ isMerge: true,
717
+ },
718
+ }).message,
719
+ parseByHash: mock(async (hash: string) =>
720
+ createMockCommit({
721
+ message: {
722
+ type: "refactor",
723
+ subject: "refactor code",
724
+ description: "improve code structure",
725
+ },
726
+ info: { hash },
727
+ }),
728
+ ),
729
+ },
730
+ {
731
+ name: "dependencies for chore commits with dependency keywords",
732
+ message: createMockCommit({
733
+ message: {
734
+ type: "merge",
735
+ subject: "Merge pull request #123",
736
+ description: "Merge pull request #123",
737
+ isMerge: true,
738
+ },
739
+ }).message,
740
+ parseByHash: mock(async (hash: string) =>
741
+ createMockCommit({
742
+ message: {
743
+ type: "chore",
744
+ subject: "update dependencies",
745
+ description: "update package dependencies",
746
+ },
747
+ info: { hash },
748
+ }),
749
+ ),
750
+ },
751
+ {
752
+ name: "infrastructure for chore commits with CI keywords",
753
+ message: createMockCommit({
754
+ message: {
755
+ type: "merge",
756
+ subject: "Merge pull request #123",
757
+ description: "Merge pull request #123",
758
+ isMerge: true,
759
+ },
760
+ }).message,
761
+ parseByHash: mock(async (hash: string) =>
762
+ createMockCommit({
763
+ message: {
764
+ type: "chore",
765
+ subject: "update CI",
766
+ description: "update CI configuration",
767
+ },
768
+ info: { hash },
769
+ }),
770
+ ),
771
+ },
772
+ {
773
+ name: "other when no clear pattern emerges",
774
+ message: createMockCommit({
775
+ message: {
776
+ type: "merge",
777
+ subject: "Merge pull request #123",
778
+ description: "Merge pull request #123",
779
+ isMerge: true,
780
+ },
781
+ }).message,
782
+ parseByHash: mock(async (_hash: string) =>
783
+ createMockCommit({
784
+ message: {
785
+ type: "other",
786
+ subject: "misc changes",
787
+ description: "various miscellaneous changes",
788
+ },
789
+ info: { hash: "test-hash" },
790
+ }),
791
+ ),
792
+ },
793
+ ];
794
+
795
+ for (const testCase of testCases) {
796
+ const result = await entityPr.getPRInfo(testCase.parseByHash, "abc123", testCase.message);
797
+
798
+ // The categorization depends on git command execution which we can't easily mock
799
+ // But we can verify the structure is correct
800
+ expect(result?.prCategory).toBeDefined();
801
+ expect(typeof result?.prCategory).toBe("string");
802
+ }
803
+ });
804
+
805
+ it("should handle empty PR commits array", async () => {
806
+ // Mock gitLogHashes to return empty result
807
+ const mockGitLogHashes = mock(async () => ({
808
+ text: () => "",
809
+ exitCode: 0,
810
+ })) as unknown as (args: string[]) => $.ShellPromise;
811
+
812
+ // Assign the mock to entitiesShell
813
+ const { entitiesShell } = await import("../entities.shell");
814
+ entitiesShell.gitLogHashes = mockGitLogHashes;
815
+
816
+ const message = createMockCommit({
817
+ message: {
818
+ type: "merge",
819
+ subject: "Merge pull request #123",
820
+ description: "Merge pull request #123",
821
+ isMerge: true,
822
+ },
823
+ }).message;
824
+
825
+ const result = await entityPr.getPRInfo(mockParseByHash, "abc123", message);
826
+
827
+ expect(result).toBeDefined();
828
+ expect(result?.prCommits).toEqual([]);
829
+ expect(result?.prCategory).toBe("other");
830
+ });
831
+
832
+ it("should handle PR commits with missing info", async () => {
833
+ // Mock parseByHash to return commits with missing info
834
+ const incompleteParseByHash = mock(async (_hash: string) =>
835
+ createMockCommit({
836
+ message: {
837
+ type: "feat",
838
+ subject: "feature",
839
+ description: "feature description",
840
+ },
841
+ info: undefined,
842
+ }),
843
+ );
844
+
845
+ const message = createMockCommit({
846
+ message: {
847
+ type: "merge",
848
+ subject: "Merge pull request #123",
849
+ description: "Merge pull request #123",
850
+ isMerge: true,
851
+ },
852
+ }).message;
853
+
854
+ const result = await entityPr.getPRInfo(incompleteParseByHash, "abc123", message);
855
+
856
+ expect(result).toBeDefined();
857
+ expect(result?.prCommits).toBeDefined();
858
+ });
859
+ });
860
+ });