Skip to content

Commit 67a3e4e

Browse files
authoredOct 10, 2024··
Merge pull request #2 from phryneas/kcd-scripts
2 parents 036fbc0 + 0f7cf17 commit 67a3e4e

20 files changed

+8741
-1933
lines changed
 

‎.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tsup.config.ts
2+
dist/

‎.eslintrc.cjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
extends: 'kentcdodds',
3+
rules: {
4+
'@typescript-eslint/no-explicit-any': 'off',
5+
'@typescript-eslint/no-empty-interface': 'off',
6+
'@typescript-eslint/no-non-null-assertion': 'off',
7+
'@typescript-eslint/unified-signatures': 'off',
8+
'@typescript-eslint/no-unused-vars': [
9+
'error',
10+
{
11+
args: 'after-used',
12+
argsIgnorePattern: '^_',
13+
ignoreRestSiblings: true,
14+
varsIgnorePattern: '^_',
15+
},
16+
],
17+
},
18+
}

‎.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# format with kcd-scripts
2+
325d59e3cd0bf4c7ab738381e1bb49aef3bc7363

‎.github/workflows/pkg-pr-new-publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ on:
44
pull_request:
55
push:
66
branches:
7-
- "**"
7+
- '**'
88
tags:
9-
- "!**"
9+
- '!**'
1010

1111
jobs:
1212
prerelease:

‎.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ dist/
55
!.yarn/plugins
66
!.yarn/releases
77
!.yarn/sdks
8-
!.yarn/versions
8+
!.yarn/versions
9+
*.tsbuildinfo

‎.prettierrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("kcd-scripts/prettier.js");

‎package.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@types/react": "^18",
6262
"@types/react-dom": "^18",
6363
"expect": "^29.7.0",
64+
"kcd-scripts": "^16.0.0",
6465
"pkg-pr-new": "^0.0.29",
6566
"prettier": "^3.3.3",
6667
"publint": "^0.2.11",
@@ -79,7 +80,15 @@
7980
"build": "tsup",
8081
"pkg-pr-new-publish": "yarn build && pkg-pr-new publish --no-template",
8182
"prepack": "yarn build",
82-
"verify": "attw --pack . && publint"
83+
"format": "kcd-scripts format",
84+
"lint": "kcd-scripts lint --config .eslintrc.cjs",
85+
"test": "kcd-scripts test --passWithNoTests",
86+
"verify": "attw --pack . && publint",
87+
"typecheck": "kcd-scripts typecheck --build",
88+
"validate": "CI=true kcd-scripts validate verify,lint,typecheck,test"
8389
},
84-
"packageManager": "yarn@4.5.0"
90+
"packageManager": "yarn@4.5.0",
91+
"resolutions": {
92+
"eslint-config-kentcdodds": "^21.0.0"
93+
}
8594
}

‎src/assertable.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { RenderStream } from "./renderStream/createRenderStream.js";
1+
import {type RenderStream} from './renderStream/createRenderStream.js'
22

33
export const assertableSymbol = Symbol.for(
4-
"@testing-library/react-render-stream:assertable"
5-
);
4+
'@testing-library/react-render-stream:assertable',
5+
)
66

77
/**
88
* A function or object that can be used in assertions, like e.g.
@@ -13,14 +13,14 @@ export const assertableSymbol = Symbol.for(
1313
```
1414
*/
1515
export type Assertable = {
16-
[assertableSymbol]: RenderStream<any>;
17-
};
16+
[assertableSymbol]: RenderStream<any>
17+
}
1818

1919
export function markAssertable<T extends {}>(
2020
assertable: T,
21-
stream: RenderStream<any>
21+
stream: RenderStream<any>,
2222
): T & Assertable {
2323
return Object.assign(assertable, {
2424
[assertableSymbol]: stream,
25-
});
25+
})
2626
}

‎src/index.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ export type {
33
RenderStream,
44
RenderStreamWithRenderFn,
55
RenderStreamOptions,
6-
} from "./renderStream/createRenderStream.js";
6+
} from './renderStream/createRenderStream.js'
77
export {
88
createRenderStream,
99
useTrackRenders,
1010
WaitForRenderTimeoutError,
11-
} from "./renderStream/createRenderStream.js";
11+
} from './renderStream/createRenderStream.js'
1212

