mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-04-28 06:59:37 +00:00
Adds unit tests for the project-filter helper: include OR semantics, exclude AND-negation, case-insensitive matching against both project name and projectPath, ordering (exclude applied after include), empty-string edge case, and input immutability.
82 lines
3 KiB
TypeScript
82 lines
3 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
|
|
import { filterProjectsByName } from '../src/parser.js'
|
|
import type { ProjectSummary } from '../src/types.js'
|
|
|
|
function makeProject(project: string, projectPath = project): ProjectSummary {
|
|
return {
|
|
project,
|
|
projectPath,
|
|
sessions: [],
|
|
totalCostUSD: 0,
|
|
totalApiCalls: 0,
|
|
}
|
|
}
|
|
|
|
describe('filterProjectsByName', () => {
|
|
const projects = [
|
|
makeProject('codeburn', '/Users/alice/codeburn'),
|
|
makeProject('AgentSeal', '/Users/alice/projects/AgentSeal'),
|
|
makeProject('dashboard', '/Users/alice/AgentSeal/dashboard'),
|
|
makeProject('sandbox', '/tmp/sandbox'),
|
|
]
|
|
|
|
it('returns all projects when no filters given', () => {
|
|
expect(filterProjectsByName(projects)).toEqual(projects)
|
|
expect(filterProjectsByName(projects, [], [])).toEqual(projects)
|
|
expect(filterProjectsByName(projects, undefined, undefined)).toEqual(projects)
|
|
})
|
|
|
|
it('include matches project name (case-insensitive substring)', () => {
|
|
const result = filterProjectsByName(projects, ['codeburn'])
|
|
expect(result.map(p => p.project)).toEqual(['codeburn'])
|
|
})
|
|
|
|
it('include is case-insensitive', () => {
|
|
const result = filterProjectsByName(projects, ['AGENTSEAL'])
|
|
expect(result.map(p => p.project).sort()).toEqual(['AgentSeal', 'dashboard'])
|
|
})
|
|
|
|
it('include matches substring in path when name does not match', () => {
|
|
const result = filterProjectsByName(projects, ['alice/projects'])
|
|
expect(result.map(p => p.project)).toEqual(['AgentSeal'])
|
|
})
|
|
|
|
it('include uses OR semantics across patterns', () => {
|
|
const result = filterProjectsByName(projects, ['codeburn', 'sandbox'])
|
|
expect(result.map(p => p.project).sort()).toEqual(['codeburn', 'sandbox'])
|
|
})
|
|
|
|
it('exclude removes matching projects (AND-negation across patterns)', () => {
|
|
const result = filterProjectsByName(projects, undefined, ['codeburn', 'sandbox'])
|
|
expect(result.map(p => p.project).sort()).toEqual(['AgentSeal', 'dashboard'])
|
|
})
|
|
|
|
it('exclude matches path substring', () => {
|
|
const result = filterProjectsByName(projects, undefined, ['/tmp'])
|
|
expect(result.map(p => p.project)).not.toContain('sandbox')
|
|
})
|
|
|
|
it('exclude is applied after include', () => {
|
|
const result = filterProjectsByName(projects, ['AgentSeal'], ['dashboard'])
|
|
expect(result.map(p => p.project)).toEqual(['AgentSeal'])
|
|
})
|
|
|
|
it('returns empty array when no project matches include', () => {
|
|
expect(filterProjectsByName(projects, ['does-not-exist'])).toEqual([])
|
|
})
|
|
|
|
it('empty-string pattern matches every project', () => {
|
|
const resultInclude = filterProjectsByName(projects, [''])
|
|
expect(resultInclude).toHaveLength(projects.length)
|
|
const resultExclude = filterProjectsByName(projects, undefined, [''])
|
|
expect(resultExclude).toEqual([])
|
|
})
|
|
|
|
it('does not mutate the input array', () => {
|
|
const input = [makeProject('a'), makeProject('b')]
|
|
const snapshot = [...input]
|
|
filterProjectsByName(input, ['a'], ['b'])
|
|
expect(input).toEqual(snapshot)
|
|
})
|
|
})
|