@khanacademy/wonder-blocks-testing 10.1.1 → 11.0.1

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.
Files changed (87) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/es/index.js +15 -390
  3. package/dist/gql/types.d.ts +1 -2
  4. package/dist/harness/adapters/data.d.ts +1 -1
  5. package/dist/harness/adapters/index.d.ts +41 -0
  6. package/dist/harness/adapters/ssr.d.ts +1 -1
  7. package/dist/index.d.ts +8 -13
  8. package/dist/index.js +54 -399
  9. package/package.json +9 -7
  10. package/src/gql/__tests__/mock-gql-fetch.test.tsx +1 -1
  11. package/src/gql/__tests__/types.typestest.ts +1 -1
  12. package/src/gql/__tests__/wb-data-integration.test.tsx +1 -1
  13. package/src/gql/mock-gql-fetch.ts +1 -1
  14. package/src/gql/types.ts +4 -2
  15. package/src/harness/adapters/__tests__/ssr.test.tsx +1 -1
  16. package/src/harness/adapters/data.tsx +1 -1
  17. package/src/harness/adapters/{adapters.ts → index.ts} +10 -11
  18. package/src/harness/adapters/ssr.tsx +1 -1
  19. package/src/index.ts +32 -13
  20. package/tsconfig-build.json +1 -0
  21. package/tsconfig-build.tsbuildinfo +1 -1
  22. package/dist/fetch/fetch-request-matches-mock.d.ts +0 -5
  23. package/dist/fetch/mock-fetch.d.ts +0 -5
  24. package/dist/fetch/types.d.ts +0 -9
  25. package/dist/fixtures/fixtures.basic.stories.d.ts +0 -13
  26. package/dist/fixtures/fixtures.d.ts +0 -13
  27. package/dist/fixtures/fixtures.defaultwrapper.stories.d.ts +0 -9
  28. package/dist/fixtures/types.d.ts +0 -36
  29. package/dist/harness/adapt.d.ts +0 -17
  30. package/dist/harness/adapters/adapters.d.ts +0 -36
  31. package/dist/harness/adapters/css.d.ts +0 -12
  32. package/dist/harness/adapters/portal.d.ts +0 -12
  33. package/dist/harness/adapters/router.d.ts +0 -94
  34. package/dist/harness/get-named-adapter-component.d.ts +0 -16
  35. package/dist/harness/hook-harness.d.ts +0 -13
  36. package/dist/harness/make-hook-harness.d.ts +0 -17
  37. package/dist/harness/make-test-harness.d.ts +0 -15
  38. package/dist/harness/test-harness.d.ts +0 -33
  39. package/dist/harness/types.d.ts +0 -36
  40. package/dist/mock-requester.d.ts +0 -5
  41. package/dist/respond-with.d.ts +0 -75
  42. package/dist/response-impl.d.ts +0 -1
  43. package/dist/settle-controller.d.ts +0 -19
  44. package/dist/settle-signal.d.ts +0 -18
  45. package/dist/types.d.ts +0 -25
  46. package/src/__tests__/mock-requester.test.ts +0 -212
  47. package/src/__tests__/respond-with.test.ts +0 -524
  48. package/src/__tests__/response-impl.test.js +0 -47
  49. package/src/__tests__/settle-controller.test.ts +0 -28
  50. package/src/__tests__/settle-signal.test.ts +0 -104
  51. package/src/fetch/__tests__/__snapshots__/mock-fetch.test.ts.snap +0 -29
  52. package/src/fetch/__tests__/fetch-request-matches-mock.test.ts +0 -98
  53. package/src/fetch/__tests__/mock-fetch.test.ts +0 -83
  54. package/src/fetch/fetch-request-matches-mock.ts +0 -42
  55. package/src/fetch/mock-fetch.ts +0 -20
  56. package/src/fetch/types.ts +0 -14
  57. package/src/fixtures/__tests__/fixtures.test.tsx +0 -147
  58. package/src/fixtures/fixtures.basic.stories.tsx +0 -62
  59. package/src/fixtures/fixtures.defaultwrapper.stories.tsx +0 -49
  60. package/src/fixtures/fixtures.tsx +0 -72
  61. package/src/fixtures/types.ts +0 -42
  62. package/src/harness/__tests__/adapt.test.tsx +0 -248
  63. package/src/harness/__tests__/hook-harness.test.ts +0 -73
  64. package/src/harness/__tests__/make-hook-harness.test.tsx +0 -93
  65. package/src/harness/__tests__/make-test-harness.test.tsx +0 -195
  66. package/src/harness/__tests__/test-harness.test.ts +0 -75
  67. package/src/harness/__tests__/types.typestest.tsx +0 -103
  68. package/src/harness/adapt.tsx +0 -41
  69. package/src/harness/adapters/__tests__/__snapshots__/router.test.tsx.snap +0 -5
  70. package/src/harness/adapters/__tests__/css.test.tsx +0 -95
  71. package/src/harness/adapters/__tests__/portal.test.tsx +0 -30
  72. package/src/harness/adapters/__tests__/router.test.tsx +0 -252
  73. package/src/harness/adapters/css.tsx +0 -66
  74. package/src/harness/adapters/portal.tsx +0 -25
  75. package/src/harness/adapters/router.tsx +0 -205
  76. package/src/harness/get-named-adapter-component.tsx +0 -36
  77. package/src/harness/hook-harness.ts +0 -22
  78. package/src/harness/make-hook-harness.tsx +0 -40
  79. package/src/harness/make-test-harness.tsx +0 -60
  80. package/src/harness/test-harness.ts +0 -13
  81. package/src/harness/types.ts +0 -47
  82. package/src/mock-requester.ts +0 -68
  83. package/src/respond-with.ts +0 -263
  84. package/src/response-impl.ts +0 -8
  85. package/src/settle-controller.ts +0 -34
  86. package/src/settle-signal.ts +0 -42
  87. package/src/types.ts +0 -40
