Skip to content

Commit

Permalink
add functions based on renderAsync
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed Nov 26, 2024
1 parent c4b152e commit 551d54f
Show file tree
Hide file tree
Showing 5 changed files with 1,252 additions and 1,287 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
],
"dependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.0.1",
"@testing-library/react": "https://pkg.csb.dev/testing-library/react-testing-library/commit/571fbc81/@testing-library/react/_pkg.tgz",
"jsdom": "^25.0.1",
"rehackt": "^0.1.0"
},
Expand Down
57 changes: 52 additions & 5 deletions src/renderHookToSnapshotStream.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import {RenderHookOptions} from '@testing-library/react'
import {Queries, RenderHookOptions} from '@testing-library/react'
import React from 'rehackt'
import {createRenderStream} from './renderStream/createRenderStream.js'
import {
createRenderStream,
RenderStream,
} from './renderStream/createRenderStream.js'
import {type NextRenderOptions} from './renderStream/createRenderStream.js'
import {Render} from './renderStream/Render.js'
import {Assertable, assertableSymbol, markAssertable} from './assertable.js'
import {SyncQueries} from './renderStream/syncQueries.js'

export interface SnapshotStream<Snapshot, Props> extends Assertable {
/**
Expand Down Expand Up @@ -49,7 +53,11 @@ export function renderHookToSnapshotStream<ReturnValue, Props>(
renderCallback: (props: Props) => ReturnValue,
{initialProps, ...renderOptions}: RenderHookOptions<Props> = {},
): SnapshotStream<ReturnValue, Props> {
const {render, ...stream} = createRenderStream<{value: ReturnValue}, never>()
const {
render,
renderAsync: _,
...stream
} = createRenderStream<{value: ReturnValue}, never>()

const HookComponent: React.FC<{arg: Props}> = props => {
stream.replaceSnapshot({value: renderCallback(props.arg)})
Expand All @@ -65,6 +73,47 @@ export function renderHookToSnapshotStream<ReturnValue, Props>(
return baseRerender(<HookComponent arg={rerenderCallbackProps} />)
}

return {
...renderStreamToSnapshotStream(stream),
rerender,
unmount,
}
}

export async function renderHookToAsyncSnapshotStream<ReturnValue, Props>(
renderCallback: (props: Props) => ReturnValue,
{initialProps, ...renderOptions}: RenderHookOptions<Props> = {},
): Promise<SnapshotStream<ReturnValue, Props>> {
const {
renderAsync,
render: _,
...stream
} = createRenderStream<{value: ReturnValue}, never>()

const HookComponent: React.FC<{arg: Props}> = props => {
stream.replaceSnapshot({value: renderCallback(props.arg)})
return null
}

const {rerender: baseRerender, unmount} = await renderAsync(
<HookComponent arg={initialProps!} />,
renderOptions,
)

function rerender(rerenderCallbackProps: Props) {
return baseRerender(<HookComponent arg={rerenderCallbackProps} />)
}

return {
...renderStreamToSnapshotStream(stream),
rerender,
unmount,
}
}

function renderStreamToSnapshotStream<Snapshot>(
stream: RenderStream<{value: Snapshot}, never>,
): Omit<SnapshotStream<Snapshot, any>, 'rerender' | 'unmount'> {
return {
[assertableSymbol]: stream,
renders: stream.renders,
Expand All @@ -81,7 +130,5 @@ export function renderHookToSnapshotStream<ReturnValue, Props>(
async waitForNextSnapshot(options) {
return (await stream.waitForNextRender(options)).snapshot.value
},
rerender,
unmount,
}
}
25 changes: 24 additions & 1 deletion src/renderStream/createRenderStream.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import * as React from 'rehackt'

import {render as baseRender, RenderOptions} from '@testing-library/react'
import {
render as baseRender,
renderAsync as baseRenderAsync,
RenderOptions,
} from '@testing-library/react'
import {Assertable, markAssertable} from '../assertable.js'
import {RenderInstance, type Render, type BaseRender} from './Render.js'
import {type RenderStreamContextValue} from './context.js'
Expand Down Expand Up @@ -82,6 +86,7 @@ export interface RenderStreamWithRenderFn<
Q extends Queries = SyncQueries,
> extends RenderStream<Snapshot, Q> {
render: typeof baseRender
renderAsync: typeof baseRenderAsync
}

export type RenderStreamOptions<
Expand Down Expand Up @@ -264,6 +269,23 @@ export function createRenderStream<
})
}) as typeof baseRender

const renderAsync = ((
ui: React.ReactNode,
options?: RenderOptions<any, any, any>,
) => {
return baseRenderAsync(ui, {
...options,
wrapper: (props: any) => {
const ParentWrapper = options?.wrapper ?? React.Fragment
return (
<ParentWrapper>
<Wrapper>{props.children}</Wrapper>
</ParentWrapper>
)
},
})
}) as typeof baseRenderAsync

Object.assign<typeof stream, typeof stream>(stream, {
replaceSnapshot,
mergeSnapshot,
Expand Down Expand Up @@ -356,6 +378,7 @@ export function createRenderStream<
return nextRender
},
render,
renderAsync,
})
return stream
}
Expand Down
43 changes: 42 additions & 1 deletion src/renderToRenderStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export function renderToRenderStream<
...options
}: RenderOptions<Snapshot, Q> = {},
): RenderStreamWithRenderResult<Snapshot, Q> {
const {render, ...stream} = createRenderStream<Snapshot, Q>({
const {
render,
renderAsync: _,
...stream
} = createRenderStream<Snapshot, Q>({
onRender,
snapshotDOM,
initialSnapshot,
Expand All @@ -55,3 +59,40 @@ export function renderToRenderStream<
)
return {...stream, renderResultPromise}
}

/**
* Render into a container which is appended to document.body. It should be used with cleanup.
*/
export function renderToAsyncRenderStream<
Snapshot extends ValidSnapshot = void,
Q extends Queries = SyncQueries,
>(
ui: React.ReactNode,
{
onRender,
snapshotDOM,
initialSnapshot,
skipNonTrackingRenders,
queries,
...options
}: RenderOptions<Snapshot, Q> = {},
): RenderStreamWithRenderResult<Snapshot, Q> {
const {
renderAsync,
render: _,
...stream
} = createRenderStream<Snapshot, Q>({
onRender,
snapshotDOM,
initialSnapshot,
skipNonTrackingRenders,
queries,
})
// `renderAsync` needs to be called asynchronously here, because the definition of `ui`
// might contain components that reference the return value of `renderToRenderStream`
// itself, e.g. `replaceSnapshot` or `mergeSnapshot`.
const renderResultPromise = Promise.resolve().then(() =>
renderAsync<Q>(ui, {...options, queries}),
)
return {...stream, renderResultPromise}
}
Loading

0 comments on commit 551d54f

Please sign in to comment.