13-
export type { SyncScreen } from "./renderStream/Render.js";
13+
export type {SyncScreen} from './renderStream/Render.js'
1414

15-
export { renderToRenderStream } from "./renderToRenderStream.js";
16-
export type { RenderStreamWithRenderResult } from "./renderToRenderStream.js";
17-
export { renderHookToSnapshotStream } from "./renderHookToSnapshotStream.js";
18-
export type { SnapshotStream } from "./renderHookToSnapshotStream.js";
15+
export {renderToRenderStream} from './renderToRenderStream.js'
16+
export type {RenderStreamWithRenderResult} from './renderToRenderStream.js'
17+
export {renderHookToSnapshotStream} from './renderHookToSnapshotStream.js'
18+
export type {SnapshotStream} from './renderHookToSnapshotStream.js'
1919

20-
export type { Assertable } from "./assertable.js";
20+
export type {Assertable} from './assertable.js'

‎src/jest/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { expect } from "@jest/globals";
2-
import { toRerender, toRenderExactlyTimes } from "./renderStreamMatchers.js";
3-
import type { RenderStreamMatchers } from "./renderStreamMatchers.js";
1+
import {expect} from '@jest/globals'
2+
import {
3+
toRerender,
4+
toRenderExactlyTimes,
5+
type RenderStreamMatchers,
6+
} from './renderStreamMatchers.js'
47

58
expect.extend({
69
toRerender,
710
toRenderExactlyTimes,
8-
});
11+
})
912

1013
declare global {
14+
// eslint-disable-next-line @typescript-eslint/no-namespace
1115
namespace jest {
16+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
1217
interface Matchers<R = void, T = {}> extends RenderStreamMatchers<R, T> {}
1318
}
1419
}

‎src/jest/renderStreamMatchers.ts

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,110 @@
1-
import type { MatcherFunction } from "expect";
2-
import { WaitForRenderTimeoutError } from "@testing-library/react-render-stream";
3-
import type {
4-
Assertable,
5-
NextRenderOptions,
6-
RenderStream,
7-
} from "@testing-library/react-render-stream";
1+
import {MatcherContext, type MatcherFunction} from 'expect'
2+
import {
3+
WaitForRenderTimeoutError,
4+
type Assertable,
5+
type NextRenderOptions,
6+
type RenderStream,
7+
} from '@testing-library/react-render-stream'
88
// explicitly imported the symbol from the internal file
99
// this will bundle the `Symbol.for` call twice, but we keep it private
10-
import { assertableSymbol } from "../assertable.js";
10+
import {assertableSymbol} from '../assertable.js'
1111

1212
export interface RenderStreamMatchers<R = void, T = {}> {
1313
toRerender: T extends RenderStream<any> | Assertable
1414
? (options?: NextRenderOptions) => Promise<R>
1515
: {
16-
error: "matcher needs to be called on a `takeRender` function, `takeSnapshot` function or `RenderStream` instance";
17-
};
16+
error: 'matcher needs to be called on a `takeRender` function, `takeSnapshot` function or `RenderStream` instance'
17+
}
1818

1919
toRenderExactlyTimes: T extends RenderStream<any> | Assertable
2020
? (count: number, options?: NextRenderOptions) => Promise<R>
2121
: {
22-
error: "matcher needs to be called on a `takeRender` function, `takeSnapshot` function or `RenderStream` instance";
23-
};
22+
error: 'matcher needs to be called on a `takeRender` function, `takeSnapshot` function or `RenderStream` instance'
23+
}
2424
}
2525

