@aaronshaf/ger
Version:
Gerrit CLI and SDK - A modern CLI tool and TypeScript SDK for Gerrit Code Review, built with Effect-TS
149 lines (114 loc) • 5.03 kB
text/typescript
import { describe, test, expect } from 'bun:test'
import { CHANGE_ID_PATTERN } from '@/services/commit-hook'
// Pattern matching tests for push command output parsing
// These test regex patterns and string parsing logic used by the push command
// Unit tests for buildPushRefspec are in tests/unit/commands/push.test.ts
describe('Push Command', () => {
describe('remote detection logic', () => {
test('should handle SSH remote format', () => {
const sshRemote = 'git@gerrit.example.com:project.git'
// Extract hostname from SSH format
const hostname = sshRemote.split('@')[1].split(':')[0]
expect(hostname).toBe('gerrit.example.com')
})
test('should handle HTTPS remote format', () => {
const httpsRemote = 'https://gerrit.example.com/project'
const url = new URL(httpsRemote)
expect(url.hostname).toBe('gerrit.example.com')
})
test('should parse remote output format', () => {
const remoteOutput = `origin\thttps://gerrit.example.com/project\t(fetch)
origin\thttps://gerrit.example.com/project\t(push)
upstream\tgit@github.com:org/project.git\t(fetch)
upstream\tgit@github.com:org/project.git\t(push)`
const remotes: Record<string, string> = {}
for (const line of remoteOutput.split('\n')) {
const match = line.match(/^(\S+)\s+(\S+)\s+\(push\)$/)
if (match) {
remotes[match[1]] = match[2]
}
}
expect(remotes['origin']).toBe('https://gerrit.example.com/project')
expect(remotes['upstream']).toBe('git@github.com:org/project.git')
})
})
// Note: refspec building tests are in tests/unit/commands/push.test.ts
describe('change URL extraction', () => {
test('should extract change URL from push output', () => {
const output = `Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 512 bytes | 512.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2)
remote: Processing changes: refs: 1, new: 1, done
remote:
remote: SUCCESS
remote:
remote: https://gerrit.example.com/c/project/+/12345 Fix auth bug [NEW]
remote:
To https://gerrit.example.com/project
* [new reference] HEAD -> refs/for/master`
const urlMatch = output.match(/remote:\s+(https?:\/\/\S+\/c\/\S+\/\+\/\d+)/)
expect(urlMatch).not.toBeNull()
expect(urlMatch![1]).toBe('https://gerrit.example.com/c/project/+/12345')
})
test('should handle output without change URL', () => {
const output = `Everything up-to-date
remote: no new changes`
const urlMatch = output.match(/remote:\s+(https?:\/\/\S+\/c\/\S+\/\+\/\d+)/)
expect(urlMatch).toBeNull()
})
})
describe('commit-msg hook detection', () => {
test('should check for Change-Id in commit message', () => {
const commitWithChangeId = `Fix authentication bug
This commit fixes the login issue.
Change-Id: I1234567890123456789012345678901234567890`
expect(CHANGE_ID_PATTERN.test(commitWithChangeId)).toBe(true)
})
test('should detect missing Change-Id', () => {
const commitWithoutChangeId = `Fix authentication bug
This commit fixes the login issue.`
expect(CHANGE_ID_PATTERN.test(commitWithoutChangeId)).toBe(false)
})
})
describe('error handling', () => {
test('should detect permission denied error', () => {
const errorOutput = 'fatal: remote error: Permission denied (prohibited by Gerrit)'
expect(errorOutput).toContain('prohibited by Gerrit')
})
test('should detect network error', () => {
const errorOutput =
"fatal: unable to access 'https://gerrit.example.com/': Could not resolve host"
expect(errorOutput).toContain('Could not resolve host')
})
test('should detect invalid ref error', () => {
const errorOutput = 'fatal: invalid refspec'
expect(errorOutput).toContain('invalid refspec')
})
test('should detect no new changes', () => {
const output = 'Everything up-to-date\nremote: no new changes'
expect(output).toContain('no new changes')
})
test('should detect authentication failure', () => {
const errorOutput = 'fatal: Authentication failed for'
expect(errorOutput).toContain('Authentication failed')
})
})
describe('git command patterns', () => {
test('should build correct push command args', () => {
const remote = 'origin'
const refspec = 'refs/for/master%topic=test'
const args = ['push', remote, `HEAD:${refspec}`]
expect(args).toEqual(['push', 'origin', 'HEAD:refs/for/master%topic=test'])
})
test('should build correct dry-run push command args', () => {
const remote = 'origin'
const refspec = 'refs/for/master'
const args = ['push', '--dry-run', remote, `HEAD:${refspec}`]
expect(args).toEqual(['push', '--dry-run', 'origin', 'HEAD:refs/for/master'])
})
})
})