import { existsSync } from 'node:fs';
import path from 'node:path';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import { describe, expect, it } from 'vitest';
/**
* The one thing that only the *built* package can prove.
*
* `dependencies` is empty because tsup compiles Radix into `dist` instead of
* leaving it to a consumer's install (`noExternal` in tsup.config.ts). That is
* safe only while the build keeps Radix a **single instance**: the dismissable
* layer stack, react-remove-scroll's sidecar and aria-hidden's counter are all
* module-level state, so if code-splitting ever stopped hoisting them into one
* shared chunk, each entry would get a private copy and layered overlays would
* come apart — Escape closing the dialog underneath instead of the menu on top,
* a scroll lock that never releases.
*
* Every other suite in this kit imports from `src`, where that failure cannot
* appear: there is one module graph and Vite resolves it once. So this file
* imports the two entries from `dist` and puts a menu inside a dialog, which is
* the smallest arrangement that needs them to agree.
*
* It is skipped when `dist` is absent, so a fresh clone can run `test:run`
* before `build`; CI builds first, and so does `prepublishOnly`.
*
* Both cases carry explicit timeouts. Unlike every other suite here they pull
* the built bundles in through a dynamic `import()`, which makes Vite transform
* a few hundred kB before the first assertion — enough to overrun Vitest's 5s
* default on a loaded machine and turn a contract guard into a flake that
* someone eventually mutes.
*/
const TEST_TIMEOUT = 20_000;
const WAIT = { timeout: 5_000 };
const DIST = path.resolve(__dirname, '../dist');
const built = existsSync(path.join(DIST, 'components/dialog/index.js'));
describe.skipIf(!built)('built dist — Radix module state is shared', () => {
it('keeps a menu inside a dialog on its own layer', { timeout: TEST_TIMEOUT }, async () => {
const dialog = await import(/* @vite-ignore */ `${DIST}/components/dialog/index.js`);
const menu = await import(/* @vite-ignore */ `${DIST}/components/dropdown-menu/index.js`);
const { Dialog, DialogContent, DialogTitle } = dialog;
const { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } = menu;
const user = userEvent.setup();
function Layered() {
const [menuOpen, setMenuOpen] = React.useState(false);
const [dialogOpen, setDialogOpen] = React.useState(true);
return (
);
}
render(