@aaronshaf/ger 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +21 -31
- package/package.json +6 -6
- package/src/cli/index.ts +21 -1
- package/src/prompts/system-inline-review.md +7 -0
- package/src/prompts/system-overall-review.md +35 -17
- package/tests/init.test.ts +70 -0
- package/tests/setup.test.ts +67 -0
- package/tests/status.test.ts +145 -0
- package/tests/workspace.test.ts +295 -0
- package/src/services/config.test.ts +0 -414
- package/tests/unit/utils/prompt-helpers.test.ts +0 -175
package/bun.lock
CHANGED
|
@@ -71,8 +71,6 @@
|
|
|
71
71
|
|
|
72
72
|
"@bundled-es-modules/statuses": ["@bundled-es-modules/statuses@1.0.1", "", { "dependencies": { "statuses": "^2.0.1" } }, "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg=="],
|
|
73
73
|
|
|
74
|
-
"@bundled-es-modules/tough-cookie": ["@bundled-es-modules/tough-cookie@0.1.6", "", { "dependencies": { "@types/tough-cookie": "^4.0.5", "tough-cookie": "^4.1.4" } }, "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw=="],
|
|
75
|
-
|
|
76
74
|
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
|
77
75
|
|
|
78
76
|
"@effect/cluster": ["@effect/cluster@0.46.4", "", { "peerDependencies": { "@effect/platform": "^0.90.0", "@effect/rpc": "^0.68.3", "@effect/sql": "^0.44.1", "@effect/workflow": "^0.8.3", "effect": "^3.17.6" } }, "sha512-81nWw5ABtRZZFmQTrWvfsUnqTg9LybIFYvmsiIL7xQ2t+g6746IZe9Tcv9bSmMdioJLgeuO4CiRg0FfDP2qCWA=="],
|
|
@@ -151,21 +149,21 @@
|
|
|
151
149
|
|
|
152
150
|
"@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
|
|
153
151
|
|
|
154
|
-
"@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.
|
|
152
|
+
"@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.14.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rcTw0QWeOc6IeVp+Up7WtcwdS9l4j7TOq4tihF0Ud/fl+VUVdvDCPuZ9QTnLXJhwMXiyQRWdxRyI6XBwf80ncQ=="],
|
|
155
153
|
|
|
156
|
-
"@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.
|
|
154
|
+
"@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.14.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-TWFSEmyl2/DN4HoXNwQl0y/y3EXFJDctfv5MiDtVOV1GJKX80cGSIxMxXb08Q3CCWqteqEijmfSMo5TG8X1H/A=="],
|
|
157
155
|
|
|
158
|
-
"@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.
|
|
156
|
+
"@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.14.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-N1FqdKfwhVWPpMElv8qlGqdEefTbDYaRVhdGWOjs/2f7FESa5vX0cvA7ToqzkoXyXZI5DqByWiPML33njK30Kg=="],
|
|
159
157
|
|
|
160
|
-
"@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.
|
|
158
|
+
"@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.14.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-v/BPuiateLBb7Gz1STb69EWjkgKdlPQ1NM56z+QQur21ly2hiMkBX2n0zEhqfu9PQVRUizu6AlsYuzcPY/zsIQ=="],
|
|
161
159
|
|
|
162
|
-
"@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.
|
|
160
|
+
"@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.14.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gUTp8KIrSYt97dn+tRRC3LKnH4xlHKCwrPwiDcGmLbCxojuN9/H5mnIhPKEfwNuZNdoKGS/ABuq3neVyvRCRtQ=="],
|
|
163
161
|
|
|
164
|
-
"@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.
|
|
162
|
+
"@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.14.0", "", { "os": "linux", "cpu": "x64" }, "sha512-DpN6cW2HPjYXeENG0JBbmubO8LtfKt6qJqEMBw9gUevbyBaX+k+Jn7sYgh6S23wGOkzmTNphBsf/7ulj4nIVYA=="],
|
|
165
163
|
|
|
166
|
-
"@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.
|
|
164
|
+
"@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.14.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-oXxJksnUTUMgJ0NvjKS1mrCXAy1ttPgIVacRSlxQ+1XHy+aJDMM7I8fsCtoKoEcTIpPaD98eqUqlLYs0H2MGjA=="],
|
|
167
165
|
|
|
168
|
-
"@oxlint/win32-x64": ["@oxlint/win32-x64@1.
|
|
166
|
+
"@oxlint/win32-x64": ["@oxlint/win32-x64@1.14.0", "", { "os": "win32", "cpu": "x64" }, "sha512-iRYy2rhTQKFztyx0jtNMRBnFpzsRwFdjWQ7sKKzJpmbijA3Tw3DCqlGT7QRgoVRF0+X/ccNGvvsrgMohPVfLeQ=="],
|
|
169
167
|
|
|
170
168
|
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
|
171
169
|
|
|
@@ -199,14 +197,12 @@
|
|
|
199
197
|
|
|
200
198
|
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
|
201
199
|
|
|
202
|
-
"@types/node": ["@types/node@24.3.
|
|
200
|
+
"@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="],
|
|
203
201
|
|
|
204
202
|
"@types/react": ["@types/react@19.1.11", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ=="],
|
|
205
203
|
|
|
206
204
|
"@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
|
|
207
205
|
|
|
208
|
-
"@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="],
|
|
209
|
-
|
|
210
206
|
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
|
211
207
|
|
|
212
208
|
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
@@ -287,7 +283,7 @@
|
|
|
287
283
|
|
|
288
284
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
|
289
285
|
|
|
290
|
-
"effect": ["effect@3.17.
|
|
286
|
+
"effect": ["effect@3.17.13", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-JMz5oBxs/6mu4FP9Csjub4jYMUwMLrp+IzUmSDVIzn2NoeoyOXMl7x1lghfr3dLKWffWrdnv/d8nFFdgrHXPqw=="],
|
|
291
287
|
|
|
292
288
|
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
293
289
|
|
|
@@ -393,9 +389,9 @@
|
|
|
393
389
|
|
|
394
390
|
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
|
395
391
|
|
|
396
|
-
"lint-staged": ["lint-staged@16.1.
|
|
392
|
+
"lint-staged": ["lint-staged@16.1.6", "", { "dependencies": { "chalk": "^5.6.0", "commander": "^14.0.0", "debug": "^4.4.1", "lilconfig": "^3.1.3", "listr2": "^9.0.3", "micromatch": "^4.0.8", "nano-spawn": "^1.0.2", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-U4kuulU3CKIytlkLlaHcGgKscNfJPNTiDF2avIUGFCv7K95/DCYQ7Ra62ydeRWmgQGg9zJYw2dzdbztwJlqrow=="],
|
|
397
393
|
|
|
398
|
-
"listr2": ["listr2@9.0.
|
|
394
|
+
"listr2": ["listr2@9.0.3", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-0aeh5HHHgmq1KRdMMDHfhMWQmIT/m7nRDTlxlFqni2Sp0had9baqsjJRvDGdlvgd6NmPE0nPloOipiQJGFtTHQ=="],
|
|
399
395
|
|
|
400
396
|
"locate-path": ["locate-path@2.0.0", "", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA=="],
|
|
401
397
|
|
|
@@ -425,7 +421,7 @@
|
|
|
425
421
|
|
|
426
422
|
"msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="],
|
|
427
423
|
|
|
428
|
-
"msw": ["msw@2.
|
|
424
|
+
"msw": ["msw@2.11.1", "", { "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.39.1", "@open-draft/deferred-promise": "^2.2.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", "@types/statuses": "^2.0.4", "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-dGSRx0AJmQVQfpGXTsAAq4JFdwdhOBdJ6sJS/jnN0ac3s0NZB6daacHF1z5Pefx+IejmvuiLWw260RlyQOf3sQ=="],
|
|
429
425
|
|
|
430
426
|
"multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
|
|
431
427
|
|
|
@@ -455,7 +451,7 @@
|
|
|
455
451
|
|
|
456
452
|
"outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
|
|
457
453
|
|
|
458
|
-
"oxlint": ["oxlint@1.
|
|
454
|
+
"oxlint": ["oxlint@1.14.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.14.0", "@oxlint/darwin-x64": "1.14.0", "@oxlint/linux-arm64-gnu": "1.14.0", "@oxlint/linux-arm64-musl": "1.14.0", "@oxlint/linux-x64-gnu": "1.14.0", "@oxlint/linux-x64-musl": "1.14.0", "@oxlint/win32-arm64": "1.14.0", "@oxlint/win32-x64": "1.14.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.1.5" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-oo0nq3zF9hmgATGc9esoMahLuEESOodUxEDeHDA2K7tbYcSfcmReE9G2QNppnq9rOSQHLTwlMtzGAjjttYaufQ=="],
|
|
459
455
|
|
|
460
456
|
"p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="],
|
|
461
457
|
|
|
@@ -487,22 +483,14 @@
|
|
|
487
483
|
|
|
488
484
|
"pseudomap": ["pseudomap@1.0.2", "", {}, "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="],
|
|
489
485
|
|
|
490
|
-
"psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
|
|
491
|
-
|
|
492
|
-
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
|
493
|
-
|
|
494
486
|
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
|
495
487
|
|
|
496
|
-
"querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="],
|
|
497
|
-
|
|
498
488
|
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
|
|
499
489
|
|
|
500
490
|
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
|
501
491
|
|
|
502
492
|
"require-main-filename": ["require-main-filename@1.0.1", "", {}, "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug=="],
|
|
503
493
|
|
|
504
|
-
"requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
|
|
505
|
-
|
|
506
494
|
"restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
|
|
507
495
|
|
|
508
496
|
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
|
@@ -539,9 +527,13 @@
|
|
|
539
527
|
|
|
540
528
|
"supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
|
541
529
|
|
|
530
|
+
"tldts": ["tldts@7.0.12", "", { "dependencies": { "tldts-core": "^7.0.12" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-M9ZQBPp6FyqhMcl233vHYyYRkxXOA1SKGlnq13S0mJdUhRSwr2w6I8rlchPL73wBwRlyIZpFvpu2VcdSMWLYXw=="],
|
|
531
|
+
|
|
532
|
+
"tldts-core": ["tldts-core@7.0.12", "", {}, "sha512-3K76aXywJFduGRsOYoY5JzINLs/WMlOkeDwPL+8OCPq2Rh39gkSDtWAxdJQlWjpun/xF/LHf29yqCi6VC/rHDA=="],
|
|
533
|
+
|
|
542
534
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
|
543
535
|
|
|
544
|
-
"tough-cookie": ["tough-cookie@
|
|
536
|
+
"tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
|
|
545
537
|
|
|
546
538
|
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
547
539
|
|
|
@@ -551,10 +543,6 @@
|
|
|
551
543
|
|
|
552
544
|
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
|
|
553
545
|
|
|
554
|
-
"universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
|
|
555
|
-
|
|
556
|
-
"url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
|
|
557
|
-
|
|
558
546
|
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
|
|
559
547
|
|
|
560
548
|
"which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
|
@@ -591,6 +579,8 @@
|
|
|
591
579
|
|
|
592
580
|
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
|
593
581
|
|
|
582
|
+
"bun-types/@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
|
|
583
|
+
|
|
594
584
|
"cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
595
585
|
|
|
596
586
|
"cliui/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aaronshaf/ger",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
"homepage": "https://github.com/aaronshaf/ger#readme",
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@biomejs/biome": "^2.2.2",
|
|
19
|
-
"@types/node": "^24.3.
|
|
19
|
+
"@types/node": "^24.3.1",
|
|
20
20
|
"ast-grep": "^0.1.0",
|
|
21
21
|
"bun-types": "^1.2.21",
|
|
22
22
|
"husky": "^9.1.7",
|
|
23
|
-
"lint-staged": "^16.1.
|
|
24
|
-
"msw": "^2.
|
|
25
|
-
"oxlint": "^1.
|
|
23
|
+
"lint-staged": "^16.1.6",
|
|
24
|
+
"msw": "^2.11.1",
|
|
25
|
+
"oxlint": "^1.14.0",
|
|
26
26
|
"typescript": "^5.9.2"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"chalk": "^5.6.0",
|
|
37
37
|
"cli-table3": "^0.6.5",
|
|
38
38
|
"commander": "^14.0.0",
|
|
39
|
-
"effect": "^3.17.
|
|
39
|
+
"effect": "^3.17.13",
|
|
40
40
|
"signal-exit": "3.0.7"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
package/src/cli/index.ts
CHANGED
|
@@ -23,6 +23,9 @@ if (compareSemver(bunVersion, MIN_BUN_VERSION) < 0) {
|
|
|
23
23
|
|
|
24
24
|
import { Command } from 'commander'
|
|
25
25
|
import { Effect } from 'effect'
|
|
26
|
+
import { readFileSync } from 'node:fs'
|
|
27
|
+
import { join, dirname } from 'node:path'
|
|
28
|
+
import { fileURLToPath } from 'node:url'
|
|
26
29
|
import { GerritApiServiceLive } from '@/api/gerrit'
|
|
27
30
|
import { ConfigServiceLive } from '@/services/config'
|
|
28
31
|
import { ReviewStrategyServiceLive } from '@/services/review-strategy'
|
|
@@ -40,9 +43,26 @@ import { showCommand } from './commands/show'
|
|
|
40
43
|
import { statusCommand } from './commands/status'
|
|
41
44
|
import { workspaceCommand } from './commands/workspace'
|
|
42
45
|
|
|
46
|
+
// Read version from package.json
|
|
47
|
+
function getVersion(): string {
|
|
48
|
+
try {
|
|
49
|
+
// Get the directory of the current module
|
|
50
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
51
|
+
const __dirname = dirname(__filename)
|
|
52
|
+
|
|
53
|
+
// Navigate up to the project root and read package.json
|
|
54
|
+
const packageJsonPath = join(__dirname, '..', '..', 'package.json')
|
|
55
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
56
|
+
return packageJson.version || '0.0.0'
|
|
57
|
+
} catch (error) {
|
|
58
|
+
// Fallback version if package.json can't be read
|
|
59
|
+
return '0.0.0'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
43
63
|
const program = new Command()
|
|
44
64
|
|
|
45
|
-
program.name('gi').description('LLM-centric Gerrit CLI tool').version(
|
|
65
|
+
program.name('gi').description('LLM-centric Gerrit CLI tool').version(getVersion())
|
|
46
66
|
|
|
47
67
|
// setup command (new primary command)
|
|
48
68
|
program
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
- **EMPTY ARRAY IS PERFECTLY VALID** for clean code without issues
|
|
10
10
|
- No other text before or after the tags
|
|
11
11
|
|
|
12
|
+
**GERRIT FORMATTING RULES FOR YOUR MESSAGE CONTENT:**
|
|
13
|
+
- Each message starts with "🤖 " (robot emoji and space)
|
|
14
|
+
- Use CAPS for emphasis, NOT markdown bold or italic
|
|
15
|
+
- Reference code using quotes: 'variable' or "function()"
|
|
16
|
+
- NO backticks (`) in your message text
|
|
17
|
+
- Keep explanations clear and concise
|
|
18
|
+
|
|
12
19
|
**START YOUR ANALYSIS NOW. DO NOT ASK QUESTIONS. DO NOT WAIT FOR MORE INPUT.**
|
|
13
20
|
|
|
14
21
|
## JSON Structure for Inline Comments
|
|
@@ -28,6 +28,22 @@ Gerrit uses a LIMITED markdown subset. Follow these rules EXACTLY:
|
|
|
28
28
|
- Always add blank lines between sections for readability
|
|
29
29
|
- Keep code blocks simple and well-spaced
|
|
30
30
|
|
|
31
|
+
**CRITICAL GERRIT FORMATTING RULES:**
|
|
32
|
+
|
|
33
|
+
1. NEVER start regular text lines with spaces - this creates unintended code blocks!
|
|
34
|
+
2. Only use 4 leading spaces when showing actual code examples
|
|
35
|
+
3. Regular text should start at column 1 (no indentation)
|
|
36
|
+
4. When explaining something after a bullet point, don't indent - start a new line
|
|
37
|
+
5. Use blank lines to separate sections and improve readability
|
|
38
|
+
|
|
39
|
+
WRONG (creates code blocks):
|
|
40
|
+
* Issue with authentication
|
|
41
|
+
This explanation will become a code block due to leading spaces
|
|
42
|
+
|
|
43
|
+
CORRECT:
|
|
44
|
+
* Issue with authentication
|
|
45
|
+
This explanation stays as regular text
|
|
46
|
+
|
|
31
47
|
### Content Guidelines
|
|
32
48
|
|
|
33
49
|
1. Start with the most important findings
|
|
@@ -64,22 +80,22 @@ CRITICAL ISSUES
|
|
|
64
80
|
|
|
65
81
|
1. SQL Injection Vulnerability - src/api/users.ts:45
|
|
66
82
|
|
|
67
|
-
|
|
83
|
+
The query construction uses string concatenation with user input:
|
|
68
84
|
|
|
69
85
|
const query = "SELECT * FROM users WHERE id = " + userId
|
|
70
86
|
|
|
71
|
-
|
|
87
|
+
This allows SQL injection attacks. Use parameterized queries:
|
|
72
88
|
|
|
73
89
|
const query = "SELECT * FROM users WHERE id = $1"
|
|
74
90
|
const result = await db.query(query, [userId])
|
|
75
91
|
|
|
76
92
|
2. Authentication Bypass - src/middleware/auth.ts:78-82
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
The token validation can be bypassed when 'debug' header is present:
|
|
79
95
|
|
|
80
96
|
if (req.headers.debug) return next()
|
|
81
97
|
|
|
82
|
-
|
|
98
|
+
This MUST be removed from production code.
|
|
83
99
|
|
|
84
100
|
SIGNIFICANT CONCERNS
|
|
85
101
|
|
|
@@ -103,12 +119,12 @@ Add proper cleanup in a finally block:
|
|
|
103
119
|
PERFORMANCE ANALYSIS
|
|
104
120
|
|
|
105
121
|
- N+1 Query Pattern in src/api/posts.ts:234-248
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
Loading comments for each post individually causes N+1 queries.
|
|
123
|
+
Consider using a single query with JOIN or batch loading.
|
|
108
124
|
|
|
109
125
|
- Unbounded Memory Usage in src/utils/processor.ts:89
|
|
110
|
-
|
|
111
|
-
|
|
126
|
+
Loading entire dataset into memory without pagination.
|
|
127
|
+
For large datasets, this will cause OOM errors.
|
|
112
128
|
|
|
113
129
|
TEST COVERAGE
|
|
114
130
|
|
|
@@ -129,19 +145,19 @@ The security issues are blocking and must be fixed. The performance concerns sho
|
|
|
129
145
|
## Review Tone and Approach
|
|
130
146
|
|
|
131
147
|
1. **Be Direct but Constructive**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
148
|
+
- State issues clearly without hedging
|
|
149
|
+
- Explain impact and provide solutions
|
|
150
|
+
- Focus on the code, not the coder
|
|
135
151
|
|
|
136
152
|
2. **Prioritize Effectively**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
- Lead with blocking issues
|
|
154
|
+
- Group related problems
|
|
155
|
+
- Don't bury critical findings
|
|
140
156
|
|
|
141
157
|
3. **Provide Value**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
- Every comment should help improve the code
|
|
159
|
+
- Skip trivial issues unless they indicate patterns
|
|
160
|
+
- Include concrete fix suggestions
|
|
145
161
|
|
|
146
162
|
## GIT REPOSITORY ACCESS
|
|
147
163
|
|
|
@@ -180,6 +196,8 @@ CRITICAL FORMATTING RULES:
|
|
|
180
196
|
- Use exactly 4 spaces to start each line of code blocks
|
|
181
197
|
- Keep code blocks simple and readable
|
|
182
198
|
- Add proper spacing for readability
|
|
199
|
+
- NEVER indent regular text - start all non-code text at column 1
|
|
200
|
+
- Only code examples should have leading spaces (exactly 4)
|
|
183
201
|
|
|
184
202
|
## TASK SUMMARY
|
|
185
203
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, test, expect } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
describe('Init Command', () => {
|
|
4
|
+
describe('token obscuring', () => {
|
|
5
|
+
test('should obscure short tokens', () => {
|
|
6
|
+
const obscureToken = (token: string): string => {
|
|
7
|
+
if (token.length <= 8) return '****'
|
|
8
|
+
return `${token.substring(0, 4)}****${token.substring(token.length - 4)}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
expect(obscureToken('1234')).toBe('****')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('should obscure long tokens', () => {
|
|
15
|
+
const obscureToken = (token: string): string => {
|
|
16
|
+
if (token.length <= 8) return '****'
|
|
17
|
+
return `${token.substring(0, 4)}****${token.substring(token.length - 4)}`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
expect(obscureToken('verylongpassword123456')).toBe('very****3456')
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe('URL normalization', () => {
|
|
25
|
+
test('should remove trailing slashes', () => {
|
|
26
|
+
const url = 'https://gerrit.example.com/'
|
|
27
|
+
const normalized = url.replace(/\/$/, '')
|
|
28
|
+
expect(normalized).toBe('https://gerrit.example.com')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('input validation', () => {
|
|
33
|
+
test('should require non-empty host', () => {
|
|
34
|
+
const host = ''
|
|
35
|
+
expect(host).toBeFalsy()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('should require non-empty username', () => {
|
|
39
|
+
const username = ''
|
|
40
|
+
expect(username).toBeFalsy()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('should require non-empty password', () => {
|
|
44
|
+
const password = ''
|
|
45
|
+
expect(password).toBeFalsy()
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe('control characters', () => {
|
|
50
|
+
test('should handle Ctrl+C', () => {
|
|
51
|
+
const charCode = '\x03'.charCodeAt(0) // Ctrl+C
|
|
52
|
+
expect(charCode).toBe(3)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('should handle Enter key', () => {
|
|
56
|
+
const charCode = '\r'.charCodeAt(0) // Enter
|
|
57
|
+
expect(charCode).toBe(13)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('should handle backspace', () => {
|
|
61
|
+
const charCode = '\x7f'.charCodeAt(0) // Backspace
|
|
62
|
+
expect(charCode).toBe(127)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('should filter printable characters', () => {
|
|
66
|
+
const charCode = 'a'.charCodeAt(0)
|
|
67
|
+
expect(charCode >= 32 && charCode <= 126).toBe(true)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, test, expect } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
describe('Setup Command', () => {
|
|
4
|
+
describe('URL processing', () => {
|
|
5
|
+
test('should remove trailing slashes', () => {
|
|
6
|
+
const url = 'https://gerrit.example.com/'
|
|
7
|
+
const normalized = url.replace(/\/$/, '')
|
|
8
|
+
expect(normalized).toBe('https://gerrit.example.com')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('should handle URLs without trailing slashes', () => {
|
|
12
|
+
const url = 'https://gerrit.example.com'
|
|
13
|
+
const normalized = url.replace(/\/$/, '')
|
|
14
|
+
expect(normalized).toBe('https://gerrit.example.com')
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('Configuration validation', () => {
|
|
19
|
+
test('should validate required fields', () => {
|
|
20
|
+
const config = {
|
|
21
|
+
host: 'https://gerrit.example.com',
|
|
22
|
+
username: 'testuser',
|
|
23
|
+
password: 'testpass',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
expect(config.host).toBeTruthy()
|
|
27
|
+
expect(config.username).toBeTruthy()
|
|
28
|
+
expect(config.password).toBeTruthy()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('should reject empty required fields', () => {
|
|
32
|
+
const config = {
|
|
33
|
+
host: '',
|
|
34
|
+
username: 'testuser',
|
|
35
|
+
password: 'testpass',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
expect(config.host).toBeFalsy()
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('AI tool detection', () => {
|
|
43
|
+
test('should check for available tools', () => {
|
|
44
|
+
const availableTools = ['claude', 'llm', 'chatgpt']
|
|
45
|
+
expect(availableTools).toContain('claude')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('should handle missing tools', () => {
|
|
49
|
+
const availableTools: string[] = []
|
|
50
|
+
expect(availableTools).not.toContain('nonexistent-tool')
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('Connection verification', () => {
|
|
55
|
+
test('should test connection success scenario', () => {
|
|
56
|
+
const mockResponse = { ok: true, status: 200 }
|
|
57
|
+
expect(mockResponse.ok).toBe(true)
|
|
58
|
+
expect(mockResponse.status).toBe(200)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('should handle connection failures', () => {
|
|
62
|
+
const mockResponse = { ok: false, status: 401 }
|
|
63
|
+
expect(mockResponse.ok).toBe(false)
|
|
64
|
+
expect(mockResponse.status).toBe(401)
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
})
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { describe, test, expect, mock, beforeEach, afterEach } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
// Mock console
|
|
4
|
+
const mockConsole = {
|
|
5
|
+
log: mock(),
|
|
6
|
+
error: mock(),
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Mock global console
|
|
10
|
+
global.console = mockConsole as any
|
|
11
|
+
|
|
12
|
+
describe('Status Command', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
mockConsole.log.mockReset()
|
|
15
|
+
mockConsole.error.mockReset()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
mock.restore()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
describe('pretty output format', () => {
|
|
23
|
+
test('should show success message when connected', () => {
|
|
24
|
+
console.log('✓ Connected to Gerrit successfully!')
|
|
25
|
+
|
|
26
|
+
expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should show failure message when connection fails', () => {
|
|
30
|
+
console.log('✗ Failed to connect to Gerrit')
|
|
31
|
+
console.log('Please check your credentials and network connection')
|
|
32
|
+
|
|
33
|
+
expect(mockConsole.log).toHaveBeenCalledWith('✗ Failed to connect to Gerrit')
|
|
34
|
+
expect(mockConsole.log).toHaveBeenCalledWith(
|
|
35
|
+
'Please check your credentials and network connection',
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('XML output format', () => {
|
|
41
|
+
test('should output XML format when connected successfully', () => {
|
|
42
|
+
console.log('<?xml version="1.0" encoding="UTF-8"?>')
|
|
43
|
+
console.log('<status_result>')
|
|
44
|
+
console.log(' <connected>true</connected>')
|
|
45
|
+
console.log('</status_result>')
|
|
46
|
+
|
|
47
|
+
expect(mockConsole.log).toHaveBeenCalledWith('<?xml version="1.0" encoding="UTF-8"?>')
|
|
48
|
+
expect(mockConsole.log).toHaveBeenCalledWith('<status_result>')
|
|
49
|
+
expect(mockConsole.log).toHaveBeenCalledWith(' <connected>true</connected>')
|
|
50
|
+
expect(mockConsole.log).toHaveBeenCalledWith('</status_result>')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('should output XML format when connection fails', () => {
|
|
54
|
+
console.log('<?xml version="1.0" encoding="UTF-8"?>')
|
|
55
|
+
console.log('<status_result>')
|
|
56
|
+
console.log(' <connected>false</connected>')
|
|
57
|
+
console.log('</status_result>')
|
|
58
|
+
|
|
59
|
+
expect(mockConsole.log).toHaveBeenCalledWith('<?xml version="1.0" encoding="UTF-8"?>')
|
|
60
|
+
expect(mockConsole.log).toHaveBeenCalledWith('<status_result>')
|
|
61
|
+
expect(mockConsole.log).toHaveBeenCalledWith(' <connected>false</connected>')
|
|
62
|
+
expect(mockConsole.log).toHaveBeenCalledWith('</status_result>')
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('option handling', () => {
|
|
67
|
+
test('should handle xml option correctly', () => {
|
|
68
|
+
const options: { xml?: boolean } = { xml: true }
|
|
69
|
+
expect(options.xml).toBe(true)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('should handle undefined xml option correctly', () => {
|
|
73
|
+
const options = { xml: undefined }
|
|
74
|
+
expect(options.xml).toBeUndefined()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('should handle missing xml option', () => {
|
|
78
|
+
const options: { xml?: boolean } = {}
|
|
79
|
+
expect(options.xml).toBeUndefined()
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
describe('connection testing', () => {
|
|
84
|
+
test('should simulate connection success', async () => {
|
|
85
|
+
const mockTestConnection = mock(() => Promise.resolve(true))
|
|
86
|
+
const result = await mockTestConnection()
|
|
87
|
+
expect(result).toBe(true)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('should simulate connection failure', async () => {
|
|
91
|
+
const mockTestConnection = mock(() => Promise.resolve(false))
|
|
92
|
+
const result = await mockTestConnection()
|
|
93
|
+
expect(result).toBe(false)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('should handle connection errors', async () => {
|
|
97
|
+
const mockTestConnection = mock(() => Promise.reject(new Error('Network error')))
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
await mockTestConnection()
|
|
101
|
+
} catch (error: any) {
|
|
102
|
+
expect(error.message).toBe('Network error')
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
describe('console output verification', () => {
|
|
108
|
+
test('should output exactly the expected XML structure', () => {
|
|
109
|
+
const expectedXML = [
|
|
110
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
111
|
+
'<status_result>',
|
|
112
|
+
' <connected>true</connected>',
|
|
113
|
+
'</status_result>',
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
expectedXML.forEach((line) => console.log(line))
|
|
117
|
+
|
|
118
|
+
const calls = mockConsole.log.mock.calls.map((call) => call[0])
|
|
119
|
+
expect(calls).toEqual(expectedXML)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('should output exactly one success message in pretty mode', () => {
|
|
123
|
+
console.log('✓ Connected to Gerrit successfully!')
|
|
124
|
+
|
|
125
|
+
expect(mockConsole.log).toHaveBeenCalledTimes(1)
|
|
126
|
+
expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
describe('status indicators', () => {
|
|
131
|
+
test('should use checkmark for success', () => {
|
|
132
|
+
const successIcon = '✓'
|
|
133
|
+
console.log(`${successIcon} Connected to Gerrit successfully!`)
|
|
134
|
+
|
|
135
|
+
expect(mockConsole.log).toHaveBeenCalledWith('✓ Connected to Gerrit successfully!')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('should use X mark for failure', () => {
|
|
139
|
+
const failureIcon = '✗'
|
|
140
|
+
console.log(`${failureIcon} Failed to connect to Gerrit`)
|
|
141
|
+
|
|
142
|
+
expect(mockConsole.log).toHaveBeenCalledWith('✗ Failed to connect to Gerrit')
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
})
|