@@ -1,263 +0,0 @@
1
- import {SettleSignal} from "./settle-signal";
2
- import {ResponseImpl} from "./response-impl";
3
- import type {GraphQLJson} from "./types";
4
-
5
- /**
6
- * This symbol is used so we can create an opaque type, using a custom field
7
- * that cannot be directly referenced since folks won't have access to the
8
- * symbol.
9
- *
10
- * See https://stackoverflow.com/a/56749647/23234
11
- */
12
- declare const opaque: unique symbol;
13
-
14
- // We want the parameterization here so that folks can assert a response is
15
- // of a specific type if passing between various functions. For example,
16
- // the graphql mocking framework might want to assert a response is returning
17
- // the expected data structure. We could use `opaque` but that would then
18
- // hide the `toPromise` call we want to provide.
19
- /* eslint-disable @typescript-eslint/no-unused-vars */
20
- /**
21
- * Describes a mock response to a fetch request.
22
- */
23
- export type MockResponse<TData> = {
24
- /**
25
- * This is used to enforce the use of the TData type parameter. We won't
26
- * actually attach anything to this field. Doing this makes sure that
27
- * TData is relevant to the response. Without it, it will get ignored
28
- * and a value of type MockResponse<string> will be considered the same
29
- * type as a value of type MockResponse<number> (or any other type
30
- * constraint).
31
- */
32
- [opaque]: TData;
33
-
34
- /**
35
- * Create a promise from the mocked response.
36
- *
37
- * If a signal was provided when the mock response was created, the promise
38
- * will only settle to resolution or rejection if the signal is raised.
39
- */
40
- readonly toPromise: () => Promise<Response>;
41
- };
42
- /* eslint-enable @typescript-eslint/no-unused-vars */
43
-
44
- type InternalMockResponse =
45
- | {
46
- readonly type: "text";
47
- readonly text: string | (() => string);
48
- readonly statusCode: number;
49
- readonly signal: SettleSignal | null | undefined;
50
- }
51
- | {
52
- readonly type: "reject";
53
- readonly error: Error | (() => Error);
54
- readonly signal: SettleSignal | null | undefined;
55
- };
56
-
57
- /**
58
- * Helper for creating a text-based mock response.
59
- */
60
- const textResponse = <TData>(
61
- text: string | (() => string),
62
- statusCode: number,
63
- signal?: SettleSignal | null,
64
- ): MockResponse<TData> =>
65
- ({
66
- toPromise: () =>
67
- makeMockResponse({
68
- type: "text",
69
- text,
70
- statusCode,
71
- signal,
72
- }),
73
- } as MockResponse<TData>);
74
-
75
- /**
76
- * Helper for creating a rejected mock response.
77
- */
78
- const rejectResponse = (
79
- error: Error | (() => Error),
80
- signal?: SettleSignal | null,
81
- ): MockResponse<never> =>
82
- ({
83
- toPromise: () =>
84
- makeMockResponse({
85
- type: "reject",
86
- error,
87
- signal,
88
- }),
89
- } as MockResponse<never>);
90
-
91
- /**
92
- * Helpers to define mock responses for mocked requests.
93
- */
94
- export const RespondWith = Object.freeze({
95
- /**
96
- * Response with text body and status code.
97
- * Status code defaults to 200.
98
- */
99
- text: <TData = string>(
100
- text: string,
101
- statusCode = 200,
102
- signal: SettleSignal | null = null,
103
- ): MockResponse<TData> => textResponse<TData>(text, statusCode, signal),
104
-
105
- /**
106
- * Response with JSON body and status code 200.
107
- */
108
- json: <TJson extends Record<any, any>>(
109
- json: TJson,
110
- signal: SettleSignal | null = null,
111
- ): MockResponse<TJson> =>
112
- textResponse<TJson>(() => JSON.stringify(json), 200, signal),
113
-
114
- /**
115
- * Response with GraphQL data JSON body and status code 200.
116
- */
117
- graphQLData: <TData extends Record<any, any>>(
118
- data: TData,
119
- signal: SettleSignal | null = null,
120
- ): MockResponse<GraphQLJson<TData>> =>
121
- textResponse<GraphQLJson<TData>>(
122
- () => JSON.stringify({data}),
123
- 200,
124
- signal,
125
- ),
126
-
127
- /**
128
- * Response with body that will not parse as JSON and status code 200.
129
- */
130
- unparseableBody: (signal: SettleSignal | null = null): MockResponse<any> =>
131
- textResponse("INVALID JSON", 200, signal),
132
-
133
- /**
134
- * Rejects with an AbortError to simulate an aborted request.
135
- */
136
- abortedRequest: (signal: SettleSignal | null = null): MockResponse<any> =>
137
- rejectResponse(() => {
138
- const abortError = new Error("Mock request aborted");
139
- abortError.name = "AbortError";
140
- return abortError;
141
- }, signal),
142
-
143
- /**
144
- * Rejects with the given error.
145
- */
146
- reject: (
147
- error: Error,
148
- signal: SettleSignal | null = null,
149
- ): MockResponse<any> => rejectResponse(error, signal),
150
-
151
- /**
152
- * A non-200 status code with empty text body.
153
- * Equivalent to calling `ResponseWith.text("", statusCode)`.
154
- */
155
- errorStatusCode: (
156
- statusCode: number,
157
- signal: SettleSignal | null = null,
158
- ): MockResponse<any> => {
159
- if (statusCode < 300) {
160
- throw new Error(`${statusCode} is not a valid error status code`);
161
- }
162
- return textResponse("{}", statusCode, signal);
163
- },
164
-
165
- /**
166
- * Response body that is valid JSON but not a valid GraphQL response.
167
- */
168
- nonGraphQLBody: (signal: SettleSignal | null = null): MockResponse<any> =>
169
- textResponse(
170
- () =>
171
- JSON.stringify({
172
- valid: "json",
173
- that: "is not a valid graphql response",
174
- }),
175
- 200,
176
- signal,
177
- ),
178
-
179
- /**
180
- * Response that is a GraphQL errors response with status code 200.
181
- */
182
- graphQLErrors: (
183
- errorMessages: ReadonlyArray<string>,
184
- signal: SettleSignal | null = null,
185
- ): MockResponse<GraphQLJson<any>> =>
186
- textResponse<GraphQLJson<any>>(
187
- () =>
188
- JSON.stringify({
189
- errors: errorMessages.map((e) => ({
190
- message: e,
191
- })),
192
- }),
193
- 200,
194
- signal,
195
- ),
196
- });
197
-
198
- const callOnSettled = (
199
- signal: SettleSignal | null | undefined,
200
- fn: () => void,
201
- ): void => {
202
- if (signal == null || signal.settled) {
203
- fn();
204
- return;
205
- }
206
-
207
- const onSettled = () => {
208
- signal.removeEventListener("settled", onSettled);
209
- fn();
210
- };
211
- signal.addEventListener("settled", onSettled);
212
- };
213
-
214
- /**
215
- * Turns a MockResponse value to an actual Response that represents the mock.
216
- */
217
- const makeMockResponse = (
218
- response: InternalMockResponse,
219
- ): Promise<Response> => {
220
- const {signal} = response;
221
-
222
- switch (response.type) {
223
- case "text":
224
- return new Promise((resolve, reject: (error?: any) => void) => {
225
- callOnSettled(signal, () => {
226
- const text =
227
- typeof response.text === "function"
228
- ? response.text()
229
- : response.text;
230
- resolve(
231
- new ResponseImpl(text, {status: response.statusCode}),
232
- );
233
- });
234
- });
235
-
236
- case "reject":
237
- return new Promise((resolve, reject: (error?: any) => void) => {
238
- callOnSettled(signal, () =>
239
- reject(
240
- response.error instanceof Error
241
- ? response.error
242
- : response.error(),
243
- ),
244
- );
245
- });
246
-
247
- /* istanbul ignore next */
248
- default:
249
- if (process.env.NODE_ENV !== "production") {
250
- // If we're not in production, give an immediate signal that the
251
- // dev forgot to support this new type.
252
- // @ts-expect-error TS knows we can't get here and so sees
253
- // `response` as `never`.
254
- throw new Error(`Unknown response type: ${response.type}`);
255
- }
256
- // Production; assume a rejection.
257
- return makeMockResponse({
258
- type: "reject",
259
- error: new Error("Unknown response type"),
260
- signal,
261
- });
262
- }
263
- };
@@ -1,8 +0,0 @@
1
- // We need a version of Response. When we're in Jest JSDOM environment or a
2
- // version of Node that supports the fetch API (17 and up, possibly with
3
- // --experimental-fetch flag), then we're good, but otherwise we need an
4
- // implementation, so this uses node-fetch as a peer dependency and uses that
5
- // to provide the implementation if we don't already have one.
6
- export const ResponseImpl: typeof Response =
7
- // eslint-disable-next-line @typescript-eslint/no-var-requires
8
- typeof Response === "undefined" ? require("node-fetch").Response : Response;
@@ -1,34 +0,0 @@
1
- import {SettleSignal} from "./settle-signal";
2
-
3
- /**
4
- * A controller for the `RespondWith` API to control response settlement.
5
- */
6
- export class SettleController {
7
- private _settleFn: undefined | (() => void);
8
- private _signal: SettleSignal;
9
-
10
- constructor() {
11
- // Create our signal.
12
- // We pass in a method to capture it's settle function so that
13
- // only we can call it.
14
- this._signal = new SettleSignal(
15
- (settleFn: () => void) => (this._settleFn = settleFn),
16
- );
17
- }
18
-
19
- /**
20
- * The signal to pass to the `RespondWith` API.
21
- */
22
- get signal(): SettleSignal {
23
- return this._signal;
24
- }
25
-
26
- /**
27
- * Settle the signal and therefore any associated responses.
28
- *
29
- * @throws {Error} if the signal has already been settled.
30
- */
31
- settle(): void {
32
- this._settleFn?.();
33
- }
34
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * A signal for controlling the `RespondWith` API responses.
3
- *
4
- * This provide finely-grained control over the promise lifecycle to support
5
- * complex test scenarios.
6
- */
7
- export class SettleSignal extends EventTarget {
8
- private _settled = false;
9
-
10
- constructor(
11
- setSettleFn: ((settleFn: () => void) => unknown) | null = null,
12
- ) {
13
- super();
14
-
15
- // If we were given a function, we call it with a method that will
16
- // settle ourselves. This allows the appropriate SettleController
17
- // to be in charge of settling this instance.
18
- setSettleFn?.(() => {
19
- if (this._settled) {
20
- throw new Error("SettleSignal already settled");
21
- }
22
- this._settled = true;
23
- this.dispatchEvent(new Event("settled"));
24
- });
25
- }
26
-
27
- /**
28
- * An already settled signal.
29
- */
30
- static settle(): SettleSignal {
31
- const signal = new SettleSignal();
32
- signal._settled = true;
33
- return signal;
34
- }
35
-
36
- /**
37
- * Has this signal been settled yet?
38
- */
39
- get settled(): boolean {
40
- return this._settled;
41
- }
42
- }
package/src/types.ts DELETED
@@ -1,40 +0,0 @@
1
- import type {MockResponse} from "./respond-with";
2
-
3
- /**
4
- * A valid GraphQL response as supported by our mocking framework.
5
- * Note that we don't currently support both data and errors being set.
6
- */
7
- export type GraphQLJson<TData extends Record<any, any>> =
8
- | {
9
- data: TData;
10
- }
11
- | {
12
- errors: Array<{
13
- message: string;
14
- }>;
15
- };
16
-
17
- export type MockFn<TOperationType> = {
18
- (...args: Array<any>): Promise<Response>;
19
- mockOperation: MockOperationFn<TOperationType>;
20
- mockOperationOnce: MockOperationFn<TOperationType>;
21
- };
22
-
23
- export type OperationMock<TOperation> = {
24
- operation: TOperation;
25
- onceOnly: boolean;
26
- used: boolean;
27
- response: () => Promise<Response>;
28
- };
29
-
30
- export type OperationMatcher<TOperation> = (
31
- operation: TOperation,
32
- ...args: Array<any>
33
- ) => boolean;
34
-
35
- export type MockOperationFn<TOperationType> = <
36
- TOperation extends TOperationType,
37
- >(
38
- operation: TOperation,
39
- response: MockResponse<any>,
40
- ) => MockFn<TOperationType>;