2626
export const toRerender: MatcherFunction<[options?: NextRenderOptions]> =
27-
async function (actual, options) {
28-
const _stream = actual as RenderStream<any> | Assertable;
27+
async function toRerender(this: MatcherContext, actual, options) {
28+
const _stream = actual as RenderStream<any> | Assertable
2929
const stream =
30-
assertableSymbol in _stream ? _stream[assertableSymbol] : _stream;
31-
const hint = this.utils.matcherHint("toRerender");
32-
let pass = true;
30+
assertableSymbol in _stream ? _stream[assertableSymbol] : _stream
31+
const hint = this.utils.matcherHint('toRerender')
32+
let pass = true
3333
try {
34-
await stream.peekRender({ timeout: 100, ...options });
34+
await stream.peekRender({timeout: 100, ...options})
3535
} catch (e) {
3636
if (e instanceof WaitForRenderTimeoutError) {
37-
pass = false;
37+
pass = false
3838
} else {
39-
throw e;
39+
throw e
4040
}
4141
}
4242

4343
return {
4444
pass,
4545
message() {
4646
return (
47-
hint +
48-
`\n\nExpected component to${pass ? " not" : ""} rerender, ` +
49-
`but it did${pass ? "" : " not"}.`
50-
);
47+
`${hint}\n\nExpected component to${pass ? ' not' : ''} rerender, ` +
48+
`but it did${pass ? '' : ' not'}.`
49+
)
5150
},
52-
};
53-
};
51+
}
52+
}
5453

5554
/** to be thrown to "break" test execution and fail it */
56-
const failed = {};
55+
const failed = new Error()
5756

5857
export const toRenderExactlyTimes: MatcherFunction<
5958
[times: number, options?: NextRenderOptions]
60-
> = async function (actual, times, optionsPerRender) {
61-
const _stream = actual as RenderStream<any> | Assertable;
59+
> = async function toRenderExactlyTimes(
60+
this: MatcherContext,
61+
actual,
62+
times,
63+
optionsPerRender,
64+
) {
65+
const _stream = actual as RenderStream<any> | Assertable
6266
const stream =
63-
assertableSymbol in _stream ? _stream[assertableSymbol] : _stream;
64-
const options = { timeout: 100, ...optionsPerRender };
65-
const hint = this.utils.matcherHint("toRenderExactlyTimes");
66-
let pass = true;
67+
assertableSymbol in _stream ? _stream[assertableSymbol] : _stream
68+
const options = {timeout: 100, ...optionsPerRender}
69+
const hint = this.utils.matcherHint('toRenderExactlyTimes')
70+
let pass = true
6771
try {
6872
if (stream.totalRenderCount() > times) {
69-
throw failed;
73+
throw failed
7074
}
7175
try {
7276
while (stream.totalRenderCount() < times) {
73-
await stream.waitForNextRender(options);
77+
// eslint-disable-next-line no-await-in-loop
78+
await stream.waitForNextRender(options)
7479
}
7580
} catch (e) {
7681
// timeouts here should just fail the test, rethrow other errors
77-
throw e instanceof WaitForRenderTimeoutError ? failed : e;
82+
throw e instanceof WaitForRenderTimeoutError ? failed : e
7883
}
7984
try {
80-
await stream.waitForNextRender(options);
85+
await stream.waitForNextRender(options)
8186
} catch (e) {
8287
// we are expecting a timeout here, so swallow that error, rethrow others
8388
if (!(e instanceof WaitForRenderTimeoutError)) {
84-
throw e;
89+
throw e
8590
}
8691
}
8792
} catch (e) {
8893
if (e === failed) {
89-
pass = false;
94+
pass = false
9095
} else {
91-
throw e;
96+
throw e
9297
}
9398
}
9499
return {
95100
pass,
96101
message() {
97102
return (
98-
hint +
99-
` Expected component to${pass ? " not" : ""} render exactly ${times}.` +
103+
`${
104+
hint
105+
} Expected component to${pass ? ' not' : ''} render exactly ${times}.` +
100106
` It rendered ${stream.totalRenderCount()} times.`
101-
);
107+
)
102108
},
103-
};
104-
};
109+
}
110+
}

‎src/renderHookToSnapshotStream.tsx

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,88 @@
1-
import { RenderHookOptions } from "@testing-library/react";
2-
import { createRenderStream } from "./renderStream/createRenderStream.js";
3-
import type { NextRenderOptions } from "./renderStream/createRenderStream.js";
1+
import {RenderHookOptions} from '@testing-library/react'
2+
import {createElement} from 'rehackt'
3+
import {createRenderStream} from './renderStream/createRenderStream.js'
4+
import {type NextRenderOptions} from './renderStream/createRenderStream.js'
45

