business-as-code
Version:
Primitives for expressing business logic and processes as code
215 lines (171 loc) • 6.34 kB
text/typescript
/**
* Tests for vision.ts - Vision statement definition and tracking
*/
import { describe, it, expect } from 'vitest'
import { Vision, checkIndicator, calculateProgress, validateVision } from '../src/vision.js'
import type { VisionDefinition } from '../src/types.js'
describe('Vision', () => {
describe('Vision()', () => {
it('should create a vision with required fields', () => {
const vision = Vision({
statement: 'To become the industry leader',
})
expect(vision.statement).toBe('To become the industry leader')
expect(vision.successIndicators).toEqual([])
expect(vision.metadata).toEqual({})
})
it('should create a vision with all fields', () => {
const vision = Vision({
statement: "To become the world's most trusted widget platform",
timeframe: '5 years',
successIndicators: ['10M+ active users', 'Present in 50+ countries', '$1B+ annual revenue'],
metadata: { category: 'growth' },
})
expect(vision.statement).toBe("To become the world's most trusted widget platform")
expect(vision.timeframe).toBe('5 years')
expect(vision.successIndicators).toHaveLength(3)
expect(vision.metadata).toEqual({ category: 'growth' })
})
it('should throw error if statement is empty', () => {
expect(() => Vision({ statement: '' })).toThrow('Vision statement is required')
})
it('should preserve provided success indicators', () => {
const indicators = ['Indicator 1', 'Indicator 2']
const vision = Vision({
statement: 'Test vision',
successIndicators: indicators,
})
expect(vision.successIndicators).toEqual(indicators)
})
})
describe('checkIndicator()', () => {
const vision = Vision({
statement: 'Growth vision',
successIndicators: [
'10M+ active users',
'Present in 50+ countries',
'Industry-leading NPS score',
],
})
it('should return true when indicator matches metric', () => {
const result = checkIndicator(vision, '10M+ active users', {
users: true,
activeUsers: 15000000,
})
expect(result).toBe(true)
})
it('should return false when metric is false', () => {
const result = checkIndicator(vision, '10M+ active users', {
users: false,
})
expect(result).toBe(false)
})
it('should return false when no matching metric', () => {
const result = checkIndicator(vision, '10M+ active users', {
revenue: 1000000,
})
expect(result).toBe(false)
})
it('should match case-insensitively', () => {
const result = checkIndicator(vision, 'Industry-leading NPS score', {
NPS: 75,
})
expect(result).toBe(true)
})
it('should handle numeric values as truthy', () => {
const result = checkIndicator(vision, 'Present in 50+ countries', {
countries: 60,
})
expect(result).toBe(true)
})
it('should handle zero as falsy', () => {
const result = checkIndicator(vision, 'Present in 50+ countries', {
countries: 0,
})
expect(result).toBe(false)
})
})
describe('calculateProgress()', () => {
it('should return 0 for vision with no indicators', () => {
const vision = Vision({ statement: 'Empty vision' })
const progress = calculateProgress(vision, { metric: true })
expect(progress).toBe(0)
})
it('should return 0 when no indicators are achieved', () => {
const vision = Vision({
statement: 'Test vision',
successIndicators: ['10M users', '50 countries'],
})
const progress = calculateProgress(vision, { revenue: 1000000 })
expect(progress).toBe(0)
})
it('should return 100 when all indicators are achieved', () => {
const vision = Vision({
statement: 'Test vision',
successIndicators: ['10M users', '50 countries'],
})
const progress = calculateProgress(vision, {
users: 15000000,
countries: 60,
})
expect(progress).toBe(100)
})
it('should return partial progress', () => {
const vision = Vision({
statement: 'Test vision',
successIndicators: ['users achieved', 'revenue target', 'countries expanded'],
})
const progress = calculateProgress(vision, {
users: true,
revenue: false,
countries: 0,
})
expect(progress).toBeCloseTo(33.33, 0)
})
it('should handle 50% progress', () => {
const vision = Vision({
statement: 'Test vision',
successIndicators: ['users target', 'revenue target'],
})
const progress = calculateProgress(vision, {
users: true,
revenue: 0,
})
expect(progress).toBe(50)
})
})
describe('validateVision()', () => {
it('should validate valid vision', () => {
const vision: VisionDefinition = {
statement: 'To become the industry leader in sustainable technology',
}
const result = validateVision(vision)
expect(result.valid).toBe(true)
expect(result.errors).toHaveLength(0)
})
it('should fail validation if statement is missing', () => {
const vision: VisionDefinition = { statement: '' }
const result = validateVision(vision)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Vision statement is required')
})
it('should fail validation if statement is too short', () => {
const vision: VisionDefinition = { statement: 'Short' }
const result = validateVision(vision)
expect(result.valid).toBe(false)
expect(result.errors).toContain('Vision statement should be at least 10 characters')
})
it('should return multiple errors', () => {
const vision: VisionDefinition = { statement: '' }
const result = validateVision(vision)
// Empty string is both missing and too short
expect(result.valid).toBe(false)
expect(result.errors.length).toBeGreaterThan(0)
})
it('should pass validation for exactly 10 character statement', () => {
const vision: VisionDefinition = { statement: '1234567890' }
const result = validateVision(vision)
expect(result.valid).toBe(true)
})
})
})