mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
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.
332 lines
9.8 KiB
TypeScript
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
|
|
})
|
|
})
|
|
})
|