5-
import { Render } from "./renderStream/Render.js";
6-
import { createElement } from "rehackt";
7-
import { Assertable, assertableSymbol, markAssertable } from "./assertable.js";
6+
import {Render} from './renderStream/Render.js'
7+
import {Assertable, assertableSymbol, markAssertable} from './assertable.js'
88

99
export interface SnapshotStream<Snapshot, Props> extends Assertable {
1010
/**
1111
* An array of all renders that have happened so far.
1212
* Errors thrown during component render will be captured here, too.
1313
*/
1414
renders: Array<
15-
| Render<{ value: Snapshot }>
16-
| { phase: "snapshotError"; count: number; error: unknown }
17-
>;
15+
| Render<{value: Snapshot}>
16+
| {phase: 'snapshotError'; count: number; error: unknown}
17+
>
1818
/**
1919
* Peeks the next render from the current iterator position, without advancing the iterator.
2020
* If no render has happened yet, it will wait for the next render to happen.
2121
* @throws {WaitForRenderTimeoutError} if no render happens within the timeout
2222
*/
23-
peekSnapshot(options?: NextRenderOptions): Promise<Snapshot>;
23+
peekSnapshot(options?: NextRenderOptions): Promise<Snapshot>
2424
/**
2525
* Iterates to the next render and returns it.
2626
* If no render has happened yet, it will wait for the next render to happen.
2727
* @throws {WaitForRenderTimeoutError} if no render happens within the timeout
2828
*/
2929
takeSnapshot: Assertable &
30-
((options?: NextRenderOptions) => Promise<Snapshot>);
30+
((options?: NextRenderOptions) => Promise<Snapshot>)
3131
/**
3232
* Returns the total number of renders.
3333
*/
34-
totalSnapshotCount(): number;
34+
totalSnapshotCount(): number
3535
/**
3636
* Returns the current render.
3737
* @throws {Error} if no render has happened yet
3838
*/
39-
getCurrentSnapshot(): Snapshot;
39+
getCurrentSnapshot(): Snapshot
4040
/**
4141
* Waits for the next render to happen.
4242
* Does not advance the render iterator.
4343
*/
44-
waitForNextSnapshot(options?: NextRenderOptions): Promise<Snapshot>;
45-
rerender: (rerenderCallbackProps: Props) => void;
46-
unmount: () => void;
44+
waitForNextSnapshot(options?: NextRenderOptions): Promise<Snapshot>
45+
rerender: (rerenderCallbackProps: Props) => void
46+
unmount: () => void
4747
}
4848

4949
export function renderHookToSnapshotStream<ReturnValue, Props extends {}>(
5050
renderCallback: (props: Props) => ReturnValue,
51-
{ initialProps, ...options }: RenderHookOptions<Props> = {}
51+
{initialProps, ...renderOptions}: RenderHookOptions<Props> = {},
5252
): SnapshotStream<ReturnValue, Props> {
53-
const { render, ...stream } = createRenderStream<{ value: ReturnValue }>();
53+
const {render, ...stream} = createRenderStream<{value: ReturnValue}>()
5454

55-
const HookComponent: React.FC<Props> = (props) => {
56-
stream.replaceSnapshot({ value: renderCallback(props) });
57-
return null;
58-
};
55+
const HookComponent: React.FC<Props> = props => {
56+
stream.replaceSnapshot({value: renderCallback(props)})
57+
return null
58+
}
5959

60-
const { rerender: baseRerender, unmount } = render(
60+
const {rerender: baseRerender, unmount} = render(
6161
createElement(HookComponent, initialProps),
62-
options
63-
);
62+
renderOptions,
63+
)
6464

6565
function rerender(rerenderCallbackProps: Props) {
66-
return baseRerender(createElement(HookComponent, rerenderCallbackProps));
66+
return baseRerender(createElement(HookComponent, rerenderCallbackProps))
6767
}
6868

6969
return {
7070
[assertableSymbol]: stream,
7171
renders: stream.renders,
7272
totalSnapshotCount: stream.totalRenderCount,
7373
async peekSnapshot(options) {
74-
return (await stream.peekRender(options)).snapshot.value;
74+
return (await stream.peekRender(options)).snapshot.value
7575
},
7676
takeSnapshot: markAssertable(async function takeSnapshot(options) {
77-
return (await stream.takeRender(options)).snapshot.value;
77+
return (await stream.takeRender(options)).snapshot.value
7878
}, stream),
7979
getCurrentSnapshot() {
80-
return stream.getCurrentRender().snapshot.value;
80+
return stream.getCurrentRender().snapshot.value
8181
},
8282
async waitForNextSnapshot(options) {
83-
return (await stream.waitForNextRender(options)).snapshot.value;
83+
return (await stream.waitForNextRender(options)).snapshot.value
8484
},
8585
rerender,
8686
unmount,
87-
};
87+
}
8888
}

