Files
qwen-code/packages/web-shell/client/components/ui/react18-ref-compat.test.tsx
T
ytahdnand钉萁 df5470e430 feat(web-shell): Add workspace file browser and previews (#13878)
* feat(web-shell): Add workspace file browser and previews

* fix(web-shell): Restore source preview CI fixtures and notices

* fix(web-shell): Address file pane review blockers

* fix(web-shell): Resolve review regressions and strengthen file checks

---------

Co-authored-by: 钉萁 <[email protected]>
2026-10-13 09:38:47 +00:00

203 lines
6.2 KiB
TypeScript

// @vitest-environment jsdom
import * as React from 'react';
import { act } from 'react';
import { createRoot } from 'react-dom/client';
import { describe, expect, it } from 'vitest';
import { AlertDialogContent, AlertDialogOverlay } from './alert-dialog';
import { Button } from './button';
import { Checkbox } from './checkbox';
import { DialogContent, DialogOverlay } from './dialog';
import { DrawerContent, DrawerOverlay } from './drawer';
import { DropdownMenuSubTrigger, DropdownMenuTrigger } from './dropdown-menu';
import { Input } from './input';
import {
Popover,
PopoverAnchor,
PopoverContent,
PopoverTrigger,
} from './popover';
import { SelectTrigger } from './select';
import {
ResizablePanelGroup,
ResizablePanel,
ResizableHandle,
} from './resizable';
import {
Table,
TableBody,
TableCaption,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from './table';
import { TabsList } from './tabs';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from './tooltip';
const FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });
describe('React 18 ref compatibility', () => {
it.each([
['AlertDialogContent', AlertDialogContent],
['AlertDialogOverlay', AlertDialogOverlay],
['Button', Button],
['Checkbox', Checkbox],
['DialogContent', DialogContent],
['DialogOverlay', DialogOverlay],
['DrawerContent', DrawerContent],
['DrawerOverlay', DrawerOverlay],
['Input', Input],
['PopoverAnchor', PopoverAnchor],
['PopoverContent', PopoverContent],
['PopoverTrigger', PopoverTrigger],
['DropdownMenuTrigger', DropdownMenuTrigger],
['DropdownMenuSubTrigger', DropdownMenuSubTrigger],
['SelectTrigger', SelectTrigger],
['ResizablePanelGroup', ResizablePanelGroup],
['ResizablePanel', ResizablePanel],
['ResizableHandle', ResizableHandle],
['Table', Table],
['TableHeader', TableHeader],
['TableBody', TableBody],
['TableFooter', TableFooter],
['TableRow', TableRow],
['TableHead', TableHead],
['TableCell', TableCell],
['TableCaption', TableCaption],
['TabsList', TabsList],
['TooltipTrigger', TooltipTrigger],
['TooltipContent', TooltipContent],
])('%s forwards refs', (_name, Component) => {
expect(Component).toHaveProperty('$$typeof', FORWARD_REF_TYPE);
});
it('forwards a Button ref to its DOM element', () => {
const ref = React.createRef<HTMLButtonElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() => root.render(<Button ref={ref}>Button</Button>));
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
act(() => root.unmount());
container.remove();
});
it('forwards a Checkbox ref to its DOM element', () => {
const ref = React.createRef<HTMLButtonElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() => root.render(<Checkbox ref={ref} />));
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
act(() => root.unmount());
container.remove();
});
it('forwards a Table ref to its DOM element', () => {
const ref = React.createRef<HTMLTableElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() => root.render(<Table ref={ref} />));
expect(ref.current).toBeInstanceOf(HTMLTableElement);
act(() => root.unmount());
container.remove();
});
it('forwards an asChild TooltipTrigger ref to its DOM element', () => {
const ref = React.createRef<HTMLButtonElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() =>
root.render(
<TooltipProvider>
<Tooltip>
<TooltipTrigger ref={ref} asChild>
<button type="button">Trigger</button>
</TooltipTrigger>
</Tooltip>
</TooltipProvider>,
),
);
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
act(() => root.unmount());
container.remove();
});
it('forwards a TooltipContent ref to its DOM element', () => {
const ref = React.createRef<HTMLDivElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() =>
root.render(
<TooltipProvider>
<Tooltip open>
<TooltipTrigger>Trigger</TooltipTrigger>
<TooltipContent ref={ref}>Content</TooltipContent>
</Tooltip>
</TooltipProvider>,
),
);
expect(ref.current).toBeInstanceOf(HTMLDivElement);
act(() => root.unmount());
container.remove();
});
it('forwards slotted PopoverAnchor and portaled content refs to their DOM elements', () => {
const anchorRef =
React.createRef<React.ComponentRef<typeof PopoverAnchor>>();
const contentRef = React.createRef<HTMLDivElement>();
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
act(() =>
root.render(
<Popover open>
<PopoverAnchor asChild ref={anchorRef}>
<Button>Context ring</Button>
</PopoverAnchor>
<PopoverContent ref={contentRef} showArrow>
Content
</PopoverContent>
</Popover>,
),
);
expect(anchorRef.current).toBe(container.querySelector('button'));
expect(contentRef.current).toBe(
document.body.querySelector('[data-slot="popover-content"]'),
);
expect(contentRef.current).toBeInstanceOf(HTMLDivElement);
const arrow = contentRef.current!.querySelector('svg')!;
expect(arrow.querySelectorAll('path')).toHaveLength(2);
expect(arrow.style.transform).toBe(
'translateY(var(--floating-arrow-offset))',
);
expect(contentRef.current!.className).toContain(
'[--floating-arrow-offset:-1px]',
);
act(() => root.unmount());
container.remove();
});
});