Files
gui/pkgs/ui/components-test/Select.native.test.tsx
zeekayandHanzo Dev 69c6e860d7 transplant onto tamagui v2.6.0, brand as a re-runnable transform
This repo could never sync. There was NO merge-base with tamagui — 372 commits
here against 15,791 there, unrelated histories — because it began as a
copy-paste rebrand with a flattened layout. Every "sync" since was a hand
re-application that drifted, which is why the tree sat on 7.3.1 while upstream
shipped fixes we then rediscovered by hand.

This commit's PARENT IS TAMAGUI. A future sync is `git merge tama/main` then
`node scripts/rebrand.mjs` — a real merge, because the history is now shared.

174 packages: 166 upstream, our 8 restored (chrome, shell, telemetry, recipes,
get, font-geist-{sans,mono}, @hanzo/booker), bento-get gained. 170/170 build.

Our patches to files UPSTREAM ALSO OWNS are carried, which the package-level
delta missed and which was where the value actually was:
  - useMedia's server snapshot (`initState ?? getMedia()`). Upstream still
    returns undefined there, so every Tamagui Dialog kills a prerender — the
    exact crash hanzo.app spent a day on.
  - data-slot on web host nodes, absent upstream entirely.
Both applied ONTO upstream's newer files (it rewrote useMedia +150/-63 and
createComponent +160/-55), marked `PATCH (ours, carried across the transplant)`.

Seven traps are encoded in scripts/rebrand.mjs, each found by a gate:
skip itself and lockfiles; special-case the double-branded names in BOTH scoped
and bare form; map path strings, not just paths; drop a level for the flattened
group; check disk rather than a stale index.

Rust build artifacts are NOT committed. An earlier draft of this commit swept
apps/desktop/src-tauri/target/debug in via `git add -A` — 3,859 files including
a 272MB .a, over GitHub's 100MB cap, so the push could never have landed. They
are gitignored now.

Co-Authored-By: Hanzo Dev <[email protected]>
2026-07-30 18:25:06 -07:00

108 lines
3.0 KiB
TypeScript

import { Adapt } from '@hanzogui/adapt'
import { getDefaultGuiConfig } from '@hanzogui/config-default'
import { GuiProvider, createGui } from '@hanzogui/core'
import { PortalProvider } from '@hanzogui/portal'
import { Select } from '@hanzogui/select'
import { Sheet } from '@hanzogui/sheet'
import TestRenderer, { act } from 'react-test-renderer'
import { describe, expect, test } from 'vitest'
const conf = createGui(getDefaultGuiConfig())
async function renderSelect(element: React.ReactElement) {
let rendered: TestRenderer.ReactTestRenderer | null = null
await act(async () => {
rendered = TestRenderer.create(
<GuiProvider config={conf} defaultTheme="light">
<PortalProvider shouldAddRootHost>{element}</PortalProvider>
</GuiProvider>
)
})
return rendered!
}
function hasDisplayNone(style: any) {
if (!style) return false
if (Array.isArray(style)) {
return style.some(hasDisplayNone)
}
return style.display === 'none'
}
function isHidden(node: TestRenderer.ReactTestInstance) {
let current: TestRenderer.ReactTestInstance | null = node
while (current) {
if (current.props.display === 'none' || hasDisplayNone(current.props.style)) {
return true
}
current = current.parent
}
return false
}
function visibleTextExists(rendered: TestRenderer.ReactTestRenderer, text: string) {
return (
rendered.root.findAll((node) => {
const children = node.props.children
const hasText = Array.isArray(children)
? children.includes(text)
: children === text
return hasText && !isHidden(node)
}).length > 0
)
}
describe('Select native content', () => {
test('does not render closed items through the native portal fallback', async () => {
const rendered = await renderSelect(
<Select value="">
<Select.Trigger>
<Select.Value placeholder="Search..." />
</Select.Trigger>
<Adapt when="sm">
<Sheet>
<Sheet.Frame>
<Adapt.Contents />
</Sheet.Frame>
<Sheet.Overlay />
</Sheet>
</Adapt>
<Select.Content>
<Select.Viewport>
<Select.Item index={0} value="apple">
<Select.ItemText>Apple</Select.ItemText>
</Select.Item>
</Select.Viewport>
</Select.Content>
</Select>
)
expect(visibleTextExists(rendered, 'Apple')).toBe(false)
})
test('renders the selected item label while closed', async () => {
const rendered = await renderSelect(
<Select value="apple">
<Select.Trigger>
<Select.Value placeholder="Search..." />
</Select.Trigger>
<Select.Content>
<Select.Viewport>
<Select.Item index={0} value="apple">
<Select.ItemText>Apple</Select.ItemText>
</Select.Item>
</Select.Viewport>
</Select.Content>
</Select>
)
expect(visibleTextExists(rendered, 'Apple')).toBe(true)
expect(visibleTextExists(rendered, 'apple')).toBe(false)
})
})