@avgz/react-contract-renderer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -0
- package/dist/THIRD_PARTY_LICENSES.txt +334 -0
- package/dist/adapters/dom.d.cts +5 -0
- package/dist/adapters/dom.d.ts +5 -0
- package/dist/adapters/react17.cjs +18657 -0
- package/dist/adapters/react18.cjs +20627 -0
- package/dist/adapters/react19_0.cjs +20014 -0
- package/dist/adapters/react19_1.cjs +20319 -0
- package/dist/adapters/react19_2.cjs +22561 -0
- package/dist/adapters/react19_3.cjs +24506 -0
- package/dist/adapters/reconciler.d.cts +19 -0
- package/dist/adapters/reconciler.d.ts +19 -0
- package/dist/index.cjs +1010 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.cts +82 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +2 -0
- package/dist/internal.d.cts +30 -0
- package/dist/internal.d.ts +30 -0
- package/dist/mount.d.cts +2 -0
- package/dist/mount.d.ts +2 -0
- package/dist/shallow.d.cts +2 -0
- package/dist/shallow.d.ts +2 -0
- package/dist/subject.d.cts +35 -0
- package/dist/subject.d.ts +35 -0
- package/package.json +86 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/mount.ts", "../src/adapters/dom.ts", "../src/internal.ts", "../src/shallow.ts", "../src/adapters/reconciler.ts", "../src/subject.ts"],
|
|
4
|
+
"sourcesContent": ["import { createElement } from 'react';\nimport type {\n ComponentProps,\n ComponentType,\n ElementType,\n ReactElement,\n ReactNode,\n} from 'react';\nimport type { DriverFactory, PropRecord, RenderDriver } from './internal.js';\nimport { createMountDriver } from './mount.js';\nimport { createShallowDriver } from './shallow.js';\nimport { Subject } from './subject.js';\n\nexport { Subject } from './subject.js';\n\n/** A React provider applied around every render session with {@link RenderSession.with}. */\nexport type Provider = ComponentType<{ children?: ReactNode }>;\nconst mounted = new Set<RenderSession<unknown>>();\n\n/**\n * A lazily initialized component render. Configure providers before observing\n * {@link subject}; unmount it manually or with {@link cleanup}.\n */\nexport class RenderSession<P> {\n private driver: RenderDriver | undefined;\n private wrappers: readonly Provider[] = [];\n private disposed = false;\n private selection: Subject<P> | undefined;\n\n /**\n * @internal\n * Constructed by {@link getComponentRenderer}.\n */\n constructor(\n private readonly component: ElementType,\n private props: P,\n private readonly factory: DriverFactory,\n private readonly initialElement?: ReactElement,\n ) {}\n\n /**\n * Configure providers before first observation. Providers nest in argument\n * order, so the first provider is outermost.\n */\n with(...providers: readonly Provider[]): this {\n if (this.disposed) throw new Error('Cannot configure an unmounted subject');\n if (this.driver)\n throw new Error(\n 'Call .with(...) before observing or updating the subject',\n );\n this.wrappers = [...this.wrappers, ...providers];\n return this;\n }\n\n /** Inspect the current render through live, typed contract queries. */\n get subject(): Subject<P> {\n const driver = this.initialize();\n this.selection ??= new Subject<P>(() => {\n const node = driver.inspect();\n return node ? [node] : [];\n }, driver.mode);\n return this.selection;\n }\n\n /** Merge props into the current render while preserving component state. */\n rerender(overrides: Partial<P>): void {\n const driver = this.initialize();\n this.props = { ...this.props, ...overrides };\n driver.render(this.props as PropRecord, this.wrappers);\n }\n\n /** Flush already scheduled synchronous work; use {@link act} for asynchronous work. */\n flush(): void {\n this.initialize().flush();\n }\n\n /** Await React work scheduled by the callback. Await the component request or timer inside the callback. */\n async act(callback: () => void | Promise<void>): Promise<void> {\n await this.initialize().act(callback);\n }\n\n /** Unmount the render. Calling this more than once is safe. */\n unmount(): void {\n if (this.disposed) return;\n this.disposed = true;\n mounted.delete(this as RenderSession<unknown>);\n this.driver?.unmount();\n }\n\n private initialize(): RenderDriver {\n if (this.disposed)\n throw new Error('Cannot use an unmounted render session');\n if (!this.driver) {\n this.driver = this.factory({\n component: this.component,\n props: this.props as PropRecord,\n wrappers: this.wrappers,\n initialElement: this.initialElement,\n });\n mounted.add(this as RenderSession<unknown>);\n }\n return this.driver;\n }\n}\n\n/** Create shallow and DOM render sessions for one component and its typed defaults. */\nexport interface ComponentRenderer<C extends ElementType> {\n /**\n * Render the target while keeping custom child components opaque. Hooks and\n * effects in the target still run.\n */\n shallow(\n overrides?: Partial<ComponentProps<C>>,\n ): RenderSession<ComponentProps<C>>;\n\n /** Render the target and descendants into a DOM container. */\n mount(\n overrides?: Partial<ComponentProps<C>>,\n ): RenderSession<ComponentProps<C>>;\n}\n\n/**\n * Create independent render sessions from a snapshot of strictly typed defaults.\n *\n * Shallow uses a version-matched React reconciler to execute the target's hooks\n * and effects. Returned custom children are opaque contracts: their props and\n * presence are inspectable, but neither their render functions nor descendants\n * execute. Host refs/DOM behavior therefore belong in mount tests.\n *\n * Mount requires a DOM environment (for example Vitest's jsdom environment)\n * and matching react/react-dom versions. Rendering uses public React DOM APIs;\n * component queries use isolated, read-only, version-gated Fiber inspection.\n * Supported stable lines: React 17.0.2, 18.2\u201318.3, and 19.0\u201319.3.\n *\n * Sessions render on first observation/update so provider chaining mounts once.\n * Register `afterEach(cleanup)` with your test runner.\n *\n * @example\n * const renderer = getComponentRenderer(App, { name: 'value' });\n * const { subject } = renderer.shallow({ name: 'other' });\n * expect(subject.find(Page).prop('name')).toBe('other');\n * const mounted = renderer.mount().with(OuterProvider, InnerProvider);\n * expect(mounted.subject.find('button').getDOMNode().textContent).toBe('Save');\n */\nexport function getComponentRenderer<C extends ElementType>(\n component: C,\n defaultProps: NoInfer<ComponentProps<C>>,\n): ComponentRenderer<C> {\n const defaults = { ...defaultProps };\n let defaultElement: ReactElement | undefined;\n return {\n shallow(overrides) {\n return new RenderSession(\n component,\n overrides === undefined ? defaults : { ...defaults, ...overrides },\n createShallowDriver,\n );\n },\n mount(overrides) {\n const props =\n overrides === undefined ? defaults : { ...defaults, ...overrides };\n const element =\n overrides === undefined\n ? (defaultElement ??= createElement(component, defaults))\n : createElement(component, props);\n return new RenderSession(component, props, createMountDriver, element);\n },\n };\n}\n\n/**\n * Unmount every live render session. Register this with the test runner's\n * `afterEach`; cleanup continues after an individual unmount fails.\n */\nexport function cleanup(): void {\n const errors: unknown[] = [];\n for (const session of mounted) {\n try {\n session.unmount();\n } catch (error) {\n errors.push(error);\n }\n }\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1)\n throw new AggregateError(\n errors,\n 'Multiple render sessions failed to clean up',\n );\n}\n", "import * as React from 'react';\nimport type { ElementType, ReactNode } from 'react';\nimport { inspectDOMRoot, selectDOMReactVersion } from './adapters/dom.js';\nimport type { DOMReactVersion } from './adapters/dom.js';\nimport { enterActEnvironment, leaveActEnvironment, wrap } from './internal.js';\nimport type { DriverOptions, PropRecord, RenderDriver } from './internal.js';\n\ntype ReactAct = (callback: () => void | Promise<void>) => PromiseLike<void>;\n\ninterface LegacyDOM {\n readonly version: string;\n render(element: ReactNode, container: Element): unknown;\n unmountComponentAtNode(container: Element): boolean;\n}\n\ninterface ConcurrentDOM {\n readonly version: string;\n flushSync(callback: () => void): void;\n}\n\ninterface DOMRoot {\n render(element: ReactNode): void;\n unmount(): void;\n}\n\ninterface DOMClient {\n createRoot(\n container: Element,\n options?: { onUncaughtError: (error: unknown) => void },\n ): DOMRoot;\n}\n\ninterface DOMRuntime {\n readonly version: DOMReactVersion;\n readonly reactAct: ReactAct;\n readonly legacy: LegacyDOM | null;\n readonly concurrent: ConcurrentDOM | null;\n readonly client: DOMClient | null;\n}\n\nlet cachedRuntime: DOMRuntime | undefined;\n\nfunction loadRuntime(): DOMRuntime {\n const version = selectDOMReactVersion(React.version);\n const reactRuntime = React as unknown as Readonly<Record<string, unknown>>;\n // Load only the entry points supported by this React version, once per process.\n const utilities: Readonly<Record<string, unknown>> =\n typeof reactRuntime['act'] === 'function'\n ? reactRuntime\n : (require('react-dom/test-utils') as Readonly<Record<string, unknown>>);\n const actCandidate = utilities['act'];\n if (typeof actCandidate !== 'function')\n throw new Error(\n 'This React build does not provide act(). Use a development React build for testing.',\n );\n const reactAct = actCandidate as ReactAct;\n const legacy = version === 17 ? (require('react-dom') as LegacyDOM) : null;\n const concurrent =\n version === 17 ? null : (require('react-dom') as ConcurrentDOM);\n const domVersion = legacy?.version ?? concurrent?.version;\n if (domVersion !== React.version) {\n throw new Error(\n `React and React DOM versions must match; received React ${React.version} and React DOM ${String(domVersion)}.`,\n );\n }\n const client =\n version === 17 ? null : (require('react-dom/client') as DOMClient);\n return { version, reactAct, legacy, concurrent, client };\n}\n\nexport function createMountDriver(options: DriverOptions): RenderDriver {\n if (typeof document === 'undefined' || document.body === null) {\n throw new Error(\n 'mount() requires a DOM document with a body. Configure jsdom before mounting.',\n );\n }\n const { version, reactAct, legacy, client } = (cachedRuntime ??=\n loadRuntime());\n const container = document.createElement('div');\n let root: DOMRoot | null = null;\n let unmounted = false;\n let currentProps = options.props;\n let currentWrappers = options.wrappers;\n let { initialElement } = options;\n const pendingErrors: unknown[] = [];\n\n function throwPendingErrors(): void {\n if (pendingErrors.length === 0) return;\n if (pendingErrors.length === 1) throw pendingErrors.shift();\n const errors = pendingErrors.splice(0);\n throw new AggregateError(errors, 'Multiple uncaught React errors.');\n }\n\n function sync(callback: () => void): void {\n enterActEnvironment();\n try {\n // act() already commits synchronous work and effects; nesting flushSync\n // here creates a second scheduler boundary on every render and unmount.\n reactAct(callback);\n throwPendingErrors();\n } finally {\n leaveActEnvironment();\n }\n }\n\n const driver: RenderDriver = {\n mode: 'mount',\n inspect() {\n throwPendingErrors();\n return unmounted\n ? null\n : inspectDOMRoot(version, container, root, options.component);\n },\n render(props: PropRecord, wrappers: readonly ElementType[]): void {\n if (unmounted) throw new Error('Cannot render an unmounted subject.');\n currentProps = props;\n currentWrappers = wrappers;\n const target =\n initialElement ?? React.createElement(options.component, props);\n initialElement = undefined;\n const element = wrap(target, wrappers, (type, providerProps) =>\n React.createElement(type, providerProps),\n );\n sync(() => {\n if (legacy !== null) legacy.render(element, container);\n else if (root !== null) root.render(element);\n else throw new Error('React DOM root was not initialized.');\n });\n },\n flush(): void {\n if (!unmounted) driver.render(currentProps, currentWrappers);\n },\n async act(callback: () => void | Promise<void>): Promise<void> {\n if (unmounted) throw new Error('Cannot act on an unmounted subject.');\n enterActEnvironment();\n try {\n await reactAct(async () => {\n await callback();\n });\n throwPendingErrors();\n } finally {\n leaveActEnvironment();\n }\n },\n unmount(): void {\n if (unmounted) return;\n unmounted = true;\n try {\n sync(() => {\n if (legacy !== null) legacy.unmountComponentAtNode(container);\n else root?.unmount();\n });\n } finally {\n root = null;\n container.remove();\n }\n },\n };\n\n document.body.appendChild(container);\n try {\n if (client !== null) {\n root =\n version === 19\n ? client.createRoot(container, {\n onUncaughtError: (error: unknown) => {\n pendingErrors.push(error);\n },\n })\n : client.createRoot(container);\n }\n driver.render(options.props, options.wrappers);\n } catch (error) {\n try {\n driver.unmount();\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n 'Mount failed and React cleanup also failed.',\n );\n }\n throw error;\n }\n return driver;\n}\n", "import type { ElementType } from 'react';\nimport type { InspectionNode, PropRecord } from '../internal.js';\n\nexport type DOMReactVersion = 17 | 18 | 19;\n\nexport function selectDOMReactVersion(version: string): DOMReactVersion {\n const match = /^(17|18|19)\\.(\\d+)\\.(\\d+)$/.exec(version);\n const major = Number(match?.[1]);\n const minor = Number(match?.[2]);\n const patch = Number(match?.[3]);\n if (major === 17 && minor === 0 && patch === 2) return 17;\n if (major === 18 && (minor === 2 || minor === 3)) return 18;\n if (major === 19 && minor >= 0 && minor <= 3) return 19;\n throw new Error(\n `Unsupported React version ${version}. Mount supports stable React 17.0.2, 18.2\u201318.3, and 19.0\u201319.3.`,\n );\n}\n\n// All private React DOM reads stay in this adapter. These fields and work tags\n// are shared by the supported releases, except the React 17 offscreen tags.\ninterface Fiber {\n readonly tag: number;\n readonly type: unknown;\n readonly elementType: unknown;\n readonly memoizedProps: unknown;\n readonly memoizedState: unknown;\n readonly stateNode: unknown;\n readonly child: Fiber | null;\n readonly sibling: Fiber | null;\n}\n\nfunction record(value: unknown): Readonly<Record<string, unknown>> | null {\n return typeof value === 'object' && value !== null\n ? (value as Readonly<Record<string, unknown>>)\n : null;\n}\n\nfunction currentFiber(publicRoot: unknown): Fiber {\n const root = record(publicRoot);\n if (root === null)\n throw new Error(\n 'Unsupported React DOM internals: expected a mounted root.',\n );\n const internalRoot = record(root['_internalRoot']);\n if (internalRoot === null)\n throw new Error('Unsupported React DOM internals: expected a FiberRoot.');\n const current = record(internalRoot['current']);\n if (current === null || current['tag'] !== 3) {\n throw new Error(\n 'Unsupported React DOM internals: expected FiberRoot.current.',\n );\n }\n return current as unknown as Fiber;\n}\n\nfunction skipped(fiber: Fiber, version: DOMReactVersion): boolean {\n if (fiber.tag === 4 || fiber.tag === 18) return true; // Portal, dehydrated fragment.\n const offscreen = version === 17 ? 23 : 22;\n const legacyHidden = version === 17 ? 24 : 23;\n return (\n (fiber.tag === offscreen || fiber.tag === legacyHidden) &&\n fiber.memoizedState !== null\n );\n}\n\nfunction isHost(fiber: Fiber, version: DOMReactVersion): boolean {\n return (\n fiber.tag === 5 ||\n (version === 19 && (fiber.tag === 26 || fiber.tag === 27))\n );\n}\n\nfunction exposedType(\n fiber: Fiber,\n version: DOMReactVersion,\n): ElementType | null {\n if (isHost(fiber, version)) return fiber.type as ElementType;\n switch (fiber.tag) {\n case 0: // Function.\n case 1: // Class.\n return fiber.type as ElementType;\n case 11: // ForwardRef.\n case 14: // Memo.\n return fiber.type as ElementType;\n case 15: // SimpleMemo (fiber.type is the unwrapped function).\n return fiber.elementType as ElementType;\n default:\n return null;\n }\n}\n\nfunction hostElement(fiber: Fiber): Element | null {\n const node = record(fiber.stateNode);\n return node?.['nodeType'] === 1 ? (fiber.stateNode as Element) : null;\n}\n\nfunction firstDOM(fiber: Fiber, version: DOMReactVersion): Element | null {\n if (skipped(fiber, version)) return null;\n if (isHost(fiber, version)) return hostElement(fiber);\n for (let { child } = fiber; child !== null; child = child.sibling) {\n const element = firstDOM(child, version);\n if (element !== null) return element;\n }\n return null;\n}\n\nfunction committedText(fiber: Fiber, version: DOMReactVersion): string {\n if (skipped(fiber, version)) return '';\n if (fiber.tag === 6) {\n const node = record(fiber.stateNode);\n return typeof node?.['nodeValue'] === 'string' ? node['nodeValue'] : '';\n }\n // React omits HostText fibers for direct string children and innerHTML.\n // Reading the DOM also reflects browser-normalized text, not prop coercion.\n if (isHost(fiber, version) && fiber.child === null)\n return hostElement(fiber)?.textContent ?? '';\n let text = '';\n for (let { child } = fiber; child !== null; child = child.sibling) {\n text += committedText(child, version);\n }\n return text;\n}\n\nclass CommittedNode implements InspectionNode {\n constructor(\n private readonly fiber: Fiber,\n readonly type: ElementType,\n private readonly version: DOMReactVersion,\n ) {}\n\n get props(): PropRecord {\n return record(this.fiber.memoizedProps) ?? {};\n }\n\n get children(): readonly InspectionNode[] {\n const children: InspectionNode[] = [];\n appendChildren(this.fiber.child, this.version, children);\n return children;\n }\n\n get text(): string {\n return committedText(this.fiber, this.version);\n }\n\n get dom(): Element | null {\n return firstDOM(this.fiber, this.version);\n }\n}\n\nfunction appendChildren(\n first: Fiber | null,\n version: DOMReactVersion,\n output: InspectionNode[],\n): void {\n for (let fiber = first; fiber !== null; fiber = fiber.sibling) {\n if (skipped(fiber, version)) continue;\n const type = exposedType(fiber, version);\n if (type === null) appendChildren(fiber.child, version, output);\n else output.push(new CommittedNode(fiber, type, version));\n }\n}\n\nfunction findBoundary(\n first: Fiber | null,\n boundary: ElementType,\n version: DOMReactVersion,\n): Fiber | null {\n for (let fiber = first; fiber !== null; fiber = fiber.sibling) {\n if (skipped(fiber, version)) continue;\n if (fiber.elementType === boundary || fiber.type === boundary) return fiber;\n const found = findBoundary(fiber.child, boundary, version);\n if (found !== null) return found;\n }\n return null;\n}\n\nexport function inspectDOMRoot(\n version: DOMReactVersion,\n container: Element,\n publicRoot: unknown,\n boundary: ElementType,\n): InspectionNode | null {\n const root =\n version === 17 ? record(container)?.['_reactRootContainer'] : publicRoot;\n const current = currentFiber(root);\n const targetBoundary = findBoundary(current.child, boundary, version);\n if (targetBoundary === null) return null;\n return new CommittedNode(targetBoundary, boundary, version);\n}\n", "import type { ElementType, ReactElement, ReactNode } from 'react';\n\nexport type PropRecord = Readonly<Record<string, unknown>>;\n\n/** A query-time view. Rendering does not allocate an inspection tree. */\nexport interface InspectionNode {\n readonly type: ElementType;\n readonly props: PropRecord;\n readonly children: readonly InspectionNode[];\n readonly text: string;\n readonly dom: Element | null;\n}\n\nexport interface RenderDriver {\n readonly mode: 'shallow' | 'mount';\n inspect(): InspectionNode | null;\n render(props: PropRecord, wrappers: readonly ElementType[]): void;\n flush(): void;\n act(callback: () => void | Promise<void>): Promise<void>;\n unmount(): void;\n}\n\nexport interface DriverOptions {\n readonly component: ElementType;\n readonly props: PropRecord;\n readonly wrappers: readonly ElementType[];\n readonly initialElement?: ReactElement | undefined;\n}\n\nexport type DriverFactory = (options: DriverOptions) => RenderDriver;\n\nlet actScopes = 0;\nlet previousActEnvironment: PropertyDescriptor | undefined;\n\nexport function enterActEnvironment(): void {\n if (actScopes === 0) {\n previousActEnvironment = Object.getOwnPropertyDescriptor(\n globalThis,\n 'IS_REACT_ACT_ENVIRONMENT',\n );\n Object.defineProperty(globalThis, 'IS_REACT_ACT_ENVIRONMENT', {\n configurable: true,\n enumerable: true,\n writable: true,\n value: true,\n });\n }\n actScopes += 1;\n}\n\nexport function leaveActEnvironment(): void {\n actScopes -= 1;\n if (actScopes !== 0) return;\n if (previousActEnvironment === undefined) {\n Reflect.deleteProperty(globalThis, 'IS_REACT_ACT_ENVIRONMENT');\n } else {\n Object.defineProperty(\n globalThis,\n 'IS_REACT_ACT_ENVIRONMENT',\n previousActEnvironment,\n );\n }\n previousActEnvironment = undefined;\n}\n\nexport function wrap(\n element: ReactNode,\n wrappers: readonly ElementType[],\n create: (type: ElementType, props: { children: ReactNode }) => ReactNode,\n): ReactNode {\n let result = element;\n for (let index = wrappers.length - 1; index >= 0; index -= 1) {\n const wrapper = wrappers[index];\n if (wrapper !== undefined) result = create(wrapper, { children: result });\n }\n return result;\n}\n", "import * as React from 'react';\nimport type { ComponentType, ElementType, ReactNode } from 'react';\nimport { createShallowRoot } from './adapters/reconciler.js';\nimport type { HostNode } from './adapters/reconciler.js';\nimport type {\n DriverOptions,\n InspectionNode,\n PropRecord,\n RenderDriver,\n} from './internal.js';\nimport { wrap } from './internal.js';\n\nconst outputType = 'contract-renderer-output';\nconst wrappedTypes = new WeakMap<object, ElementType>();\nconst noChildren: readonly InspectionNode[] = Object.freeze([]);\n\ntype FunctionComponent = (props: PropRecord) => ReactNode;\ntype ClassComponent = new (\n props: PropRecord,\n context?: unknown,\n) => React.Component<PropRecord>;\ninterface ExoticType {\n readonly $$typeof?: symbol;\n readonly type?: ElementType;\n readonly render?: (\n props: PropRecord,\n ref: React.ForwardedRef<unknown>,\n ) => ReactNode;\n readonly compare?: (previous: PropRecord, next: PropRecord) => boolean;\n readonly _init?: (payload: unknown) => ElementType;\n readonly _payload?: unknown;\n}\n\nfunction capture(value: ReactNode, props: PropRecord): React.ReactElement {\n return React.createElement(outputType, { value, input: props });\n}\n\n/** Only this boundary invokes the target; React still owns the wrapper's hook and class lifecycle. */\nfunction instrument(type: ElementType): ElementType {\n if (typeof type === 'string') {\n return (props: PropRecord) =>\n capture(props['children'] as ReactNode, props);\n }\n const existing = wrappedTypes.get(type);\n if (existing) return existing;\n let result: ComponentType<PropRecord>;\n if (typeof type === 'function') {\n if (type.prototype && 'isReactComponent' in type.prototype) {\n // React component constructors cannot be expressed as a single invariant ElementType generic.\n const Base = type as ClassComponent;\n result = class ContractTarget extends Base {\n override render(): ReactNode {\n return capture(super.render(), this.props);\n }\n };\n } else {\n const render = type as FunctionComponent;\n result = (props: PropRecord) => capture(render(props), props);\n if ('defaultProps' in type)\n Object.assign(result, { defaultProps: type.defaultProps });\n }\n } else {\n // These symbols and lazy/forwardRef fields are the version-tested private integration boundary.\n const exotic = type as ExoticType;\n switch (exotic.$$typeof) {\n case Symbol.for('react.memo'): {\n if (!exotic.type) throw new TypeError('Invalid memo component');\n const child = instrument(exotic.type) as ComponentType<PropRecord>;\n result = React.memo(child, exotic.compare);\n break;\n }\n case Symbol.for('react.forward_ref'): {\n const { render } = exotic;\n if (!render) throw new TypeError('Invalid forwardRef component');\n result = React.forwardRef<unknown, PropRecord>((props, ref) =>\n capture(render(props, ref), props),\n );\n break;\n }\n case Symbol.for('react.lazy'): {\n const initialize = exotic._init;\n if (!initialize) throw new TypeError('Invalid lazy component');\n result = (props: PropRecord) =>\n React.createElement(instrument(initialize(exotic._payload)), props);\n break;\n }\n default:\n throw new TypeError(\n 'Shallow rendering requires a component function, class, memo, forwardRef, lazy component, or host tag',\n );\n }\n }\n wrappedTypes.set(type, result);\n return result;\n}\n\nfunction outputNode(node: HostNode): HostNode | undefined {\n if (node.hidden) return undefined;\n if (node.type === outputType) return node;\n for (const child of node.children) {\n const found = outputNode(child);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction inspectChildren(value: ReactNode): {\n children: readonly InspectionNode[];\n text: string;\n} {\n const children: InspectionNode[] = [];\n let text = '';\n React.Children.forEach(value, (child) => {\n if (\n typeof child === 'string' ||\n typeof child === 'number' ||\n typeof child === 'bigint'\n ) {\n text += String(child);\n } else if (React.isValidElement<PropRecord>(child)) {\n const { type } = child;\n if (type === React.Fragment) {\n const inner = inspectChildren(child.props['children'] as ReactNode);\n children.push(...inner.children);\n text += inner.text;\n } else {\n const inner =\n typeof type === 'string'\n ? inspectChildren(child.props['children'] as ReactNode)\n : { children: noChildren, text: '' };\n children.push({\n type: type as ElementType,\n props: child.props,\n children: inner.children,\n text: inner.text,\n dom: null,\n });\n text += inner.text;\n }\n }\n });\n return { children, text };\n}\n\nexport function createShallowDriver(options: DriverOptions): RenderDriver {\n const root = createShallowRoot();\n const Target = instrument(options.component);\n let disposed = false;\n let currentProps = options.props;\n let currentWrappers = options.wrappers;\n const driver: RenderDriver = {\n mode: 'shallow',\n inspect() {\n if (disposed) return null;\n const node = outputNode(root.container);\n if (!node) return null;\n const children = inspectChildren(node.props['value'] as ReactNode);\n return {\n type: options.component,\n props: node.props['input'] as PropRecord,\n children: children.children,\n text: children.text,\n dom: null,\n };\n },\n render(props, wrappers) {\n if (disposed) throw new Error('Cannot render an unmounted subject');\n currentProps = props;\n currentWrappers = wrappers;\n const target = React.createElement(Target, props);\n root.render(wrap(target, wrappers, React.createElement));\n },\n flush() {\n if (disposed) throw new Error('Cannot flush an unmounted subject');\n driver.render(currentProps, currentWrappers);\n },\n async act(callback) {\n if (disposed) throw new Error('Cannot update an unmounted subject');\n await root.act(callback);\n },\n unmount() {\n if (disposed) return;\n disposed = true;\n root.render(null);\n },\n };\n try {\n driver.render(options.props, options.wrappers);\n } catch (error) {\n driver.unmount();\n throw error;\n }\n return driver;\n}\n", "import * as React from 'react';\nimport type { ReactNode } from 'react';\nimport { enterActEnvironment, leaveActEnvironment } from '../internal.js';\nimport type { PropRecord } from '../internal.js';\n\nexport interface HostNode {\n type: string;\n props: PropRecord;\n children: HostNode[];\n hidden: boolean;\n}\n\ninterface Reconciler {\n createContainer(...args: unknown[]): unknown;\n updateContainer(\n element: ReactNode,\n root: unknown,\n parent: null,\n callback: null,\n ): void;\n updateContainerSync?: (\n element: ReactNode,\n root: unknown,\n parent: null,\n callback: null,\n ) => void;\n flushSync?: (callback: () => void) => void;\n flushSyncFromReconciler?: (callback: () => void) => void;\n flushSyncWork?: () => void;\n flushPassiveEffects(): boolean;\n}\n\ntype Factory = (config: Readonly<Record<string, unknown>>) => Reconciler;\ntype Act = (callback: () => void | Promise<void>) => PromiseLike<void>;\nconst noop = (): void => {};\nconst emptyContext = Object.freeze({});\nlet instance: Reconciler | undefined;\nlet cachedAct: Act | undefined;\n\nexport function reactVersion(): { major: number; minor: number } {\n const match = /^(17|18|19)\\.(\\d+)\\.(\\d+)$/.exec(React.version);\n const major = Number(match?.[1]);\n const minor = Number(match?.[2]);\n if (\n !match ||\n (major === 17 && minor !== 0) ||\n (major === 18 && (minor < 2 || minor > 3)) ||\n (major === 19 && minor > 3)\n ) {\n throw new Error(\n `Unsupported React ${React.version}; tested adapters cover 17.0.2, 18.2\u201318.3, and 19.0\u201319.3 stable releases.`,\n );\n }\n return { major, minor };\n}\n\nfunction loadFactory(major: number, minor: number): Factory {\n switch (major) {\n case 17:\n return require('./adapters/react17.cjs') as Factory;\n case 18:\n return require('./adapters/react18.cjs') as Factory;\n case 19:\n switch (minor) {\n case 0:\n return require('./adapters/react19_0.cjs') as Factory;\n case 1:\n return require('./adapters/react19_1.cjs') as Factory;\n case 2:\n return require('./adapters/react19_2.cjs') as Factory;\n case 3:\n return require('./adapters/react19_3.cjs') as Factory;\n }\n }\n throw new Error(`No reconciler adapter for React ${React.version}`);\n}\n\nfunction remove(parent: HostNode, child: HostNode): void {\n const index = parent.children.indexOf(child);\n if (index >= 0) parent.children.splice(index, 1);\n}\nfunction append(parent: HostNode, child: HostNode): void {\n remove(parent, child);\n parent.children.push(child);\n}\nfunction insert(parent: HostNode, child: HostNode, before: HostNode): void {\n remove(parent, child);\n const index = parent.children.indexOf(before);\n if (index < 0)\n throw new Error('Invalid insertion point in shallow host tree');\n parent.children.splice(index, 0, child);\n}\n\nfunction getReconciler(): Reconciler {\n if (instance) return instance;\n const { major, minor } = reactVersion();\n let priority = 0;\n const config: Record<string, unknown> = {\n rendererVersion: '0.1.0',\n rendererPackageName: '@avgz/react-contract-renderer',\n isPrimaryRenderer: false,\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n supportsMicrotasks: true,\n supportsResources: false,\n supportsSingletons: false,\n supportsTestSelectors: false,\n getRootHostContext: () => emptyContext,\n getChildHostContext: () => emptyContext,\n getPublicInstance: (node: HostNode) => node,\n prepareForCommit: () => null,\n resetAfterCommit: noop,\n createInstance: (type: string, props: PropRecord): HostNode => ({\n type,\n props,\n children: [],\n hidden: false,\n }),\n createTextInstance: (text: string): HostNode => ({\n type: '#text',\n props: { text },\n children: [],\n hidden: false,\n }),\n appendInitialChild: append,\n appendChild: append,\n appendChildToContainer: append,\n insertBefore: insert,\n insertInContainerBefore: insert,\n removeChild: remove,\n removeChildFromContainer: remove,\n clearContainer: (container: HostNode) => {\n container.children.length = 0;\n },\n finalizeInitialChildren: () => false,\n shouldSetTextContent: () => false,\n prepareUpdate: () => true,\n commitUpdate:\n major >= 19\n ? (\n node: HostNode,\n _type: string,\n _old: PropRecord,\n props: PropRecord,\n ) => {\n node.props = props;\n }\n : (\n node: HostNode,\n _payload: unknown,\n _type: string,\n _old: PropRecord,\n props: PropRecord,\n ) => {\n node.props = props;\n },\n commitTextUpdate: (node: HostNode, _old: string, text: string) => {\n node.props = { text };\n },\n resetTextContent: (node: HostNode) => {\n node.children.length = 0;\n },\n hideInstance: (node: HostNode) => {\n node.hidden = true;\n },\n unhideInstance: (node: HostNode) => {\n node.hidden = false;\n },\n hideTextInstance: (node: HostNode) => {\n node.hidden = true;\n },\n unhideTextInstance: (node: HostNode) => {\n node.hidden = false;\n },\n detachDeletedInstance: (node: HostNode) => {\n node.children.length = 0;\n },\n preparePortalMount: noop,\n now: () => performance.now(),\n scheduleTimeout: setTimeout,\n cancelTimeout: clearTimeout,\n noTimeout: -1,\n scheduleMicrotask: queueMicrotask,\n getCurrentEventPriority: () => 16,\n getCurrentUpdatePriority: () => priority,\n setCurrentUpdatePriority: (next: number) => {\n priority = next;\n },\n resolveUpdatePriority: () => priority || 32,\n shouldAttemptEagerTransition: () => false,\n trackSchedulerEvent: noop,\n resolveEventType: () => null,\n resolveEventTimeStamp: () => -1.1,\n maySuspendCommit: () => false,\n maySuspendCommitOnUpdate: () => false,\n maySuspendCommitInSyncRender: () => false,\n preloadInstance: () => true,\n NotPendingTransition: null,\n HostTransitionContext: React.createContext(null),\n };\n instance = loadFactory(major, minor)(config);\n return instance;\n}\n\nfunction actFunction(): Act | undefined {\n if (cachedAct) return cachedAct;\n const react = React as unknown as { act?: Act };\n if (react.act) cachedAct = react.act;\n else if (reactVersion().major === 18) {\n // React 18.2 exposes the shared act queue through react-dom/test-utils.\n const utilities = require('react-dom/test-utils') as { act: Act };\n cachedAct = utilities.act;\n }\n return cachedAct;\n}\n\n/** React owns hook state, scheduling, and effect lifecycles; this adapter owns only host output. */\nexport function createShallowRoot(): {\n readonly container: HostNode;\n render(element: ReactNode): void;\n flush(): void;\n act(callback: () => void | Promise<void>): Promise<void>;\n} {\n const reconciler = getReconciler();\n const { major } = reactVersion();\n const container: HostNode = {\n type: '#root',\n props: {},\n children: [],\n hidden: false,\n };\n let failure: { error: unknown } | undefined;\n const onError = (error: unknown): void => {\n failure = { error };\n };\n const root =\n major === 17\n ? reconciler.createContainer(container, 0, false, null)\n : major === 18\n ? reconciler.createContainer(\n container,\n 1,\n null,\n false,\n null,\n '',\n onError,\n null,\n )\n : reconciler.createContainer(\n container,\n 1,\n null,\n false,\n null,\n '',\n onError,\n onError,\n onError,\n noop,\n );\n const checkError = (): void => {\n if (failure) {\n const { error } = failure;\n failure = undefined;\n throw error;\n }\n };\n const flushSync = reconciler.flushSync ?? reconciler.flushSyncFromReconciler;\n if (!flushSync)\n throw new Error(\n `React ${React.version} reconciler has no synchronous flush API`,\n );\n const drain = (): void => {\n let passes = 0;\n do {\n flushSync(noop);\n checkError();\n if (++passes > 100)\n throw new Error('Shallow effects did not settle after 100 flushes');\n } while (reconciler.flushPassiveEffects());\n checkError();\n };\n const sync = (callback: () => void): void => {\n const act = actFunction();\n if (act) {\n enterActEnvironment();\n try {\n void act(() => {\n callback();\n drain();\n });\n } finally {\n leaveActEnvironment();\n }\n } else {\n callback();\n drain();\n }\n checkError();\n };\n return {\n container,\n render(element) {\n sync(() =>\n flushSync(() => {\n (reconciler.updateContainerSync ?? reconciler.updateContainer)(\n element,\n root,\n null,\n null,\n );\n }),\n );\n },\n flush() {\n sync(noop);\n },\n async act(callback) {\n const act = actFunction();\n if (act) {\n enterActEnvironment();\n try {\n await act(async () => {\n await callback();\n drain();\n });\n } finally {\n leaveActEnvironment();\n }\n } else {\n await callback();\n drain();\n }\n checkError();\n },\n };\n}\n", "import { createElement } from 'react';\nimport type { ComponentProps, ElementType, ReactElement } from 'react';\nimport type { InspectionNode } from './internal.js';\n\nfunction validateType(type: unknown): void {\n if (typeof type === 'string') {\n if (!/^[a-zA-Z][a-zA-Z0-9:_-]*$/.test(type)) {\n throw new TypeError(\n 'Subject queries accept an intrinsic tag name, not a CSS selector.',\n );\n }\n return;\n }\n\n if (typeof type === 'function') return;\n\n const marker: unknown =\n typeof type === 'object' && type !== null && '$$typeof' in type\n ? type.$$typeof\n : type;\n if (typeof marker === 'symbol') {\n const name = Symbol.keyFor(marker);\n if (\n name === 'react.memo' ||\n name === 'react.forward_ref' ||\n name === 'react.lazy' ||\n name === 'react.context' ||\n name === 'react.provider' ||\n name === 'react.consumer' ||\n name === 'react.fragment' ||\n name === 'react.strict_mode' ||\n name === 'react.profiler' ||\n name === 'react.suspense' ||\n name === 'react.suspense_list' ||\n name === 'react.activity'\n )\n return;\n }\n\n throw new TypeError(\n 'Subject queries require a React component identity or an intrinsic tag name.',\n );\n}\n\nfunction collectMatches(\n node: InspectionNode,\n type: ElementType,\n matches: InspectionNode[],\n): void {\n if (node.type === type) matches.push(node);\n for (const child of node.children) collectMatches(child, type, matches);\n}\n\n/** A live selection: every inspection resolves against the latest committed render. */\nexport class Subject<P = Readonly<Record<string, unknown>>> {\n /** @internal */\n constructor(\n private readonly source: () => readonly InspectionNode[],\n private readonly mode: 'shallow' | 'mount',\n ) {}\n\n /** Match a component identity or host tag, including this node; inspection rejects multiple matches. */\n find<C extends ElementType>(type: C): Subject<ComponentProps<C>> {\n validateType(type);\n this.resolve();\n return new Subject<ComponentProps<C>>(() => this.search(type), this.mode);\n }\n\n /** Return live selections by match index. Re-query after insertion/reordering to obtain a new list. */\n findAll<C extends ElementType>(\n type: C,\n ): readonly Subject<ComponentProps<C>>[] {\n validateType(type);\n return this.search(type).map(\n (_, index) =>\n new Subject<ComponentProps<C>>(() => {\n const node = this.search(type)[index];\n return node === undefined ? [] : [node];\n }, this.mode),\n );\n }\n\n /** Report whether exactly one matching node exists in the current render. */\n exists(): boolean {\n return this.resolve() !== undefined;\n }\n\n /** Return every prop from the selected component or host node. */\n props(): P {\n return this.requireNode().props as P;\n }\n\n /** Return one typed prop from the selected component or host node. */\n prop<K extends keyof P>(key: K): P[K] {\n return this.props()[key];\n }\n\n /** Return the selected node's string className, if it has one. */\n className(): string | undefined {\n const value = this.requireNode().props['className'];\n if (value === undefined) return undefined;\n if (typeof value !== 'string') {\n throw new TypeError(\n 'The selected node has a className prop that is not a string.',\n );\n }\n return value;\n }\n\n /** Return the selected component identity or intrinsic host tag. */\n type(): ElementType {\n return this.requireNode().type;\n }\n\n /** Recreate the selected node as a React element with its current props. */\n element(): ReactElement<P> {\n const node = this.requireNode();\n return createElement(node.type, node.props) as unknown as ReactElement<P>;\n }\n\n /** Return all text content beneath the selected node. */\n text(): string {\n return this.requireNode().text;\n }\n\n /**\n * Mount only: return the first host element represented by the selected\n * contract.\n */\n getDOMNode(): Element {\n const node = this.requireNode();\n if (this.mode === 'shallow') {\n throw new Error(\n 'getDOMNode() is unavailable for shallow rendering; use mount() instead.',\n );\n }\n if (node.dom === null) {\n throw new Error('The selected node has no associated host DOM element.');\n }\n return node.dom;\n }\n\n private resolve(): InspectionNode | undefined {\n const nodes = this.source();\n if (nodes.length > 1) {\n throw new Error(\n `Subject selection is ambiguous: found ${nodes.length} nodes. Use findAll() to select multiple nodes.`,\n );\n }\n return nodes[0];\n }\n\n private requireNode(): InspectionNode {\n const node = this.resolve();\n if (node === undefined) {\n throw new Error(\n 'Subject selection is empty: no matching node exists in the current render.',\n );\n }\n return node;\n }\n\n private search(type: ElementType): readonly InspectionNode[] {\n const node = this.resolve();\n if (node === undefined) return [];\n const matches: InspectionNode[] = [];\n collectMatches(node, type, matches);\n return matches;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_react", "version", "version", "React", "React", "React"]
|
|
7
|
+
}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ComponentProps, ComponentType, ElementType, ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { DriverFactory } from './internal.cjs';
|
|
3
|
+
import { Subject } from './subject.cjs';
|
|
4
|
+
export { Subject } from './subject.cjs';
|
|
5
|
+
/** A React provider applied around every render session with {@link RenderSession.with}. */
|
|
6
|
+
export type Provider = ComponentType<{
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* A lazily initialized component render. Configure providers before observing
|
|
11
|
+
* {@link subject}; unmount it manually or with {@link cleanup}.
|
|
12
|
+
*/
|
|
13
|
+
export declare class RenderSession<P> {
|
|
14
|
+
private readonly component;
|
|
15
|
+
private props;
|
|
16
|
+
private readonly factory;
|
|
17
|
+
private readonly initialElement?;
|
|
18
|
+
private driver;
|
|
19
|
+
private wrappers;
|
|
20
|
+
private disposed;
|
|
21
|
+
private selection;
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
* Constructed by {@link getComponentRenderer}.
|
|
25
|
+
*/
|
|
26
|
+
constructor(component: ElementType, props: P, factory: DriverFactory, initialElement?: ReactElement | undefined);
|
|
27
|
+
/**
|
|
28
|
+
* Configure providers before first observation. Providers nest in argument
|
|
29
|
+
* order, so the first provider is outermost.
|
|
30
|
+
*/
|
|
31
|
+
with(...providers: readonly Provider[]): this;
|
|
32
|
+
/** Inspect the current render through live, typed contract queries. */
|
|
33
|
+
get subject(): Subject<P>;
|
|
34
|
+
/** Merge props into the current render while preserving component state. */
|
|
35
|
+
rerender(overrides: Partial<P>): void;
|
|
36
|
+
/** Flush already scheduled synchronous work; use {@link act} for asynchronous work. */
|
|
37
|
+
flush(): void;
|
|
38
|
+
/** Await React work scheduled by the callback. Await the component request or timer inside the callback. */
|
|
39
|
+
act(callback: () => void | Promise<void>): Promise<void>;
|
|
40
|
+
/** Unmount the render. Calling this more than once is safe. */
|
|
41
|
+
unmount(): void;
|
|
42
|
+
private initialize;
|
|
43
|
+
}
|
|
44
|
+
/** Create shallow and DOM render sessions for one component and its typed defaults. */
|
|
45
|
+
export interface ComponentRenderer<C extends ElementType> {
|
|
46
|
+
/**
|
|
47
|
+
* Render the target while keeping custom child components opaque. Hooks and
|
|
48
|
+
* effects in the target still run.
|
|
49
|
+
*/
|
|
50
|
+
shallow(overrides?: Partial<ComponentProps<C>>): RenderSession<ComponentProps<C>>;
|
|
51
|
+
/** Render the target and descendants into a DOM container. */
|
|
52
|
+
mount(overrides?: Partial<ComponentProps<C>>): RenderSession<ComponentProps<C>>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create independent render sessions from a snapshot of strictly typed defaults.
|
|
56
|
+
*
|
|
57
|
+
* Shallow uses a version-matched React reconciler to execute the target's hooks
|
|
58
|
+
* and effects. Returned custom children are opaque contracts: their props and
|
|
59
|
+
* presence are inspectable, but neither their render functions nor descendants
|
|
60
|
+
* execute. Host refs/DOM behavior therefore belong in mount tests.
|
|
61
|
+
*
|
|
62
|
+
* Mount requires a DOM environment (for example Vitest's jsdom environment)
|
|
63
|
+
* and matching react/react-dom versions. Rendering uses public React DOM APIs;
|
|
64
|
+
* component queries use isolated, read-only, version-gated Fiber inspection.
|
|
65
|
+
* Supported stable lines: React 17.0.2, 18.2–18.3, and 19.0–19.3.
|
|
66
|
+
*
|
|
67
|
+
* Sessions render on first observation/update so provider chaining mounts once.
|
|
68
|
+
* Register `afterEach(cleanup)` with your test runner.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const renderer = getComponentRenderer(App, { name: 'value' });
|
|
72
|
+
* const { subject } = renderer.shallow({ name: 'other' });
|
|
73
|
+
* expect(subject.find(Page).prop('name')).toBe('other');
|
|
74
|
+
* const mounted = renderer.mount().with(OuterProvider, InnerProvider);
|
|
75
|
+
* expect(mounted.subject.find('button').getDOMNode().textContent).toBe('Save');
|
|
76
|
+
*/
|
|
77
|
+
export declare function getComponentRenderer<C extends ElementType>(component: C, defaultProps: NoInfer<ComponentProps<C>>): ComponentRenderer<C>;
|
|
78
|
+
/**
|
|
79
|
+
* Unmount every live render session. Register this with the test runner's
|
|
80
|
+
* `afterEach`; cleanup continues after an individual unmount fails.
|
|
81
|
+
*/
|
|
82
|
+
export declare function cleanup(): void;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ComponentProps, ComponentType, ElementType, ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { DriverFactory } from './internal.js';
|
|
3
|
+
import { Subject } from './subject.js';
|
|
4
|
+
export { Subject } from './subject.js';
|
|
5
|
+
/** A React provider applied around every render session with {@link RenderSession.with}. */
|
|
6
|
+
export type Provider = ComponentType<{
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* A lazily initialized component render. Configure providers before observing
|
|
11
|
+
* {@link subject}; unmount it manually or with {@link cleanup}.
|
|
12
|
+
*/
|
|
13
|
+
export declare class RenderSession<P> {
|
|
14
|
+
private readonly component;
|
|
15
|
+
private props;
|
|
16
|
+
private readonly factory;
|
|
17
|
+
private readonly initialElement?;
|
|
18
|
+
private driver;
|
|
19
|
+
private wrappers;
|
|
20
|
+
private disposed;
|
|
21
|
+
private selection;
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
* Constructed by {@link getComponentRenderer}.
|
|
25
|
+
*/
|
|
26
|
+
constructor(component: ElementType, props: P, factory: DriverFactory, initialElement?: ReactElement | undefined);
|
|
27
|
+
/**
|
|
28
|
+
* Configure providers before first observation. Providers nest in argument
|
|
29
|
+
* order, so the first provider is outermost.
|
|
30
|
+
*/
|
|
31
|
+
with(...providers: readonly Provider[]): this;
|
|
32
|
+
/** Inspect the current render through live, typed contract queries. */
|
|
33
|
+
get subject(): Subject<P>;
|
|
34
|
+
/** Merge props into the current render while preserving component state. */
|
|
35
|
+
rerender(overrides: Partial<P>): void;
|
|
36
|
+
/** Flush already scheduled synchronous work; use {@link act} for asynchronous work. */
|
|
37
|
+
flush(): void;
|
|
38
|
+
/** Await React work scheduled by the callback. Await the component request or timer inside the callback. */
|
|
39
|
+
act(callback: () => void | Promise<void>): Promise<void>;
|
|
40
|
+
/** Unmount the render. Calling this more than once is safe. */
|
|
41
|
+
unmount(): void;
|
|
42
|
+
private initialize;
|
|
43
|
+
}
|
|
44
|
+
/** Create shallow and DOM render sessions for one component and its typed defaults. */
|
|
45
|
+
export interface ComponentRenderer<C extends ElementType> {
|
|
46
|
+
/**
|
|
47
|
+
* Render the target while keeping custom child components opaque. Hooks and
|
|
48
|
+
* effects in the target still run.
|
|
49
|
+
*/
|
|
50
|
+
shallow(overrides?: Partial<ComponentProps<C>>): RenderSession<ComponentProps<C>>;
|
|
51
|
+
/** Render the target and descendants into a DOM container. */
|
|
52
|
+
mount(overrides?: Partial<ComponentProps<C>>): RenderSession<ComponentProps<C>>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create independent render sessions from a snapshot of strictly typed defaults.
|
|
56
|
+
*
|
|
57
|
+
* Shallow uses a version-matched React reconciler to execute the target's hooks
|
|
58
|
+
* and effects. Returned custom children are opaque contracts: their props and
|
|
59
|
+
* presence are inspectable, but neither their render functions nor descendants
|
|
60
|
+
* execute. Host refs/DOM behavior therefore belong in mount tests.
|
|
61
|
+
*
|
|
62
|
+
* Mount requires a DOM environment (for example Vitest's jsdom environment)
|
|
63
|
+
* and matching react/react-dom versions. Rendering uses public React DOM APIs;
|
|
64
|
+
* component queries use isolated, read-only, version-gated Fiber inspection.
|
|
65
|
+
* Supported stable lines: React 17.0.2, 18.2–18.3, and 19.0–19.3.
|
|
66
|
+
*
|
|
67
|
+
* Sessions render on first observation/update so provider chaining mounts once.
|
|
68
|
+
* Register `afterEach(cleanup)` with your test runner.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const renderer = getComponentRenderer(App, { name: 'value' });
|
|
72
|
+
* const { subject } = renderer.shallow({ name: 'other' });
|
|
73
|
+
* expect(subject.find(Page).prop('name')).toBe('other');
|
|
74
|
+
* const mounted = renderer.mount().with(OuterProvider, InnerProvider);
|
|
75
|
+
* expect(mounted.subject.find('button').getDOMNode().textContent).toBe('Save');
|
|
76
|
+
*/
|
|
77
|
+
export declare function getComponentRenderer<C extends ElementType>(component: C, defaultProps: NoInfer<ComponentProps<C>>): ComponentRenderer<C>;
|
|
78
|
+
/**
|
|
79
|
+
* Unmount every live render session. Register this with the test runner's
|
|
80
|
+
* `afterEach`; cleanup continues after an individual unmount fails.
|
|
81
|
+
*/
|
|
82
|
+
export declare function cleanup(): void;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ElementType, ReactElement, ReactNode } from 'react';
|
|
2
|
+
export type PropRecord = Readonly<Record<string, unknown>>;
|
|
3
|
+
/** A query-time view. Rendering does not allocate an inspection tree. */
|
|
4
|
+
export interface InspectionNode {
|
|
5
|
+
readonly type: ElementType;
|
|
6
|
+
readonly props: PropRecord;
|
|
7
|
+
readonly children: readonly InspectionNode[];
|
|
8
|
+
readonly text: string;
|
|
9
|
+
readonly dom: Element | null;
|
|
10
|
+
}
|
|
11
|
+
export interface RenderDriver {
|
|
12
|
+
readonly mode: 'shallow' | 'mount';
|
|
13
|
+
inspect(): InspectionNode | null;
|
|
14
|
+
render(props: PropRecord, wrappers: readonly ElementType[]): void;
|
|
15
|
+
flush(): void;
|
|
16
|
+
act(callback: () => void | Promise<void>): Promise<void>;
|
|
17
|
+
unmount(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface DriverOptions {
|
|
20
|
+
readonly component: ElementType;
|
|
21
|
+
readonly props: PropRecord;
|
|
22
|
+
readonly wrappers: readonly ElementType[];
|
|
23
|
+
readonly initialElement?: ReactElement | undefined;
|
|
24
|
+
}
|
|
25
|
+
export type DriverFactory = (options: DriverOptions) => RenderDriver;
|
|
26
|
+
export declare function enterActEnvironment(): void;
|
|
27
|
+
export declare function leaveActEnvironment(): void;
|
|
28
|
+
export declare function wrap(element: ReactNode, wrappers: readonly ElementType[], create: (type: ElementType, props: {
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}) => ReactNode): ReactNode;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ElementType, ReactElement, ReactNode } from 'react';
|
|
2
|
+
export type PropRecord = Readonly<Record<string, unknown>>;
|
|
3
|
+
/** A query-time view. Rendering does not allocate an inspection tree. */
|
|
4
|
+
export interface InspectionNode {
|
|
5
|
+
readonly type: ElementType;
|
|
6
|
+
readonly props: PropRecord;
|
|
7
|
+
readonly children: readonly InspectionNode[];
|
|
8
|
+
readonly text: string;
|
|
9
|
+
readonly dom: Element | null;
|
|
10
|
+
}
|
|
11
|
+
export interface RenderDriver {
|
|
12
|
+
readonly mode: 'shallow' | 'mount';
|
|
13
|
+
inspect(): InspectionNode | null;
|
|
14
|
+
render(props: PropRecord, wrappers: readonly ElementType[]): void;
|
|
15
|
+
flush(): void;
|
|
16
|
+
act(callback: () => void | Promise<void>): Promise<void>;
|
|
17
|
+
unmount(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface DriverOptions {
|
|
20
|
+
readonly component: ElementType;
|
|
21
|
+
readonly props: PropRecord;
|
|
22
|
+
readonly wrappers: readonly ElementType[];
|
|
23
|
+
readonly initialElement?: ReactElement | undefined;
|
|
24
|
+
}
|
|
25
|
+
export type DriverFactory = (options: DriverOptions) => RenderDriver;
|
|
26
|
+
export declare function enterActEnvironment(): void;
|
|
27
|
+
export declare function leaveActEnvironment(): void;
|
|
28
|
+
export declare function wrap(element: ReactNode, wrappers: readonly ElementType[], create: (type: ElementType, props: {
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}) => ReactNode): ReactNode;
|
package/dist/mount.d.cts
ADDED
package/dist/mount.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ComponentProps, ElementType, ReactElement } from 'react';
|
|
2
|
+
import type { InspectionNode } from './internal.cjs';
|
|
3
|
+
/** A live selection: every inspection resolves against the latest committed render. */
|
|
4
|
+
export declare class Subject<P = Readonly<Record<string, unknown>>> {
|
|
5
|
+
private readonly source;
|
|
6
|
+
private readonly mode;
|
|
7
|
+
/** @internal */
|
|
8
|
+
constructor(source: () => readonly InspectionNode[], mode: 'shallow' | 'mount');
|
|
9
|
+
/** Match a component identity or host tag, including this node; inspection rejects multiple matches. */
|
|
10
|
+
find<C extends ElementType>(type: C): Subject<ComponentProps<C>>;
|
|
11
|
+
/** Return live selections by match index. Re-query after insertion/reordering to obtain a new list. */
|
|
12
|
+
findAll<C extends ElementType>(type: C): readonly Subject<ComponentProps<C>>[];
|
|
13
|
+
/** Report whether exactly one matching node exists in the current render. */
|
|
14
|
+
exists(): boolean;
|
|
15
|
+
/** Return every prop from the selected component or host node. */
|
|
16
|
+
props(): P;
|
|
17
|
+
/** Return one typed prop from the selected component or host node. */
|
|
18
|
+
prop<K extends keyof P>(key: K): P[K];
|
|
19
|
+
/** Return the selected node's string className, if it has one. */
|
|
20
|
+
className(): string | undefined;
|
|
21
|
+
/** Return the selected component identity or intrinsic host tag. */
|
|
22
|
+
type(): ElementType;
|
|
23
|
+
/** Recreate the selected node as a React element with its current props. */
|
|
24
|
+
element(): ReactElement<P>;
|
|
25
|
+
/** Return all text content beneath the selected node. */
|
|
26
|
+
text(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Mount only: return the first host element represented by the selected
|
|
29
|
+
* contract.
|
|
30
|
+
*/
|
|
31
|
+
getDOMNode(): Element;
|
|
32
|
+
private resolve;
|
|
33
|
+
private requireNode;
|
|
34
|
+
private search;
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ComponentProps, ElementType, ReactElement } from 'react';
|
|
2
|
+
import type { InspectionNode } from './internal.js';
|
|
3
|
+
/** A live selection: every inspection resolves against the latest committed render. */
|
|
4
|
+
export declare class Subject<P = Readonly<Record<string, unknown>>> {
|
|
5
|
+
private readonly source;
|
|
6
|
+
private readonly mode;
|
|
7
|
+
/** @internal */
|
|
8
|
+
constructor(source: () => readonly InspectionNode[], mode: 'shallow' | 'mount');
|
|
9
|
+
/** Match a component identity or host tag, including this node; inspection rejects multiple matches. */
|
|
10
|
+
find<C extends ElementType>(type: C): Subject<ComponentProps<C>>;
|
|
11
|
+
/** Return live selections by match index. Re-query after insertion/reordering to obtain a new list. */
|
|
12
|
+
findAll<C extends ElementType>(type: C): readonly Subject<ComponentProps<C>>[];
|
|
13
|
+
/** Report whether exactly one matching node exists in the current render. */
|
|
14
|
+
exists(): boolean;
|
|
15
|
+
/** Return every prop from the selected component or host node. */
|
|
16
|
+
props(): P;
|
|
17
|
+
/** Return one typed prop from the selected component or host node. */
|
|
18
|
+
prop<K extends keyof P>(key: K): P[K];
|
|
19
|
+
/** Return the selected node's string className, if it has one. */
|
|
20
|
+
className(): string | undefined;
|
|
21
|
+
/** Return the selected component identity or intrinsic host tag. */
|
|
22
|
+
type(): ElementType;
|
|
23
|
+
/** Recreate the selected node as a React element with its current props. */
|
|
24
|
+
element(): ReactElement<P>;
|
|
25
|
+
/** Return all text content beneath the selected node. */
|
|
26
|
+
text(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Mount only: return the first host element represented by the selected
|
|
29
|
+
* contract.
|
|
30
|
+
*/
|
|
31
|
+
getDOMNode(): Element;
|
|
32
|
+
private resolve;
|
|
33
|
+
private requireNode;
|
|
34
|
+
private search;
|
|
35
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@avgz/react-contract-renderer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Typed React component-contract testing with shallow and DOM renderers",
|
|
5
|
+
"homepage": "https://github.com/AverageZ/testing-library#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/AverageZ/testing-library/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/AverageZ/testing-library.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"require": {
|
|
23
|
+
"types": "./dist/index.d.cts",
|
|
24
|
+
"default": "./dist/index.cjs"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.cjs",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"directories": {
|
|
31
|
+
"doc": "docs",
|
|
32
|
+
"test": "tests"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node scripts/build.mjs && tsc -p tsconfig.build.json && node scripts/declarations.mjs",
|
|
39
|
+
"docs": "typedoc",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"benchmark": "node scripts/benchmark.mjs",
|
|
43
|
+
"verify": "node scripts/verify.mjs",
|
|
44
|
+
"lint": "oxlint src tests scripts",
|
|
45
|
+
"lint:fix": "oxlint --fix src tests scripts",
|
|
46
|
+
"format": "oxfmt src tests scripts *.json *.ts",
|
|
47
|
+
"format:check": "oxfmt --check src tests scripts *.json *.ts",
|
|
48
|
+
"prepare": "husky",
|
|
49
|
+
"pre-commit": "lint-staged"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@testing-library/dom": "^10.4.1",
|
|
53
|
+
"@testing-library/react": "^16.3.0",
|
|
54
|
+
"@types/node": "^24.0.0",
|
|
55
|
+
"@types/react": "^19.2.0",
|
|
56
|
+
"@types/react-dom": "^19.2.0",
|
|
57
|
+
"esbuild": "^0.25.0",
|
|
58
|
+
"fast-check": "^4.8.0",
|
|
59
|
+
"husky": "^9.1.7",
|
|
60
|
+
"jsdom": "^26.1.0",
|
|
61
|
+
"lint-staged": "^17.5.1",
|
|
62
|
+
"oxfmt": "^0.65.0",
|
|
63
|
+
"oxlint": "^1.85.0",
|
|
64
|
+
"react": "19.3.0",
|
|
65
|
+
"react-dom": "19.3.0",
|
|
66
|
+
"reconciler17": "npm:react-reconciler@0.26.2",
|
|
67
|
+
"reconciler18": "npm:react-reconciler@0.29.0",
|
|
68
|
+
"reconciler19_0": "npm:react-reconciler@0.31.0",
|
|
69
|
+
"reconciler19_1": "npm:react-reconciler@0.32.0",
|
|
70
|
+
"reconciler19_2": "npm:react-reconciler@0.33.0",
|
|
71
|
+
"reconciler19_3": "npm:react-reconciler@0.34.0",
|
|
72
|
+
"typedoc": "^0.28.20",
|
|
73
|
+
"typescript": "^5.9.3",
|
|
74
|
+
"vitest": "^3.2.4"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"react": "^17.0.2 || ^18.2.0 || >=19.0.0 <19.4.0",
|
|
78
|
+
"react-dom": "^17.0.2 || ^18.2.0 || >=19.0.0 <19.4.0"
|
|
79
|
+
},
|
|
80
|
+
"engines": {
|
|
81
|
+
"node": ">=22"
|
|
82
|
+
},
|
|
83
|
+
"module": "./dist/index.js",
|
|
84
|
+
"sideEffects": false,
|
|
85
|
+
"packageManager": "pnpm@10.24.0"
|
|
86
|
+
}
|