‎src/renderStream/Render.tsx

Lines changed: 114 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,43 @@ if we do not ignore this file in code coverage.
99
As we only use this file in our internal tests, we can safely ignore it.
1010
*/
1111

12-
import { within, screen } from "@testing-library/dom";
13-
import { JSDOM, VirtualConsole } from "jsdom";
12+
import {within, screen} from '@testing-library/dom'
13+
import {JSDOM, VirtualConsole} from 'jsdom'
1414

1515
export interface BaseRender {
16-
id: string;
17-
phase: "mount" | "update" | "nested-update";
18-
actualDuration: number;
19-
baseDuration: number;
20-
startTime: number;
21-
commitTime: number;
16+
id: string
17+
phase: 'mount' | 'update' | 'nested-update'
18+
actualDuration: number
19+
baseDuration: number
20+
startTime: number
21+
commitTime: number
2222
/**
2323
* The number of renders that have happened so far (including this render).
2424
*/
25-
count: number;
25+
count: number
2626
}
2727

28-
type Screen = typeof screen;
28+
type Screen = typeof screen
2929

3030
export type SyncScreen = {
3131
[K in keyof Screen]: K extends `find${string}`
3232
? {
3333
/** @deprecated A snapshot is static, so avoid async queries! */
34-
(...args: Parameters<Screen[K]>): ReturnType<Screen[K]>;
34+
(...args: Parameters<Screen[K]>): ReturnType<Screen[K]>
3535
}
36-
: Screen[K];
37-
};
36+
: Screen[K]
37+
}
3838

3939
export interface Render<Snapshot> extends BaseRender {
4040
/**
4141
* The snapshot, as returned by the `takeSnapshot` option of `createRenderStream`.
4242
*/
43-
snapshot: Snapshot;
43+
snapshot: Snapshot
4444
/**
4545
* A DOM snapshot of the rendered component, if the `snapshotDOM`
4646
* option of `createRenderStream` was enabled.
4747
*/
48-
readonly domSnapshot: HTMLElement;
48+
readonly domSnapshot: HTMLElement
4949
/**
5050
* Returns a callback to receive a `screen` instance that is scoped to the
5151
* DOM snapshot of this `Render` instance.
@@ -57,65 +57,71 @@ export interface Render<Snapshot> extends BaseRender {
5757
* +expect(withinDOM().getByText("foo")).toBeInTheDocument();
5858
* ```
5959
*/
60-
withinDOM: () => SyncScreen;
60+
withinDOM: () => SyncScreen
6161

62-
renderedComponents: Array<string | React.ComponentType>;
62+
renderedComponents: Array<string | React.ComponentType>
6363
}
6464

