Files
gui/pkgs/core/core-test/mergeVariants.web.test.tsx
zeekay 4620297b84 chore(layout): rename code/ → pkgs/ + apps/ + templates/ for cross-repo consistency
Match the layout convention used elsewhere in the Hanzo / Liquidity stack
(pkgs/* for libraries, apps/* for consumer apps, templates/* for starters).

Layout changes:
  pkgs/    ← code/{compiler,core,packages,ui,ui-admin}/
  apps/    ← code/{admin-base,admin-tasks,demos,gui.hanzo.ai,
              kitchen-sink*,sandbox,tests}/
  templates/  ← code/starters/* (flattened — no more starters/ subdir)

Updated:
- package.json workspaces glob.
- All scripts/* path references (postinstall, format, repair, release,
  sync-gui-versions, ci-serve, check-references, etc).
- ../../tasks/scripts/sync-admin-ui.sh — DEFAULT_SRC now points at
  ../gui/apps/admin-tasks (and scrubbed Tamagui mentions in comments).
- ~/work/hanzo/HANZO_BINARY.md doctrine doc.
- ~/work/hanzo/ui/pkg/ui/BASES.md framework-bases doc.
- gui CLAUDE.md, CONTRIBUTING.md.
- Memory entries.

Side-effect fix: ui-admin/src/primitives/index.ts now re-exports
PageShell from ../shell/PageShell. Several IAM identity pages
(GroupEdit, OrgEdit, GroupTree, UserEdit, RoleEdit) imported PageShell
from ./primitives — pre-existing barrel mismatch the test suite missed
because the smoke tests don't full-render. The rename surfaced it via
production build; back-compat re-export keeps both barrels working.

Verification:
- bun install: clean.
- ui-admin tests: 127/127 green.
- admin-tasks vite build: 721 KB JS / 213 KB gzip + 10 KB CSS, clean.
2026-04-27 14:33:21 -07:00

321 lines
7.6 KiB
TypeScript

import { mergeVariants } from '../web/src/helpers/mergeVariants'
import { describe, expect, test } from 'vitest'
describe('mergeVariants', () => {
test('should merge simple variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
medium: { fontSize: 16 },
},
}
const ourVariants = {
size: {
large: { fontSize: 20 },
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 },
medium: { fontSize: 16 },
large: { fontSize: 20 },
},
})
})
test('should override parent variants with our variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12, padding: 8 },
medium: { fontSize: 16, padding: 12 },
},
}
const ourVariants = {
size: {
small: { fontSize: 10 }, // override fontSize but keep padding
medium: { fontSize: 18, margin: 4 }, // override fontSize, keep padding, add margin
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 10, padding: 8 },
medium: { fontSize: 18, padding: 12, margin: 4 },
},
})
})
test('should add new variant keys from our variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
},
}
const ourVariants = {
color: {
primary: { backgroundColor: 'blue' },
secondary: { backgroundColor: 'gray' },
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 },
},
color: {
primary: { backgroundColor: 'blue' },
secondary: { backgroundColor: 'gray' },
},
})
})
test('should handle function variants by overriding parent completely', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
medium: { fontSize: 16 },
},
}
const sizeFunction = (val: any, config: any) => ({
fontSize: val === 'tiny' ? 8 : 14,
})
const ourVariants = {
size: sizeFunction as any,
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: sizeFunction,
})
})
test('should handle empty parent variants', () => {
const parentVariants = {}
const ourVariants = {
size: {
small: { fontSize: 12 },
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 },
},
})
})
test('should handle empty our variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
},
}
const ourVariants = {}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 },
},
})
})
test('should handle undefined parent variants', () => {
const parentVariants = undefined
const ourVariants = {
size: {
small: { fontSize: 12 },
},
}
const result = mergeVariants(parentVariants as any, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 },
},
})
})
test('should handle complex nested variants', () => {
const parentVariants = {
size: {
small: {
fontSize: 12,
padding: 8,
borderRadius: 4,
},
medium: {
fontSize: 16,
padding: 12,
borderRadius: 6,
},
},
variant: {
primary: {
backgroundColor: 'blue',
color: 'white',
},
secondary: {
backgroundColor: 'gray',
color: 'black',
},
},
}
const ourVariants = {
size: {
small: { fontSize: 10 }, // override fontSize
large: { fontSize: 20, padding: 16 }, // new size
},
variant: {
primary: { backgroundColor: 'darkblue' }, // override backgroundColor
tertiary: { backgroundColor: 'green' }, // new variant
},
theme: {
dark: { backgroundColor: 'black' }, // completely new variant key
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 10, padding: 8, borderRadius: 4 },
medium: { fontSize: 16, padding: 12, borderRadius: 6 },
large: { fontSize: 20, padding: 16 },
},
variant: {
primary: { backgroundColor: 'darkblue', color: 'white' },
secondary: { backgroundColor: 'gray', color: 'black' },
tertiary: { backgroundColor: 'green' },
},
theme: {
dark: { backgroundColor: 'black' },
},
})
})
test('should handle mixed function and object variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
medium: { fontSize: 16 },
},
color: ((val: any, config: any) => ({ color: val })) as any,
}
const ourVariants = {
size: ((val: any, config: any) => ({ fontSize: val === 'tiny' ? 8 : 20 })) as any, // function overrides object
color: {
primary: { color: 'blue' }, // object will merge with parent function, but object wins due to spread order
},
}
const result = mergeVariants(parentVariants, ourVariants) as any
expect(result.size).toBeTypeOf('function') // function overrides object
expect(result.color).toBeTypeOf('object') // object overwrites parent function due to spread order
expect(result.color).toEqual({ primary: { color: 'blue' } })
})
test('should handle deep nesting levels correctly', () => {
const parentVariants = {
responsive: {
mobile: {
small: { fontSize: 12 },
medium: { fontSize: 14 },
},
desktop: {
small: { fontSize: 14 },
medium: { fontSize: 16 },
},
},
}
const ourVariants = {
responsive: {
mobile: {
small: { fontSize: 10 }, // override
large: { fontSize: 16 }, // new
},
tablet: {
small: { fontSize: 12 }, // completely new
},
},
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
responsive: {
mobile: {
small: { fontSize: 10 },
medium: { fontSize: 14 },
large: { fontSize: 16 },
},
desktop: {
small: { fontSize: 14 },
medium: { fontSize: 16 },
},
tablet: {
small: { fontSize: 12 },
},
},
})
})
test('should preserve parent variants not present in our variants', () => {
const parentVariants = {
size: {
small: { fontSize: 12 },
medium: { fontSize: 16 },
large: { fontSize: 20 },
},
color: {
primary: { backgroundColor: 'blue' },
secondary: { backgroundColor: 'gray' },
},
}
const ourVariants = {
size: {
medium: { fontSize: 18 }, // only override medium
},
// no color variants in our variants
}
const result = mergeVariants(parentVariants, ourVariants)
expect(result).toEqual({
size: {
small: { fontSize: 12 }, // preserved
medium: { fontSize: 18 }, // overridden
large: { fontSize: 20 }, // preserved
},
color: {
primary: { backgroundColor: 'blue' }, // preserved
secondary: { backgroundColor: 'gray' }, // preserved
},
})
})
})