-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcomponents.ts
145 lines (133 loc) · 4.31 KB
/
components.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* A thin wrapper to
* [@testing-library/preact]{@link https://github.com/testing-library/preact-testing-library} and [@testing-library/user-event]{@link https://github.com/testing-library/user-event}
* for testing island components.
*
* @module
*/
import type { ComponentChild } from "preact";
import { options } from "preact";
import { AsyncLocalStorage } from "node:async_hooks";
import { setUpClipboard } from "./deps/jest-clipboard.ts";
export * from "./deps/testing-library.ts";
import {
cleanup as _cleanup,
render as _render,
} from "./deps/testing-library.ts";
import type {
Options,
Queries,
RenderOptions,
RenderResult,
} from "./deps/testing-library.ts";
import { userEvent } from "./deps/testing-library.ts";
import { createPartialsUpdater } from "./internal/fresh/partials.ts";
import { createVnodeHook } from "./internal/fresh/preact.ts";
import {
clearDefaultManifest,
maybeGetDefaultManifest,
setDefaultManifest,
} from "./internal/fresh/manifest.ts";
import { createDocument } from "./internal/jsdom/mod.ts";
// deno-lint-ignore no-unused-vars -- referenced by `@linkcode`
import type { CreateFreshContextOptions } from "./internal/fresh/context.ts";
import type { Manifest } from "$fresh/server.ts";
let cleanupVnodeHook: (() => void) | undefined = undefined;
const asyncLocalStorage = new AsyncLocalStorage<{ isCSR: true }>();
export function render(
ui: ComponentChild,
options?: Omit<RenderOptions, "queries">,
): RenderResult;
export function render<Q extends Queries>(
ui: ComponentChild,
options: RenderOptions<Q>,
): RenderResult<Q>;
export function render<Q extends Queries>(
ui: ComponentChild,
options?: RenderOptions<Q> | Omit<RenderOptions, "queries">,
): RenderResult<Q> | RenderResult {
return asyncLocalStorage.run({ isCSR: true }, () => _render(ui, options));
}
export function cleanup(): void {
_cleanup();
cleanupVnodeHook?.();
}
function isCSR(): boolean {
return asyncLocalStorage.getStore()?.isCSR === true;
}
/**
* Options which can be passed to {@linkcode setup}.
*/
export interface SetupOptions {
/**
* @description Optionally, the {@linkcode Manifest} object which is exported from `fresh.gen.ts` can be set to this option.
*
* If this option is specified, emulation of partial rendering is enabled.
*
* The {@linkcode Manifest} object specified by this option is also used as the default value for {@linkcode CreateFreshContextOptions.manifest}, etc.
*/
manifest?: Manifest;
}
/**
* This function sets up the DOM environment to make Testing Library work.
*
* This function must be called at least once before using various APIs of Testing Library.
*/
export function setup(options?: SetupOptions) {
if (options?.manifest) {
setDefaultManifest(options.manifest);
} else if (options && "manifest" in options) {
clearDefaultManifest();
}
setupDOMEnvironmentOnce();
setupPreactOptionsHooksOnce(location);
}
function setupDOMEnvironmentOnce(): void {
if (globalThis.document) return;
setupDocument();
setUpClipboard();
setupUserEvent();
}
function setupDocument(): void {
globalThis.document = createDocument();
if (globalThis.window == null) {
// NOTE: `window` will be removed in Deno v2
// See: https://github.com/testing-library/dom-testing-library/blob/v8.20.0/src/helpers.ts#L20-L26
// TODO: Find a better solution
// @ts-expect-error This is intended
globalThis.window = globalThis;
}
}
function setupUserEvent(): void {
/**
* NOTE: Workaround for the problem of `globalThis.document` not being set at the time of loading `@testing-library/user-event`.
* TODO: Need a better solution to this problem.
* {@link https://github.com/testing-library/user-event/blob/v14.5.1/src/setup/setup.ts#L25}
* {@link https://github.com/testing-library/user-event/blob/v14.5.1/src/setup/index.ts}
*/
const setupUserEvent = userEvent.setup;
Object.assign(userEvent, {
setup(options: Options) {
return setupUserEvent({
document,
...options,
});
},
});
}
function setupPreactOptionsHooksOnce(
location?: Location,
): void {
if (cleanupVnodeHook) return;
const { cleanup, vnode } = createVnodeHook(
options.vnode,
createPartialsUpdater(
maybeGetDefaultManifest,
document,
),
isCSR,
location,
);
options.vnode = vnode;
cleanupVnodeHook = cleanup;
}