@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.
- package/.ast-grep/rules/no-as-casting.yml +13 -0
- package/.eslintrc.js +12 -0
- package/.github/workflows/ci-simple.yml +53 -0
- package/.github/workflows/ci.yml +171 -0
- package/.github/workflows/claude-code-review.yml +78 -0
- package/.github/workflows/claude.yml +64 -0
- package/.github/workflows/dependency-update.yml +84 -0
- package/.github/workflows/release.yml +166 -0
- package/.github/workflows/security-scan.yml +113 -0
- package/.github/workflows/security.yml +96 -0
- package/.husky/pre-commit +16 -0
- package/.husky/pre-push +25 -0
- package/.lintstagedrc.json +6 -0
- package/.tool-versions +1 -0
- package/CLAUDE.md +103 -0
- package/DEVELOPMENT.md +361 -0
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/bin/ger +3 -0
- package/biome.json +36 -0
- package/bun.lock +688 -0
- package/bunfig.toml +8 -0
- package/oxlint.json +24 -0
- package/package.json +55 -0
- package/scripts/check-coverage.ts +69 -0
- package/scripts/check-file-size.ts +38 -0
- package/scripts/fix-test-mocks.ts +55 -0
- package/src/api/gerrit.ts +466 -0
- package/src/cli/commands/abandon.ts +65 -0
- package/src/cli/commands/comment.ts +460 -0
- package/src/cli/commands/comments.ts +85 -0
- package/src/cli/commands/diff.ts +71 -0
- package/src/cli/commands/incoming.ts +226 -0
- package/src/cli/commands/init.ts +164 -0
- package/src/cli/commands/mine.ts +115 -0
- package/src/cli/commands/open.ts +57 -0
- package/src/cli/commands/review.ts +593 -0
- package/src/cli/commands/setup.ts +230 -0
- package/src/cli/commands/show.ts +303 -0
- package/src/cli/commands/status.ts +35 -0
- package/src/cli/commands/workspace.ts +200 -0
- package/src/cli/index.ts +420 -0
- package/src/prompts/default-review.md +80 -0
- package/src/prompts/system-inline-review.md +88 -0
- package/src/prompts/system-overall-review.md +152 -0
- package/src/schemas/config.test.ts +245 -0
- package/src/schemas/config.ts +75 -0
- package/src/schemas/gerrit.ts +455 -0
- package/src/services/ai-enhanced.ts +167 -0
- package/src/services/ai.ts +182 -0
- package/src/services/config.test.ts +414 -0
- package/src/services/config.ts +206 -0
- package/src/test-utils/mock-generator.ts +73 -0
- package/src/utils/comment-formatters.ts +153 -0
- package/src/utils/diff-context.ts +103 -0
- package/src/utils/diff-formatters.ts +141 -0
- package/src/utils/formatters.ts +85 -0
- package/src/utils/message-filters.ts +26 -0
- package/src/utils/shell-safety.ts +117 -0
- package/src/utils/status-indicators.ts +100 -0
- package/src/utils/url-parser.test.ts +123 -0
- package/src/utils/url-parser.ts +91 -0
- package/tests/abandon.test.ts +163 -0
- package/tests/ai-service.test.ts +489 -0
- package/tests/comment-batch-advanced.test.ts +431 -0
- package/tests/comment-gerrit-api-compliance.test.ts +414 -0
- package/tests/comment.test.ts +707 -0
- package/tests/comments.test.ts +323 -0
- package/tests/config-service-simple.test.ts +100 -0
- package/tests/diff.test.ts +419 -0
- package/tests/helpers/config-mock.ts +27 -0
- package/tests/incoming.test.ts +357 -0
- package/tests/interactive-incoming.test.ts +173 -0
- package/tests/mine.test.ts +318 -0
- package/tests/mocks/fetch-mock.ts +139 -0
- package/tests/mocks/msw-handlers.ts +80 -0
- package/tests/open.test.ts +233 -0
- package/tests/review.test.ts +669 -0
- package/tests/setup.ts +13 -0
- package/tests/show.test.ts +439 -0
- package/tests/unit/schemas/gerrit.test.ts +85 -0
- package/tests/unit/test-utils/mock-generator.test.ts +154 -0
- package/tests/unit/utils/comment-formatters.test.ts +415 -0
- package/tests/unit/utils/diff-context.test.ts +171 -0
- package/tests/unit/utils/diff-formatters.test.ts +165 -0
- package/tests/unit/utils/formatters.test.ts +411 -0
- package/tests/unit/utils/message-filters.test.ts +227 -0
- package/tests/unit/utils/prompt-helpers.test.ts +175 -0
- package/tests/unit/utils/shell-safety.test.ts +230 -0
- package/tests/unit/utils/status-indicators.test.ts +137 -0
- 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
|
+
}
|