Skip to content

Commit

Permalink
feat: add more tests in utils folder- part 2
Browse files Browse the repository at this point in the history
Signed-off-by: Calvin Lee <[email protected]>
  • Loading branch information
cjlee1 committed Feb 28, 2025
1 parent e3b24e6 commit 40cac08
Show file tree
Hide file tree
Showing 5 changed files with 635 additions and 0 deletions.
42 changes: 42 additions & 0 deletions apps/gitness/src/utils/__tests__/error-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { describe, expect, it } from 'vitest'

import { getErrorMessage } from '../error-utils'

// Define a custom error type for testing
interface CustomError {
data?: {
error?: string
message?: string
}
message?: string
}

describe('getErrorMessage', () => {
it('should handle undefined error', () => {
expect(getErrorMessage(undefined)).toBeUndefined()
})

it('should handle null error', () => {
expect(getErrorMessage(null)).toBeUndefined()
})

it('should extract error from data.error', () => {
const error: CustomError = { data: { error: 'Test error message' } }
expect(getErrorMessage(error)).toBe('Test error message')
})

it('should extract error from data.message', () => {
const error: CustomError = { data: { message: 'Test message' } }
expect(getErrorMessage(error)).toBe('Test message')
})

it('should extract error from message', () => {
const error: CustomError = { message: 'Direct message' }
expect(getErrorMessage(error)).toBe('Direct message')
})

it('should return error as string if no structured format is found', () => {
const error = 'Plain error string'
expect(getErrorMessage(error)).toBe('Plain error string')
})
})
123 changes: 123 additions & 0 deletions apps/gitness/src/utils/__tests__/execution-utils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { describe, expect, it } from 'vitest'

import { EnumCiStatus, TypesExecution } from '@harnessio/code-service-client'
import { MeterState } from '@harnessio/ui/components'
import { PipelineExecutionStatus } from '@harnessio/ui/views'

import { getExecutionStatus, getLabel, getMeterState } from '../execution-utils'

describe('getLabel', () => {
it('should return empty string for missing author_name or event', () => {
const baseExecution: TypesExecution = {
number: 1,
status: 'success' as EnumCiStatus,
created: 0,
updated: 0,
started: 0,
finished: 0
}

expect(getLabel({ ...baseExecution, author_name: '', event: undefined })).toBe('')
expect(getLabel({ ...baseExecution, author_name: 'test', event: undefined })).toBe('')
expect(getLabel({ ...baseExecution, author_name: '', event: 'manual' })).toBe('')
})

it('should handle manual event', () => {
const execution: TypesExecution = {
author_name: 'John Doe',
event: 'manual',
number: 1,
status: 'success' as EnumCiStatus,
created: 0,
updated: 0,
started: 0,
finished: 0
}
expect(getLabel(execution)).toBe('John Doe triggered manually')
})

it('should handle pull_request event with source and target', () => {
const execution: TypesExecution = {
author_name: 'John Doe',
event: 'pull_request',
source: 'feature',
target: 'main',
number: 1,
status: 'success' as EnumCiStatus,
created: 0,
updated: 0,
started: 0,
finished: 0
}
const result = getLabel(execution)
expect(result).toBeTruthy() // Since it returns a React element, we just verify it's not null
})
})
describe('getExecutionStatus', () => {
it('should map running status correctly', () => {
expect(getExecutionStatus('running')).toBe(PipelineExecutionStatus.RUNNING)
})

it('should map success status correctly', () => {
expect(getExecutionStatus('success')).toBe(PipelineExecutionStatus.SUCCESS)
})

it('should map failure status correctly', () => {
expect(getExecutionStatus('failure')).toBe(PipelineExecutionStatus.FAILURE)
})

it('should map error status correctly', () => {
expect(getExecutionStatus('error')).toBe(PipelineExecutionStatus.ERROR)
})

it('should map killed status correctly', () => {
expect(getExecutionStatus('killed')).toBe(PipelineExecutionStatus.KILLED)
})

it('should return UNKNOWN for undefined status', () => {
expect(getExecutionStatus(undefined)).toBe(PipelineExecutionStatus.UNKNOWN)
})

it('should return UNKNOWN for invalid status', () => {
const invalidStatus = 'invalid' as EnumCiStatus
expect(getExecutionStatus(invalidStatus)).toBe(PipelineExecutionStatus.UNKNOWN)
})
})

