Files
gui/pkgs/core/core-test/webAlignment.web.test.tsx
zeekay ba9f436467 chore: drop 'hanzo' prefix from file/identifier names, use 'gui'/'Gui'
Internal renames so source matches the published @hanzogui/[email protected] dist
(Gui.ts, createGui.ts, views/GuiProvider.mjs, views/GuiRoot.mjs).

Renames applied:
- Files: Hanzogui.ts -> Gui.ts, createHanzogui.ts -> createGui.ts,
  HanzoguiProvider.tsx -> GuiProvider.tsx, HanzoguiRoot[.native].tsx ->
  GuiRoot[.native].tsx, HanzoguiPlugin.ts -> GuiPlugin.ts,
  withHanzogui.ts -> withGui.ts, loadHanzogui.ts -> loadGui.ts,
  v4-hanzogui.ts -> v4-gui.ts, *.d.ts mirrors, hanzogui.config.ts ->
  gui.config.ts, hanzogui.build.ts -> gui.build.ts, hanzogui.css ->
  gui.css, hanzogui-build.js -> gui-build.js, etc.
- Directories: pkgs/core/create-hanzogui -> pkgs/core/create-gui,
  apps/sandbox/config/hanzogui -> apps/sandbox/config/gui.
- Identifiers: Hanzogui* -> Gui*, createHanzogui -> createGui, withHanzogui
  -> withGui, loadHanzogui -> loadGui, HANZOGUI_* env -> GUI_*,
  __hanzogui* globals -> __gui*, hanzoguiOptions/hanzoguiConfig/
  hanzoguiPlugin etc. -> guiOptions/guiConfig/guiPlugin, CSS vars
  --hanzogui-* -> --gui-*, data-hanzogui-* -> data-gui-*, [hanzogui]
  log prefix -> [gui].
- Removed duplicate pkgs/packages/hanzogui-dev-config; the canonical
  pkgs/packages/gui-dev-config (@hanzogui/dev-config) already existed
  with the correct shape. apps/demos now consumes @hanzogui/dev-config.

Preserved (public npm names):
- "hanzogui" umbrella package (pkgs/ui/hanzogui/package.json)
- "@hanzogui/*" namespace
- "hanzogui-loader" package name (pkgs/compiler/loader)
- "hanzogui-build-test-*" test fixture names
- "hanzogui-publish-smoke" workflow id
- pkgs/core/helpers-hanzogui dir (not on rename list)
- apps/gui.hanzo.ai/ marketing site directory
- AGENTS.md symlink restored after perl -i clobbered it

Smoke build (turbo run build): 169/169 workspaces successful.
Sample tests: pkgs/core/core-test getSplitStyles.android* + createGui.web
all green.
2026-05-26 18:25:52 -07:00

332 lines
9.8 KiB
TypeScript

