business-as-code
Version:
Primitives for expressing business logic and processes as code
283 lines (244 loc) • 8.32 kB
text/typescript
/**
* Tests for business.ts - Business entity definition and management
*/
import { describe, it, expect } from 'vitest'
import {
Business,
getTotalBudget,
getTotalTeamSize,
getDepartment,
getTeam,
validateBusiness,
} from '../src/business.js'
import type { BusinessDefinition } from '../src/types.js'
describe('Business', () => {
describe('Business()', () => {
it('should create a business entity with required fields', () => {
const business = Business({
name: 'Acme Corp',
})
expect(business.name).toBe('Acme Corp')
expect(business.values).toEqual([])
expect(business.teamSize).toBe(0)
expect(business.metadata).toEqual({})
expect(business.foundedAt).toBeInstanceOf(Date)
})
it('should create a business entity with all fields', () => {
const foundedDate = new Date('2020-01-01')
const business = Business({
name: 'Test Corp',
description: 'A test company',
industry: 'Technology',
mission: 'To innovate',
values: ['Innovation', 'Integrity'],
targetMarket: 'Enterprise',
foundedAt: foundedDate,
teamSize: 50,
structure: {
departments: [
{
name: 'Engineering',
head: 'Jane Smith',
members: ['Alice', 'Bob'],
budget: 1000000,
},
],
},
metadata: { customField: 'value' },
})
expect(business.name).toBe('Test Corp')
expect(business.description).toBe('A test company')
expect(business.industry).toBe('Technology')
expect(business.mission).toBe('To innovate')
expect(business.values).toEqual(['Innovation', 'Integrity'])
expect(business.targetMarket).toBe('Enterprise')
expect(business.foundedAt).toBe(foundedDate)
expect(business.teamSize).toBe(50)
expect(business.structure?.departments).toHaveLength(1)
expect(business.metadata).toEqual({ customField: 'value' })
})
it('should throw error if name is empty', () => {
expect(() => Business({ name: '' })).toThrow('Business name is required')
})
it('should preserve provided values and not override with defaults', () => {
const business = Business({
name: 'Test',
values: ['Custom'],
teamSize: 100,
})
expect(business.values).toEqual(['Custom'])
expect(business.teamSize).toBe(100)
})
})
describe('getTotalBudget()', () => {
it('should return 0 if no departments', () => {
const business = Business({ name: 'Test' })
expect(getTotalBudget(business)).toBe(0)
})
it('should return 0 if structure has no departments', () => {
const business = Business({
name: 'Test',
structure: {},
})
expect(getTotalBudget(business)).toBe(0)
})
it('should calculate total budget across departments', () => {
const business = Business({
name: 'Test',
structure: {
departments: [
{ name: 'Engineering', budget: 1000000 },
{ name: 'Sales', budget: 500000 },
{ name: 'HR' }, // No budget specified
],
},
})
expect(getTotalBudget(business)).toBe(1500000)
})
it('should handle departments with zero budget', () => {
const business = Business({
name: 'Test',
structure: {
departments: [
{ name: 'Engineering', budget: 1000000 },
{ name: 'Sales', budget: 0 },
],
},
})
expect(getTotalBudget(business)).toBe(1000000)
})
})
describe('getTotalTeamSize()', () => {
it('should return teamSize if no departments', () => {
const business = Business({ name: 'Test', teamSize: 50 })
expect(getTotalTeamSize(business)).toBe(50)
})
it('should return 0 if no teamSize and no departments', () => {
const business = Business({ name: 'Test' })
expect(getTotalTeamSize(business)).toBe(0)
})
it('should calculate total team size from department members', () => {
const business = Business({
name: 'Test',
structure: {
departments: [
{ name: 'Engineering', members: ['Alice', 'Bob', 'Charlie'] },
{ name: 'Sales', members: ['David', 'Eve'] },
{ name: 'HR' }, // No members
],
},
})
expect(getTotalTeamSize(business)).toBe(5)
})
})
describe('getDepartment()', () => {
const business = Business({
name: 'Test',
structure: {
departments: [
{ name: 'Engineering', head: 'Jane' },
{ name: 'Sales', head: 'John' },
],
},
})
it('should find department by name', () => {
const dept = getDepartment(business, 'Engineering')
expect(dept?.name).toBe('Engineering')
expect(dept?.head).toBe('Jane')
})
it('should return undefined for non-existent department', () => {
const dept = getDepartment(business, 'Marketing')
expect(dept).toBeUndefined()
})
it('should return undefined if no structure', () => {
const simpleBusiness = Business({ name: 'Simple' })
const dept = getDepartment(simpleBusiness, 'Engineering')
expect(dept).toBeUndefined()
})
})
describe('getTeam()', () => {
const business = Business({
name: 'Test',
structure: {
teams: [
{ name: 'Alpha', lead: 'Alice' },
{ name: 'Beta', lead: 'Bob' },
],
},
})
it('should find team by name', () => {
const team = getTeam(business, 'Alpha')
expect(team?.name).toBe('Alpha')
expect(team?.lead).toBe('Alice')
})
it('should return undefined for non-existent team', () => {
const team = getTeam(business, 'Gamma')
expect(team).toBeUndefined()
})
it('should return undefined if no structure', () => {
const simpleBusiness = Business({ name: 'Simple' })
const team = getTeam(simpleBusiness, 'Alpha')
expect(team).toBeUndefined()
})
})
describe('validateBusiness()', () => {
it('should validate valid business', () => {
const business = Business({
name: 'Valid Corp',
teamSize: 50,
})
const result = validateBusiness(business)
expect(result.valid).toBe(true)
expect(result.errors).toHaveLength(0)
})
it('should fail validation if name is missing', () => {
const business: BusinessDefinition = { name: '' }
const result = validateBusiness(business)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Business name is required')
})
it('should fail validation if teamSize is negative', () => {
const business: BusinessDefinition = { name: 'Test', teamSize: -5 }
const result = validateBusiness(business)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Team size cannot be negative')
})
it('should fail validation if department has no name', () => {
const business: BusinessDefinition = {
name: 'Test',
structure: {
departments: [{ name: '', budget: 1000 }],
},
}
const result = validateBusiness(business)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Department name is required')
})
it('should fail validation if department budget is negative', () => {
const business: BusinessDefinition = {
name: 'Test',
structure: {
departments: [{ name: 'Engineering', budget: -1000 }],
},
}
const result = validateBusiness(business)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Department Engineering budget cannot be negative')
})
it('should return multiple errors for multiple issues', () => {
const business: BusinessDefinition = {
name: '',
teamSize: -5,
structure: {
departments: [
{ name: '', budget: 1000 },
{ name: 'Sales', budget: -500 },
],
},
}
const result = validateBusiness(business)
expect(result.valid).toBe(false)
expect(result.errors.length).toBeGreaterThan(1)
})
})
})