describe('getMeterState', () => {
it('should return Error state for failure status', () => {
expect(getMeterState(PipelineExecutionStatus.FAILURE)).toBe(MeterState.Error)
})

it('should return Error state for killed status', () => {
expect(getMeterState(PipelineExecutionStatus.KILLED)).toBe(MeterState.Error)
})

it('should return Error state for error status', () => {
expect(getMeterState(PipelineExecutionStatus.ERROR)).toBe(MeterState.Error)
})

it('should return Success state for success status', () => {
expect(getMeterState(PipelineExecutionStatus.SUCCESS)).toBe(MeterState.Success)
})

it('should return Warning state for skipped status', () => {
expect(getMeterState(PipelineExecutionStatus.SKIPPED)).toBe(MeterState.Warning)
})

it('should return Warning state for blocked status', () => {
expect(getMeterState(PipelineExecutionStatus.BLOCKED)).toBe(MeterState.Warning)
})

it('should return Empty state for pending status', () => {
expect(getMeterState(PipelineExecutionStatus.PENDING)).toBe(MeterState.Empty)
})

it('should return Empty state for waiting on dependencies status', () => {
expect(getMeterState(PipelineExecutionStatus.WAITING_ON_DEPENDENCIES)).toBe(MeterState.Empty)
})

it('should return Empty state for undefined status', () => {
expect(getMeterState(undefined)).toBe(MeterState.Empty)
})
})
183 changes: 183 additions & 0 deletions apps/gitness/src/utils/__tests__/git-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import langMap from 'lang-map'
import { describe, expect, it, vi } from 'vitest'

import {
decodeGitContent,
filenameToLanguage,
formatBytes,
getTrimmedSha,
GitCommitAction,
isGitRev,
isRefABranch,
isRefATag,
normalizeGitRef,
REFS_BRANCH_PREFIX,
REFS_TAGS_PREFIX
} from '../git-utils'

describe('formatBytes', () => {
it('should format bytes correctly', () => {
expect(formatBytes(0)).toBe('0 Bytes')
expect(formatBytes(1024)).toBe('1 KB')
expect(formatBytes(1024 * 1024)).toBe('1 MB')
expect(formatBytes(1024 * 1024 * 1024)).toBe('1 GB')
})

it('should handle decimal places correctly', () => {
expect(formatBytes(1234, 1)).toBe('1.2 KB')
expect(formatBytes(1234, 0)).toBe('1 KB')
expect(formatBytes(1234, 3)).toBe('1.205 KB')
})

it('should handle negative decimals', () => {
expect(formatBytes(1234, -1)).toBe('1 KB')
})
})

describe('decodeGitContent', () => {
const mockConsoleError = vi.spyOn(console, 'error')
const mockAtob = vi.spyOn(window, 'atob')

beforeEach(() => {
mockConsoleError.mockImplementation(() => {})
mockAtob.mockImplementation(str => Buffer.from(str, 'base64').toString())
})

afterEach(() => {
mockConsoleError.mockRestore()
mockAtob.mockRestore()
})

it('should decode base64 content correctly', () => {
const base64Content = Buffer.from('Hello World').toString('base64')
expect(decodeGitContent(base64Content)).toBe('Hello World')
})

it('should handle empty content', () => {
expect(decodeGitContent()).toBe('')
expect(decodeGitContent('')).toBe('')
})

it('should handle invalid base64 content', () => {
expect(decodeGitContent('invalid-base64')).toBe('invalid-base64')
})

it('should handle decoding errors', () => {
mockAtob.mockImplementation(() => {
throw new Error('Decoding error')
})
expect(decodeGitContent('error-content')).toBe('error-content')
expect(mockConsoleError).toHaveBeenCalled()
})
})

