@aaronshaf/ger 0.1.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 (91) hide show
  1. package/.ast-grep/rules/no-as-casting.yml +13 -0
  2. package/.eslintrc.js +12 -0
  3. package/.github/workflows/ci-simple.yml +53 -0
  4. package/.github/workflows/ci.yml +171 -0
  5. package/.github/workflows/claude-code-review.yml +78 -0
  6. package/.github/workflows/claude.yml +64 -0
  7. package/.github/workflows/dependency-update.yml +84 -0
  8. package/.github/workflows/release.yml +166 -0
  9. package/.github/workflows/security-scan.yml +113 -0
  10. package/.github/workflows/security.yml +96 -0
  11. package/.husky/pre-commit +16 -0
  12. package/.husky/pre-push +25 -0
  13. package/.lintstagedrc.json +6 -0
  14. package/.tool-versions +1 -0
  15. package/CLAUDE.md +103 -0
  16. package/DEVELOPMENT.md +361 -0
  17. package/LICENSE +21 -0
  18. package/README.md +325 -0
  19. package/bin/ger +3 -0
  20. package/biome.json +36 -0
  21. package/bun.lock +688 -0
  22. package/bunfig.toml +8 -0
  23. package/oxlint.json +24 -0
  24. package/package.json +55 -0
  25. package/scripts/check-coverage.ts +69 -0
  26. package/scripts/check-file-size.ts +38 -0
  27. package/scripts/fix-test-mocks.ts +55 -0
  28. package/src/api/gerrit.ts +466 -0
  29. package/src/cli/commands/abandon.ts +65 -0
  30. package/src/cli/commands/comment.ts +460 -0
  31. package/src/cli/commands/comments.ts +85 -0
  32. package/src/cli/commands/diff.ts +71 -0
  33. package/src/cli/commands/incoming.ts +226 -0
  34. package/src/cli/commands/init.ts +164 -0
  35. package/src/cli/commands/mine.ts +115 -0
  36. package/src/cli/commands/open.ts +57 -0
  37. package/src/cli/commands/review.ts +593 -0
  38. package/src/cli/commands/setup.ts +230 -0
  39. package/src/cli/commands/show.ts +303 -0
  40. package/src/cli/commands/status.ts +35 -0
  41. package/src/cli/commands/workspace.ts +200 -0
  42. package/src/cli/index.ts +420 -0
  43. package/src/prompts/default-review.md +80 -0
  44. package/src/prompts/system-inline-review.md +88 -0
  45. package/src/prompts/system-overall-review.md +152 -0
  46. package/src/schemas/config.test.ts +245 -0
  47. package/src/schemas/config.ts +75 -0
  48. package/src/schemas/gerrit.ts +455 -0
  49. package/src/services/ai-enhanced.ts +167 -0
  50. package/src/services/ai.ts +182 -0
  51. package/src/services/config.test.ts +414 -0
  52. package/src/services/config.ts +206 -0
  53. package/src/test-utils/mock-generator.ts +73 -0
  54. package/src/utils/comment-formatters.ts +153 -0
  55. package/src/utils/diff-context.ts +103 -0
  56. package/src/utils/diff-formatters.ts +141 -0
  57. package/src/utils/formatters.ts +85 -0
  58. package/src/utils/message-filters.ts +26 -0
  59. package/src/utils/shell-safety.ts +117 -0
  60. package/src/utils/status-indicators.ts +100 -0
  61. package/src/utils/url-parser.test.ts +123 -0
  62. package/src/utils/url-parser.ts +91 -0
  63. package/tests/abandon.test.ts +163 -0
  64. package/tests/ai-service.test.ts +489 -0
  65. package/tests/comment-batch-advanced.test.ts +431 -0
  66. package/tests/comment-gerrit-api-compliance.test.ts +414 -0
  67. package/tests/comment.test.ts +707 -0
  68. package/tests/comments.test.ts +323 -0
  69. package/tests/config-service-simple.test.ts +100 -0
  70. package/tests/diff.test.ts +419 -0
  71. package/tests/helpers/config-mock.ts +27 -0
  72. package/tests/incoming.test.ts +357 -0
  73. package/tests/interactive-incoming.test.ts +173 -0
  74. package/tests/mine.test.ts +318 -0
  75. package/tests/mocks/fetch-mock.ts +139 -0
  76. package/tests/mocks/msw-handlers.ts +80 -0
  77. package/tests/open.test.ts +233 -0
  78. package/tests/review.test.ts +669 -0
  79. package/tests/setup.ts +13 -0
  80. package/tests/show.test.ts +439 -0
  81. package/tests/unit/schemas/gerrit.test.ts +85 -0
  82. package/tests/unit/test-utils/mock-generator.test.ts +154 -0
  83. package/tests/unit/utils/comment-formatters.test.ts +415 -0
  84. package/tests/unit/utils/diff-context.test.ts +171 -0
  85. package/tests/unit/utils/diff-formatters.test.ts +165 -0
  86. package/tests/unit/utils/formatters.test.ts +411 -0
  87. package/tests/unit/utils/message-filters.test.ts +227 -0
  88. package/tests/unit/utils/prompt-helpers.test.ts +175 -0
  89. package/tests/unit/utils/shell-safety.test.ts +230 -0
  90. package/tests/unit/utils/status-indicators.test.ts +137 -0
  91. package/tsconfig.json +40 -0