6565
export class RenderInstance<Snapshot> implements Render<Snapshot> {
66-
id: string;
67-
phase: "mount" | "update" | "nested-update";
68-
actualDuration: number;
69-
baseDuration: number;
70-
startTime: number;
71-
commitTime: number;
72-
count: number;
66+
id: string
67+
phase: 'mount' | 'update' | 'nested-update'
68+
actualDuration: number
69+
baseDuration: number
70+
startTime: number
71+
commitTime: number
72+
count: number
73+
public snapshot: Snapshot
74+
private stringifiedDOM: string | undefined
75+
public renderedComponents: Array<string | React.ComponentType>
7376

7477
constructor(
7578
baseRender: BaseRender,
76-
public snapshot: Snapshot,
77-
private stringifiedDOM: string | undefined,
78-
public renderedComponents: Array<string | React.ComponentType>
79+
snapshot: Snapshot,
80+
stringifiedDOM: string | undefined,
81+
renderedComponents: Array<string | React.ComponentType>,
7982
) {
80-
this.id = baseRender.id;
81-
this.phase = baseRender.phase;
82-
this.actualDuration = baseRender.actualDuration;
83-
this.baseDuration = baseRender.baseDuration;
84-
this.startTime = baseRender.startTime;
85-
this.commitTime = baseRender.commitTime;
86-
this.count = baseRender.count;
83+
this.snapshot = snapshot
84+
this.stringifiedDOM = stringifiedDOM
85+
this.renderedComponents = renderedComponents
86+
this.id = baseRender.id
87+
this.phase = baseRender.phase
88+
this.actualDuration = baseRender.actualDuration
89+
this.baseDuration = baseRender.baseDuration
90+
this.startTime = baseRender.startTime
91+
this.commitTime = baseRender.commitTime
92+
this.count = baseRender.count
8793
}
8894

89-
private _domSnapshot: HTMLElement | undefined;
95+
private _domSnapshot: HTMLElement | undefined
9096
get domSnapshot() {
91-
if (this._domSnapshot) return this._domSnapshot;
97+
if (this._domSnapshot) return this._domSnapshot
9298
if (!this.stringifiedDOM) {
9399
throw new Error(
94-
"DOM snapshot is not available - please set the `snapshotDOM` option"
95-
);
100+
'DOM snapshot is not available - please set the `snapshotDOM` option',
101+
)
96102
}
97103

98-
const virtualConsole = new VirtualConsole();
99-
virtualConsole.on("jsdomError", (error: any) => {
100-
throw error;
101-
});
104+
const virtualConsole = new VirtualConsole()
105+
virtualConsole.on('jsdomError', (error: any) => {
106+
throw error
107+
})
102108

103109
const snapDOM = new JSDOM(this.stringifiedDOM, {
104-
runScripts: "dangerously",
110+
runScripts: 'dangerously',
105111
virtualConsole,
106-
});
107-
const document = snapDOM.window.document;
108-
const body = document.body;
109-
const script = document.createElement("script");
110-
script.type = "text/javascript";
112+
})
113+
const document = snapDOM.window.document
114+
const body = document.body
115+
const script = document.createElement('script')
116+
script.type = 'text/javascript'
111117
script.text = `
112118
${errorOnDomInteraction.toString()};
113119
${errorOnDomInteraction.name}();
114-
`;
115-
body.appendChild(script);
116-
body.removeChild(script);
120+
`
121+
body.appendChild(script)
122+
body.removeChild(script)
117123

118-
return (this._domSnapshot = body);
124+
return (this._domSnapshot = body)
119125
}
120126

121127
get withinDOM(): () => SyncScreen {
@@ -128,70 +134,70 @@ export class RenderInstance<Snapshot> implements Render<Snapshot> {
128134
typeof screen.logTestingPlaygroundURL
129135
>
130136
) => screen.logTestingPlaygroundURL(dom, ...rest),
131-
});
132-
return () => snapScreen;
137+
})
138+
return () => snapScreen
133139
}
134140
}
135141

136142
export function errorOnDomInteraction() {
137143
const events: Array<keyof DocumentEventMap> = [
138-
"auxclick",
139-
"blur",
140-
"change",
141-
"click",
142-
"copy",
143-
"cut",
144-
"dblclick",
145-
"drag",
146-
"dragend",
147-
"dragenter",
148-
"dragleave",
149-
"dragover",
150-
"dragstart",
151-
"drop",
152-
"focus",
153-
"focusin",
154-
"focusout",
155-
"input",
156-
"keydown",
157-
"keypress",
158-
"keyup",
159-
"mousedown",
160-
"mouseenter",
161-
"mouseleave",
162-
"mousemove",
163-
"mouseout",
164-
"mouseover",
165-
"mouseup",
166-
"paste",
167-
"pointercancel",
168-
"pointerdown",
169-
"pointerenter",
170-
"pointerleave",
171-
"pointermove",
172-
"pointerout",
173-
"pointerover",
174-
"pointerup",
175-
"scroll",
176-
"select",
177-
"selectionchange",
178-
"selectstart",
179-
"submit",
180-
"toggle",
181-
"touchcancel",
182-
"touchend",
183-
"touchmove",
184-
"touchstart",
185-
"wheel",
186-
];
144+
'auxclick',
145+
'blur',
146+
'change',
147+
'click',
148+
'copy',
149+
'cut',
150+
'dblclick',
151+
'drag',
152+
'dragend',
153+
'dragenter',
154+
'dragleave',
155+
'dragover',
156+
'dragstart',
157+
'drop',
158+
'focus',
159+
'focusin',
160+
'focusout',
161+
'input',
162+
'keydown',
163+
'keypress',
164+
'keyup',
165+
'mousedown',
166+
'mouseenter',
167+
'mouseleave',
168+
'mousemove',
169+
'mouseout',
170+
'mouseover',
171+
'mouseup',
172+
'paste',
173+
'pointercancel',
174+
'pointerdown',
175+
'pointerenter',
176+
'pointerleave',
177+
'pointermove',
178+
'pointerout',
179+
'pointerover',
180+
'pointerup',
181+
'scroll',
182+
'select',
183+
'selectionchange',
184+
'selectstart',
185+
'submit',
186+
'toggle',
187+
'touchcancel',
188+
'touchend',
189+
'touchmove',
190+
'touchstart',
191+
'wheel',
192+
]
187193
function warnOnDomInteraction() {
188194
throw new Error(`
189195
DOM interaction with a snapshot detected in test.
190196
Please don't interact with the DOM you get from \`withinDOM\`,
191-
but still use \`screen\' to get elements for simulating user interaction.
192-
`);
197+
but still use \`screen\` to get elements for simulating user interaction.
198+
`)
193199
}
194-
events.forEach((event) => {
195-
document.addEventListener(event, warnOnDomInteraction);
196-
});
200+
events.forEach(event => {
201+
document.addEventListener(event, warnOnDomInteraction)
202+
})
197203
}

