fix architecture and write new tests
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { bilingualPrimary, emptyBilingual } from './BilingualInput'
|
||||
|
||||
describe('bilingual field helpers', () => {
|
||||
it('returns a stable empty field shape for French and Arabic labels', () => {
|
||||
expect(emptyBilingual()).toEqual({ fr: '', ar: '' })
|
||||
expect(emptyBilingual()).not.toBe(emptyBilingual())
|
||||
})
|
||||
|
||||
it('prefers French as the primary display value when both translations exist', () => {
|
||||
expect(bilingualPrimary({ fr: 'Assurance', ar: 'تأمين' })).toBe('Assurance')
|
||||
})
|
||||
|
||||
it('falls back to Arabic when the French value is empty', () => {
|
||||
expect(bilingualPrimary({ fr: '', ar: 'تأمين' })).toBe('تأمين')
|
||||
})
|
||||
|
||||
it('does not trim values implicitly so form state remains lossless', () => {
|
||||
expect(bilingualPrimary({ fr: ' Service premium ', ar: 'خدمة' })).toBe(' Service premium ')
|
||||
expect(bilingualPrimary({ fr: '', ar: ' خدمة ' })).toBe(' خدمة ')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,72 @@
|
||||
import React, { isValidElement } from 'react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import StatCard from './StatCard'
|
||||
import type { LucideIcon } from 'lucide-react'
|
||||
|
||||
function collectText(node: unknown): string[] {
|
||||
if (node === null || node === undefined || typeof node === 'boolean') return []
|
||||
if (typeof node === 'string' || typeof node === 'number') return [String(node)]
|
||||
if (Array.isArray(node)) return node.flatMap(collectText)
|
||||
if (isValidElement<{ children?: React.ReactNode }>(node)) return collectText(node.props.children)
|
||||
return []
|
||||
}
|
||||
|
||||
function collectElements(node: unknown): React.ReactElement[] {
|
||||
if (node === null || node === undefined || typeof node === 'boolean') return []
|
||||
if (Array.isArray(node)) return node.flatMap(collectElements)
|
||||
if (!isValidElement<{ children?: React.ReactNode }>(node)) return []
|
||||
return [node, ...collectElements(node.props.children)]
|
||||
}
|
||||
|
||||
function FakeIcon(props: { className?: string }) {
|
||||
return React.createElement('svg', props)
|
||||
}
|
||||
|
||||
const icon = FakeIcon as unknown as LucideIcon
|
||||
|
||||
describe('StatCard', () => {
|
||||
it('renders title, numeric value, and positive changes with a plus sign', () => {
|
||||
const element = StatCard({ title: 'Revenue', value: 12450, change: 8.238, icon })
|
||||
const text = collectText(element)
|
||||
const renderedText = text.join('')
|
||||
|
||||
expect(text).toContain('Revenue')
|
||||
expect(text).toContain('12450')
|
||||
expect(renderedText).toContain('+8.2%')
|
||||
expect(text).toContain('vs last month')
|
||||
})
|
||||
|
||||
it('renders negative changes without forcing a positive marker', () => {
|
||||
const element = StatCard({ title: 'Cancellations', value: '12', change: -3.15, vsLastMonthLabel: 'vs previous period', icon })
|
||||
const text = collectText(element)
|
||||
const renderedText = text.join('')
|
||||
|
||||
expect(renderedText).toContain('-3.1%')
|
||||
expect(text).toContain('vs previous period')
|
||||
expect(renderedText).not.toContain('+-3.1')
|
||||
})
|
||||
|
||||
it('omits the trend row when no change is provided', () => {
|
||||
const element = StatCard({ title: 'Active cars', value: 31, icon })
|
||||
const text = collectText(element)
|
||||
|
||||
expect(text).toContain('Active cars')
|
||||
expect(text).toContain('31')
|
||||
expect(text).not.toContain('vs last month')
|
||||
expect(text.join('')).not.toContain('%')
|
||||
})
|
||||
|
||||
it('passes custom icon color and background classes to the rendered icon shell', () => {
|
||||
const element = StatCard({
|
||||
title: 'Fleet',
|
||||
value: 9,
|
||||
icon,
|
||||
iconColor: 'text-violet-700',
|
||||
iconBg: 'bg-violet-50',
|
||||
})
|
||||
const elements = collectElements(element)
|
||||
|
||||
expect(elements.some((node) => String(node.props.className ?? '').includes('bg-violet-50'))).toBe(true)
|
||||
expect(elements.some((node) => String(node.props.className ?? '').includes('text-violet-700'))).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user