/**
* Web Alignment Tests - Web Platform
*
* These tests verify that Gui v2 uses web-standard props exclusively.
* RN-specific accessibility props are no longer converted - use aria-* directly.
*/
import { View, Text, createGui } from '@hanzogui/core'
import { beforeAll, describe, expect, test } from 'vitest'
import config from '../config-default'
import { simplifiedGetSplitStyles } from './utils'
beforeAll(() => {
createGui(config.getDefaultGuiConfig())
})
describe('Web Alignment - Accessibility Props', () => {
describe('Web props should work (aria-*, role)', () => {
test('aria-label is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-label': 'Test label',
})
expect(viewProps['aria-label']).toBe('Test label')
})
test('aria-labelledby is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-labelledby': 'label-id',
})
expect(viewProps['aria-labelledby']).toBe('label-id')
})
test('aria-describedby is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-describedby': 'desc-id',
})
expect(viewProps['aria-describedby']).toBe('desc-id')
})
test('role is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
role: 'button',
})
expect(viewProps.role).toBe('button')
})
test('aria-hidden is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-hidden': true,
})
expect(viewProps['aria-hidden']).toBe(true)
})
test('aria-disabled is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-disabled': true,
})
expect(viewProps['aria-disabled']).toBe(true)
})
test('aria-checked is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-checked': true,
})
expect(viewProps['aria-checked']).toBe(true)
})
test('aria-expanded is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-expanded': true,
})
expect(viewProps['aria-expanded']).toBe(true)
})
test('aria-selected is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-selected': true,
})
expect(viewProps['aria-selected']).toBe(true)
})
test('aria-busy is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-busy': true,
})
expect(viewProps['aria-busy']).toBe(true)
})
test('aria-live is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-live': 'polite',
})
expect(viewProps['aria-live']).toBe('polite')
})
test('aria-modal is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-modal': true,
})
expect(viewProps['aria-modal']).toBe(true)
})
test('aria-valuemin/max/now/text are passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
'aria-valuemin': 0,
'aria-valuemax': 100,
'aria-valuenow': 50,
'aria-valuetext': '50%',
})
expect(viewProps['aria-valuemin']).toBe(0)
expect(viewProps['aria-valuemax']).toBe(100)
expect(viewProps['aria-valuenow']).toBe(50)
expect(viewProps['aria-valuetext']).toBe('50%')
})
test('id is passed through to viewProps', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
id: 'my-element',
})
expect(viewProps.id).toBe('my-element')
})
})
describe('RN accessibility props are NOT converted (v2)', () => {
test('accessibilityLabel is NOT converted to aria-label', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
accessibilityLabel: 'Test label',
})
// RN props are no longer converted - use aria-label directly
expect(viewProps['aria-label']).toBeUndefined()
})
test('accessibilityRole is NOT converted to role', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
accessibilityRole: 'button',
})
// RN props are no longer converted - use role directly
expect(viewProps.role).toBeUndefined()
})
test('accessibilityLabelledBy is NOT converted to aria-labelledby', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
accessibilityLabelledBy: 'label-id',
})
expect(viewProps['aria-labelledby']).toBeUndefined()
})
test('accessibilityHint is NOT converted to aria-describedby', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
accessibilityHint: 'Test hint',
})
expect(viewProps['aria-describedby']).toBeUndefined()
})
test('accessibilityElementsHidden is NOT converted to aria-hidden', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
accessibilityElementsHidden: true,
})
expect(viewProps['aria-hidden']).toBeUndefined()
})
test('nativeID is NOT converted to id (use id instead)', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
nativeID: 'my-element',
})
// nativeID is no longer converted - use id directly
expect(viewProps.id).toBeUndefined()
})
})
})
describe('Web Alignment - Focus Props', () => {
describe('Web props should work (tabIndex)', () => {
test('tabIndex={0} makes element focusable', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
tabIndex: 0,
})
expect(viewProps.tabIndex).toBe(0)
})
test('tabIndex={-1} makes element not focusable', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
tabIndex: -1,
})
expect(viewProps.tabIndex).toBe(-1)
})
})
describe('RN focus props are NOT converted (v2)', () => {
test('focusable is NOT converted (use tabIndex instead)', () => {
const { viewProps } = simplifiedGetSplitStyles(View, {
focusable: true,
})
// focusable is no longer converted - use tabIndex directly
expect(viewProps.tabIndex).toBeUndefined()
})
})
})
describe('Web Alignment - Event Handlers', () => {
// Note: Event handler tests need to be done at the createComponent level
// since getSplitStyles doesn't handle event attachment
// These tests verify the props are passed through
describe('Web event props should work', () => {
test('onClick is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onClick: handler,
})
expect(viewProps.onClick).toBe(handler)
})
test('onPointerDown is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onPointerDown: handler,
})
expect(viewProps.onPointerDown).toBe(handler)
})
test('onPointerUp is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onPointerUp: handler,
})
expect(viewProps.onPointerUp).toBe(handler)
})
test('onMouseEnter is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onMouseEnter: handler,
})
expect(viewProps.onMouseEnter).toBe(handler)
})
test('onMouseLeave is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onMouseLeave: handler,
})
expect(viewProps.onMouseLeave).toBe(handler)
})
})
describe('RN event props still work (kept for cross-platform compatibility)', () => {
test('onPress is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onPress: handler,
})
// onPress is kept for cross-platform compatibility
expect(viewProps.onPress).toBe(handler)
})
test('onPressIn is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onPressIn: handler,
})
expect(viewProps.onPressIn).toBe(handler)
})
test('onPressOut is passed through to viewProps', () => {
const handler = () => {}
const { viewProps } = simplifiedGetSplitStyles(View, {
onPressOut: handler,
})
expect(viewProps.onPressOut).toBe(handler)
})
})
})
describe('Web Alignment - Shadow Props', () => {
describe('Web props should work (boxShadow)', () => {
test('boxShadow string is applied correctly', () => {
const { rulesToInsert } = simplifiedGetSplitStyles(View, {
boxShadow: '0 2px 10px rgba(0,0,0,0.5)',
})
const boxShadowRule = Object.values(rulesToInsert).find(
(rule: any) => rule[0] === 'boxShadow'
)
expect(boxShadowRule).toBeDefined()
})
})
describe('RN shadow props should NOT work after migration', () => {
// Note: These currently get converted to boxShadow, which is the desired behavior
// But in v2, we want users to use boxShadow directly
// For now, we may keep the conversion as a convenience, or deprecate it
test.skip('shadowColor/shadowOffset/shadowOpacity/shadowRadius should be deprecated', () => {
// This is more of a documentation test - the actual behavior may still work
// but we want to discourage usage via deprecation warnings
})
})
})