‎src/renderStream/context.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
1-
import * as React from "rehackt";
1+
import * as React from 'rehackt'
22

33
export interface RenderStreamContextValue {
4-
renderedComponents: Array<React.ComponentType | string>;
4+
renderedComponents: Array<React.ComponentType | string>
55
}
66

77
const RenderStreamContext = React.createContext<
88
RenderStreamContextValue | undefined
9-
>(undefined);
9+
>(undefined)
1010

1111
export function RenderStreamContextProvider({
1212
children,
1313
value,
1414
}: {
15-
children: React.ReactNode;
16-
value: RenderStreamContextValue;
15+
children: React.ReactNode
16+
value: RenderStreamContextValue
1717
}) {
18-
const parentContext = useRenderStreamContext();
18+
const parentContext = useRenderStreamContext()
1919

2020
if (parentContext) {
21-
throw new Error("Render streams should not be nested in the same tree");
21+
throw new Error('Render streams should not be nested in the same tree')
2222
}
2323

2424
return (
2525
<RenderStreamContext.Provider value={value}>
2626
{children}
2727
</RenderStreamContext.Provider>
28-
);
28+
)
2929
}
3030

3131
export function useRenderStreamContext() {
32-
return React.useContext(RenderStreamContext);
32+
return React.useContext(RenderStreamContext)
3333
}

‎src/renderStream/createRenderStream.tsx

Lines changed: 152 additions & 151 deletions
Large diffs are not rendered by default.

‎src/renderStream/disableActWarnings.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
* https://github.com/reactwg/react-18/discussions/102
55
*/
66
export function disableActWarnings() {
7-
const anyThis = globalThis as any;
8-
const prevActEnv = anyThis.IS_REACT_ACT_ENVIRONMENT;
9-
anyThis.IS_REACT_ACT_ENVIRONMENT = false;
7+
const anyThis = globalThis as any as {IS_REACT_ACT_ENVIRONMENT?: boolean}
8+
const prevActEnv = anyThis.IS_REACT_ACT_ENVIRONMENT
9+
anyThis.IS_REACT_ACT_ENVIRONMENT = false
1010

1111
return {
1212
[Symbol.dispose]() {
13-
anyThis.IS_REACT_ACT_ENVIRONMENT = prevActEnv;
13+
anyThis.IS_REACT_ACT_ENVIRONMENT = prevActEnv
1414
},
15-
};
15+
}
1616
}