describe('filenameToLanguage', () => {
const mockLanguagesMap = new Map<string, string[]>([
['js', ['javascript']],
['py', ['python']],
['go', ['go']],
['ts', ['typescript']]
])

const mockLanguages = vi.spyOn(langMap, 'languages')

beforeEach(() => {
mockLanguages.mockImplementation(ext => mockLanguagesMap.get(ext) || [])
})

afterEach(() => {
mockLanguages.mockRestore()
})

it('should detect common file extensions', () => {
expect(filenameToLanguage('test.js')).toBe('javascript')
expect(filenameToLanguage('test.py')).toBe('python')
expect(filenameToLanguage('test.go')).toBe('go')
expect(filenameToLanguage('test.ts')).toBe('typescript')
})

it('should map special extensions correctly', () => {
expect(filenameToLanguage('test.jsx')).toBe('typescript')
expect(filenameToLanguage('test.tsx')).toBe('typescript')
expect(filenameToLanguage('.gitignore')).toBe('shell')
expect(filenameToLanguage('Dockerfile')).toBe('dockerfile')
})

it('should handle extensions from lang-map that match Monaco supported languages', () => {
mockLanguages.mockReturnValueOnce(['typescript', 'javascript'])
expect(filenameToLanguage('test.custom')).toBe('typescript')
})

it('should return plaintext for unknown extensions', () => {
expect(filenameToLanguage('test.unknown')).toBe('plaintext')
expect(filenameToLanguage('')).toBe('plaintext')
expect(filenameToLanguage(undefined)).toBe('plaintext')
})
})

describe('Git Reference Functions', () => {
describe('isRefATag', () => {
it('should identify tag references', () => {
expect(isRefATag(REFS_TAGS_PREFIX + 'v1.0.0')).toBe(true)
expect(isRefATag('v1.0.0')).toBe(false)
expect(isRefATag(undefined)).toBe(false)
})
})

describe('isRefABranch', () => {
it('should identify branch references', () => {
expect(isRefABranch(REFS_BRANCH_PREFIX + 'main')).toBe(true)
expect(isRefABranch('main')).toBe(false)
expect(isRefABranch(undefined)).toBe(false)
})
})

describe('isGitRev', () => {
it('should identify valid git commit hashes', () => {
expect(isGitRev('1234567')).toBe(true)
expect(isGitRev('1234567890abcdef1234567890abcdef12345678')).toBe(true)
expect(isGitRev('123456')).toBe(false) // Too short
expect(isGitRev('123456g')).toBe(false) // Invalid character
expect(isGitRev('')).toBe(false)
})
})

describe('normalizeGitRef', () => {
it('should handle undefined input', () => {
expect(normalizeGitRef(undefined)).toBe('refs/heads/undefined')
})

it('should normalize git references correctly', () => {
const tag = REFS_TAGS_PREFIX + 'v1.0.0'
const branch = REFS_BRANCH_PREFIX + 'main'
const commit = '1234567890abcdef1234567890abcdef12345678'

expect(normalizeGitRef(tag)).toBe(tag)
expect(normalizeGitRef(branch)).toBe(branch)
expect(normalizeGitRef(commit)).toBe(commit)
expect(normalizeGitRef('main')).toBe('refs/heads/main')
expect(normalizeGitRef('')).toBe('')
})
})
})

describe('getTrimmedSha', () => {
it('should trim SHA to 7 characters', () => {
const fullSha = '1234567890abcdef1234567890abcdef12345678'
expect(getTrimmedSha(fullSha)).toBe('1234567')
})

it('should handle short SHA', () => {
const shortSha = '1234567'
expect(getTrimmedSha(shortSha)).toBe('1234567')
})
})

describe('GitCommitAction enum', () => {
it('should have correct enum values', () => {
expect(GitCommitAction.DELETE).toBe('DELETE')
expect(GitCommitAction.CREATE).toBe('CREATE')
expect(GitCommitAction.UPDATE).toBe('UPDATE')
expect(GitCommitAction.MOVE).toBe('MOVE')
})
})
Loading

0 comments on commit 40cac08

Please sign in to comment.