@@ -0,0 +1,137 @@
1
+ import { test, expect, describe } from 'bun:test'
2
+ import {
3
+ getStatusIndicators,
4
+ getStatusString,
5
+ getLabelValue,
6
+ getLabelColor,
7
+ DEFAULT_STATUS_INDICATORS,
8
+ } from '@/utils/status-indicators'
9
+ import { generateMockChange } from '@/test-utils/mock-generator'
10
+
11
+ describe('Status Indicators Utility', () => {
12
+ describe('getStatusIndicators', () => {
13
+ test('should return approved indicators for approved changes', () => {
14
+ const change = generateMockChange({
15
+ labels: {
16
+ 'Code-Review': { approved: { _account_id: 1 }, value: 2 },
17
+ Verified: { approved: { _account_id: 1 }, value: 1 },
18
+ },
19
+ })
20
+
21
+ const indicators = getStatusIndicators(change)
22
+ expect(indicators).toEqual(['✓'])
23
+ })
24
+
25
+ test('should return rejected indicators for rejected changes', () => {
26
+ const change = generateMockChange({
27
+ labels: {
28
+ 'Code-Review': { rejected: { _account_id: 1 }, value: -2 },
29
+ Verified: { rejected: { _account_id: 1 }, value: -1 },
30
+ },
31
+ })
32
+
33
+ const indicators = getStatusIndicators(change)
34
+ expect(indicators).toEqual(['✗', '✗'])
35
+ })
36
+
37
+ test('should return recommended and disliked indicators', () => {
38
+ const change1 = generateMockChange({
39
+ labels: {
40
+ 'Code-Review': { recommended: { _account_id: 1 }, value: 1 },
41
+ },
42
+ })
43
+
44
+ const change2 = generateMockChange({
45
+ labels: {
46
+ 'Code-Review': { disliked: { _account_id: 1 }, value: -1 },
47
+ },
48
+ })
49
+
50
+ expect(getStatusIndicators(change1)).toEqual(['↑'])
51
+ expect(getStatusIndicators(change2)).toEqual(['↓'])
52
+ })
53
+
54
+ test('should handle empty labels', () => {
55
+ const change = generateMockChange({ labels: {} })
56
+ expect(getStatusIndicators(change)).toEqual([])
57
+ })
58
+
59
+ test('should handle undefined labels', () => {
60
+ const change = generateMockChange({ labels: undefined })
61
+ expect(getStatusIndicators(change)).toEqual([])
62
+ })
63
+
64
+ test('should use custom indicator config', () => {
65
+ const customConfig = {
66
+ ...DEFAULT_STATUS_INDICATORS,
67
+ approved: '🟢',
68
+ rejected: '🔴',
69
+ }
70
+
71
+ const change = generateMockChange({
72
+ labels: {
73
+ 'Code-Review': { approved: { _account_id: 1 }, value: 2 },
74
+ },
75
+ })
76
+
77
+ const indicators = getStatusIndicators(change, customConfig)
78
+ expect(indicators).toEqual(['🟢'])
79
+ })
80
+ })
81
+
82
+ describe('getStatusString', () => {
83
+ test('should return padded status string', () => {
84
+ const change = generateMockChange({
85
+ labels: {
86
+ 'Code-Review': { recommended: { _account_id: 1 }, value: 1 },
87
+ },
88
+ })
89
+
90
+ const statusString = getStatusString(change, undefined, 10)
91
+ expect(statusString).toBe('↑ ')
92
+ expect(statusString.length).toBe(10)
93
+ })
94
+
95
+ test('should return empty padded string for no indicators', () => {
96
+ const change = generateMockChange({ labels: {} })
97
+ const statusString = getStatusString(change, undefined, 8)
98
+ expect(statusString).toBe(' ')
99
+ expect(statusString.length).toBe(8)
100
+ })
101
+ })
102
+
103
+ describe('getLabelValue', () => {
104
+ test('should extract numeric values correctly', () => {
105
+ expect(getLabelValue({ value: 2 })).toBe(2)
106
+ expect(getLabelValue({ value: -1 })).toBe(-1)
107
+ expect(getLabelValue({ value: 0 })).toBe(0)
108
+ })
109
+
110
+ test('should return 0 for invalid inputs', () => {
111
+ expect(getLabelValue({})).toBe(0)
112
+ expect(getLabelValue({ notValue: 2 })).toBe(0)
113
+ expect(getLabelValue({ value: 'string' })).toBe(0)
114
+ expect(getLabelValue(null)).toBe(0)
115
+ expect(getLabelValue(undefined)).toBe(0)
116
+ expect(getLabelValue('string')).toBe(0)
117
+ expect(getLabelValue(123)).toBe(0)
118
+ })
119
+ })
120
+
121
+ describe('getLabelColor', () => {
122
+ test('should return correct colors for label values', () => {
123
+ expect(getLabelColor(2)).toBe('green')
124
+ expect(getLabelColor(1)).toBe('green')
125
+ expect(getLabelColor(0)).toBe('yellow')
126
+ expect(getLabelColor(-1)).toBe('red')
127
+ expect(getLabelColor(-2)).toBe('red')
128
+ })
129
+
130
+ test('should handle edge cases', () => {
131
+ expect(getLabelColor(0.1)).toBe('green')
132
+ expect(getLabelColor(-0.1)).toBe('red')
133
+ expect(getLabelColor(100)).toBe('green')
134
+ expect(getLabelColor(-100)).toBe('red')
135
+ })
136
+ })
137
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["ESNext"],
4
+ "module": "esnext",
5
+ "target": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "moduleDetection": "force",
8
+ "allowImportingTsExtensions": true,
9
+ "noEmit": true,
10
+ "composite": false,
11
+ "strict": true,
12
+ "downlevelIteration": true,
13
+ "skipLibCheck": true,
14
+ "jsx": "react",
15
+ "allowSyntheticDefaultImports": true,
16
+ "forceConsistentCasingInFileNames": true,
17
+ "allowJs": false,
18
+ "types": [
19
+ "bun-types"
20
+ ],
21
+ "isolatedDeclarations": false,
22
+ "noImplicitAny": true,
23
+ "strictNullChecks": true,
24
+ "strictFunctionTypes": true,
25
+ "strictBindCallApply": true,
26
+ "strictPropertyInitialization": true,
27
+ "noImplicitThis": true,
28
+ "alwaysStrict": true,
29
+ "esModuleInterop": true,
30
+ "resolveJsonModule": true,
31
+ "outDir": "./dist",
32
+ "rootDir": "./",
33
+ "baseUrl": ".",
34
+ "paths": {
35
+ "@/*": ["src/*"]
36
+ }
37
+ },
38
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.json", "tests/**/*.ts", "scripts/**/*.ts"],
39
+ "exclude": ["node_modules", "dist", "tmp", "**/*.js", "**/*.jsx"]
40
+ }