‎src/renderToRenderStream.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import {
22
type RenderOptions as BaseOptions,
33
type RenderResult as BaseResult,
4-
} from "@testing-library/react";
5-
import { createRenderStream } from "./renderStream/createRenderStream.js";
6-
import type {
7-
RenderStreamOptions,
8-
RenderStream,
9-
ValidSnapshot,
10-
} from "./renderStream/createRenderStream.js";
4+
} from '@testing-library/react'
5+
import {
6+
createRenderStream,
7+
type RenderStreamOptions,
8+
type RenderStream,
9+
type ValidSnapshot,
10+
} from './renderStream/createRenderStream.js'
1111

1212
type RenderOptions<Snapshot extends ValidSnapshot = void> = BaseOptions &
13-
RenderStreamOptions<Snapshot>;
13+
RenderStreamOptions<Snapshot>
1414

1515
export interface RenderStreamWithRenderResult<
1616
Snapshot extends ValidSnapshot = void,
1717
> extends RenderStream<Snapshot> {
18-
renderResultPromise: Promise<BaseResult>;
18+
renderResultPromise: Promise<BaseResult>
1919
}
2020

2121
/**
@@ -30,17 +30,17 @@ export function renderToRenderStream<Snapshot extends ValidSnapshot = void>(
3030
initialSnapshot,
3131
skipNonTrackingRenders,
3232
...options
33-
}: RenderOptions<Snapshot> = {}
33+
}: RenderOptions<Snapshot> = {},
3434
): RenderStreamWithRenderResult<Snapshot> {
35-
const { render, ...stream } = createRenderStream<Snapshot>({
35+
const {render, ...stream} = createRenderStream<Snapshot>({
3636
onRender,
3737
snapshotDOM,
3838
initialSnapshot,
3939
skipNonTrackingRenders,
40-
});
40+
})
4141
// `render` needs to be called asynchronously here, because the definition of `ui`
4242
// might contain components that reference the return value of `renderToRenderStream`
4343
// itself, e.g. `replaceSnapshot` or `mergeSnapshot`.
44-
const renderResultPromise = Promise.resolve().then(() => render(ui, options));
45-
return { ...stream, renderResultPromise };
44+
const renderResultPromise = Promise.resolve().then(() => render(ui, options))
45+
return {...stream, renderResultPromise}
4646
}

‎tsconfig.json

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,12 @@
1010
"sourceMap": true,
1111
"jsx": "react",
1212
"declarationMap": true,
13-
"types": [
14-
"react",
15-
"node"
16-
],
13+
"types": ["react", "node"],
1714
"esModuleInterop": true,
1815
"allowSyntheticDefaultImports": true,
1916
"paths": {
20-
"@testing-library/react-render-stream": [
21-
"./src/index.ts"
22-
]
17+
"@testing-library/react-render-stream": ["./src/index.ts"]
2318
}
2419
},
25-
"include": [
26-
"src"
27-
]
28-
}
20+
"include": ["src"]
21+
}

‎tsup.config.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { defineConfig } from "tsup";
1+
import {defineConfig} from 'tsup'
22

33
export default defineConfig({
44
entry: {
5-
index: "src/index.ts",
6-
jest: "src/jest/index.ts",
5+
index: 'src/index.ts',
6+
jest: 'src/jest/index.ts',
77
},
88
splitting: false,
99
sourcemap: true,
1010
clean: true,
1111
dts: true,
12-
format: ["cjs", "esm"],
13-
target: ["node20"],
12+
format: ['cjs', 'esm'],
13+
target: ['node20'],
1414
external: [/^@testing-library\/react-render-stream/],
15-
});
15+
})

‎yarn.lock

Lines changed: 8293 additions & 1529 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.