@khanacademy/wonder-blocks-form 4.9.1 → 4.9.3

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 (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/components/checkbox-core.d.ts +2 -2
  3. package/dist/components/checkbox.d.ts +2 -2
  4. package/dist/components/choice-internal.d.ts +2 -2
  5. package/dist/components/choice.d.ts +2 -2
  6. package/dist/components/radio-core.d.ts +2 -2
  7. package/dist/components/radio.d.ts +2 -2
  8. package/dist/components/text-area.d.ts +2 -2
  9. package/dist/components/text-field.d.ts +4 -1
  10. package/dist/es/index.js +31 -78
  11. package/dist/index.js +31 -78
  12. package/package.json +7 -7
  13. package/src/__tests__/__snapshots__/custom-snapshot.test.tsx.snap +0 -247
  14. package/src/__tests__/custom-snapshot.test.tsx +0 -48
  15. package/src/components/__tests__/checkbox-group.test.tsx +0 -162
  16. package/src/components/__tests__/checkbox.test.tsx +0 -138
  17. package/src/components/__tests__/field-heading.test.tsx +0 -225
  18. package/src/components/__tests__/labeled-text-field.test.tsx +0 -727
  19. package/src/components/__tests__/radio-group.test.tsx +0 -182
  20. package/src/components/__tests__/text-area.test.tsx +0 -1286
  21. package/src/components/__tests__/text-field.test.tsx +0 -562
  22. package/src/components/checkbox-core.tsx +0 -239
  23. package/src/components/checkbox-group.tsx +0 -174
  24. package/src/components/checkbox.tsx +0 -99
  25. package/src/components/choice-internal.tsx +0 -184
  26. package/src/components/choice.tsx +0 -157
  27. package/src/components/field-heading.tsx +0 -169
  28. package/src/components/group-styles.ts +0 -33
  29. package/src/components/labeled-text-field.tsx +0 -317
  30. package/src/components/radio-core.tsx +0 -171
  31. package/src/components/radio-group.tsx +0 -159
  32. package/src/components/radio.tsx +0 -82
  33. package/src/components/text-area.tsx +0 -430
  34. package/src/components/text-field.tsx +0 -437
  35. package/src/index.ts +0 -17
  36. package/src/util/types.ts +0 -85
  37. package/tsconfig-build.json +0 -19
  38. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,562 +0,0 @@
1
- import * as React from "react";
2
- import {fireEvent, render, screen} from "@testing-library/react";
3
- import {userEvent} from "@testing-library/user-event";
4
-
5
- import {View} from "@khanacademy/wonder-blocks-core";
6
- import Button from "@khanacademy/wonder-blocks-button";
7
-
8
- import TextField from "../text-field";
9
-
10
- describe("TextField", () => {
11
- it("id prop is passed to input", async () => {
12
- // Arrange
13
-
14
- // Act
15
- render(<TextField id="custom-id" value="" onChange={() => {}} />);
16
-
17
- // Assert
18
- expect(await screen.findByRole("textbox")).toHaveAttribute(
19
- "id",
20
- "custom-id",
21
- );
22
- });
23
-
24
- it("auto-generated id is passed to input when id prop is not set", async () => {
25
- // Arrange
26
-
27
- // Act
28
- render(<TextField value="" onChange={() => {}} />);
29
-
30
- // Assert
31
- // Since the generated id is unique, we cannot know what it will be. We
32
- // only test if the id attribute starts with "uid-", then followed by
33
- // "text-field-" as the scope assigned to IDProvider.
34
- const input = await screen.findByRole("textbox");
35
- expect(input.getAttribute("id")).toMatch(/uid-text-field-.*$/);
36
- });
37
-
38
- it("textfield is focused", async () => {
39
- // Arrange
40
- render(<TextField id="tf-1" value="" onChange={() => {}} />);
41
-
42
- // Act
43
- await userEvent.tab();
44
-
45
- // Assert
46
- expect(await screen.findByRole("textbox")).toHaveFocus();
47
- });
48
-
49
- it("onFocus is called after textfield is focused", async () => {
50
- // Arrange
51
- const handleOnFocus = jest.fn(() => {});
52
-
53
- render(
54
- <TextField
55
- id={"tf-1"}
56
- value="TextIsLongerThan8"
57
- onChange={() => {}}
58
- onFocus={handleOnFocus}
59
- />,
60
- );
61
-
62
- // Act
63
- await userEvent.tab();
64
-
65
- // Assert
66
- expect(handleOnFocus).toHaveBeenCalled();
67
- });
68
-
69
- it("textfield is blurred", async () => {
70
- // Arrange
71
- render(<TextField id="tf-1" value="" onChange={() => {}} />);
72
-
73
- // focus
74
- await userEvent.tab();
75
-
76
- // Act
77
- // blur
78
- await userEvent.tab();
79
-
80
- // Assert
81
- expect(await screen.findByRole("textbox")).not.toHaveFocus();
82
- });
83
-
84
- it("onBlur is called after textfield is blurred", async () => {
85
- // Arrange
86
- const handleOnBlur = jest.fn(() => {});
87
-
88
- render(
89
- <TextField
90
- id={"tf-1"}
91
- value="TextIsLongerThan8"
92
- onChange={() => {}}
93
- onBlur={handleOnBlur}
94
- />,
95
- );
96
-
97
- // focus
98
- await userEvent.tab();
99
-
100
- // Act
101
- // blur
102
- await userEvent.tab();
103
-
104
- // Assert
105
- expect(handleOnBlur).toHaveBeenCalled();
106
- });
107
-
108
- it("id prop is passed to the input element", async () => {
109
- // Arrange
110
- const id = "tf-1";
111
-
112
- // Act
113
- render(<TextField id={id} value="" onChange={() => {}} />);
114
-
115
- // Assert
116
- const input = await screen.findByRole("textbox");
117
- expect(input).toHaveAttribute("id", id);
118
- });
119
-
120
- it("type prop is passed to the input element", async () => {
121
- // Arrange
122
- const type = "number";
123
-
124
- // Act
125
- render(
126
- <TextField id={"tf-1"} type={type} value="" onChange={() => {}} />,
127
- );
128
-
129
- // Assert
130
- // NOTE: The implicit role for input[type=number] is "spinbutton".
131
- const input = await screen.findByRole("spinbutton");
132
- expect(input).toHaveAttribute("type", type);
133
- });
134
-
135
- it("name prop is passed to the input element", async () => {
136
- // Arrange
137
- const name = "some-name";
138
-
139
- // Act
140
- render(
141
- <TextField id={"tf-1"} name={name} value="" onChange={() => {}} />,
142
- );
143
-
144
- // Assert
145
- const input = await screen.findByRole("textbox");
146
- expect(input).toHaveAttribute("name", name);
147
- });
148
-
149
- it("value prop is passed to the input element", async () => {
150
- // Arrange
151
- const value = "Text";
152
-
153
- // Act
154
- render(<TextField id={"tf-1"} value={value} onChange={() => {}} />);
155
-
156
- // Assert
157
- const input = await screen.findByDisplayValue(value);
158
- expect(input).toBeInTheDocument();
159
- });
160
-
161
- it("disabled prop disables the input element", async () => {
162
- // Arrange
163
- render(
164
- <TextField
165
- id="tf-1"
166
- value=""
167
- onChange={() => {}}
168
- disabled={true}
169
- />,
170
- );
171
- const input = await screen.findByRole("textbox");
172
-
173
- // Act
174
-
175
- // Assert
176
- expect(input).toBeDisabled();
177
- });
178
-
179
- it("onChange is called when value changes", async () => {
180
- // Arrange
181
- const handleOnChange = jest.fn();
182
-
183
- render(
184
- <TextField id={"tf-1"} value="Text" onChange={handleOnChange} />,
185
- );
186
-
187
- // Act
188
- const newValue = "Test2";
189
- const input = await screen.findByRole("textbox");
190
- // @see https://testing-library.com/docs/react-testing-library/faq
191
- // How do I test input onChange handlers?
192
- // eslint-disable-next-line testing-library/prefer-user-event
193
- fireEvent.change(input, {target: {value: newValue}});
194
-
195
- // Assert
196
- expect(handleOnChange).toHaveBeenCalledWith(newValue);
197
- });
198
-
199
- it("validate is called when value changes", async () => {
200
- // Arrange
201
- const handleValidate = jest.fn((value: string) => {});
202
-
203
- render(
204
- <TextField
205
- id={"tf-1"}
206
- value="Text"
207
- validate={handleValidate}
208
- onChange={() => {}}
209
- />,
210
- );
211
-
212
- // Act
213
- const newValue = "Text2";
214
- // Select all text and replace it with the new value.
215
- await userEvent.type(
216
- await screen.findByRole("textbox"),
217
- `{selectall}${newValue}`,
218
- );
219
-
220
- // Assert
221
- expect(handleValidate).toHaveBeenCalledWith(newValue);
222
- });
223
-
224
- it("validate is given a valid input", async () => {
225
- // Arrange
226
- const handleValidate = jest.fn(
227
- (value: string): string | null | undefined => {
228
- if (value.length < 8) {
229
- return "Value is too short";
230
- }
231
- },
232
- );
233
-
234
- render(
235
- <TextField
236
- id={"tf-1"}
237
- value="TextIsLong"
238
- validate={handleValidate}
239
- onChange={() => {}}
240
- />,
241
- );
242
-
243
- // Act
244
- const newValue = "TextIsLongerThan8";
245
- // Select all text and replace it with the new value.
246
- await userEvent.type(
247
- await screen.findByRole("textbox"),
248
- `{selectall}${newValue}`,
249
- );
250
-
251
- // Assert
252
- expect(handleValidate).toHaveReturnedWith(undefined);
253
- });
254
-
255
- it("validate is given an invalid input", async () => {
256
- // Arrange
257
- const errorMessage = "Value is too short";
258
- const handleValidate = jest.fn(
259
- (value: string): string | null | undefined => {
260
- if (value.length < 8) {
261
- return errorMessage;
262
- }
263
- },
264
- );
265
-
266
- render(
267
- <TextField
268
- id={"tf-1"}
269
- value="TextIsLongerThan8"
270
- validate={handleValidate}
271
- onChange={() => {}}
272
- />,
273
- );
274
-
275
- // Act
276
- const newValue = "Text";
277
- // Select all text and replace it with the new value.
278
- const textbox = await screen.findByRole("textbox");
279
- await userEvent.click(textbox);
280
- await userEvent.clear(textbox);
281
- await userEvent.paste(newValue);
282
-
283
- // Assert
284
- expect(handleValidate).toHaveReturnedWith(errorMessage);
285
- });
286
-
287
- it("aria-invalid is set true if given an invalid input", async () => {
288
- // Arrange
289
- const handleValidate = jest.fn(
290
- (value: string): string | null | undefined => {
291
- if (value.length < 8) {
292
- return "Value is too short";
293
- }
294
- },
295
- );
296
-
297
- render(
298
- <TextField
299
- id={"tf-1"}
300
- value="short"
301
- validate={handleValidate}
302
- onChange={() => {}}
303
- />,
304
- );
305
-
306
- // Act
307
- const textbox = await screen.findByRole("textbox");
308
-
309
- // Assert
310
- expect(textbox).toHaveAttribute("aria-invalid", "true");
311
- });
312
-
313
- it("aria-invalid is set false if given a valid input", async () => {
314
- // Arrange
315
- const handleValidate = jest.fn(
316
- (value: string): string | null | undefined => {
317
- if (value.length < 8) {
318
- return "Value is too short";
319
- }
320
- },
321
- );
322
-
323
- render(
324
- <TextField
325
- id={"tf-1"}
326
- value="long enough"
327
- validate={handleValidate}
328
- onChange={() => {}}
329
- />,
330
- );
331
-
332
- // Act
333
- const textbox = await screen.findByRole("textbox");
334
-
335
- // Assert
336
- expect(textbox).toHaveAttribute("aria-invalid", "false");
337
- });
338
-
339
- it("onValidate is called after input validate", async () => {
340
- // Arrange
341
- const errorMessage = "Value is too short";
342
- const handleValidate = jest.fn((errorMessage?: string | null) => {});
343
- const validate = jest.fn((value: string): string | null | undefined => {
344
- if (value.length < 8) {
345
- return errorMessage;
346
- }
347
- });
348
-
349
- render(
350
- <TextField
351
- id={"tf-1"}
352
- value="TextIsLongerThan8"
353
- validate={validate}
354
- onValidate={handleValidate}
355
- onChange={() => {}}
356
- />,
357
- );
358
-
359
- // Act
360
- const newValue = "Text";
361
- // Select all text and replace it with the new value.
362
- const textbox = await screen.findByRole("textbox");
363
- await userEvent.click(textbox);
364
- await userEvent.clear(textbox);
365
- await userEvent.paste(newValue);
366
-
367
- // Assert
368
- expect(handleValidate).toHaveBeenCalledWith(errorMessage);
369
- });
370
-
371
- it("onValidate is called on input's initial value", async () => {
372
- // Arrange
373
- const errorMessage = "Value is too short";
374
- const handleValidate = jest.fn((errorMessage?: string | null) => {});
375
- const validate = jest.fn((value: string): string | null | undefined => {
376
- if (value.length < 8) {
377
- return errorMessage;
378
- }
379
- });
380
-
381
- // Act
382
- render(
383
- <TextField
384
- id={"tf-1"}
385
- value="Short"
386
- validate={validate}
387
- onValidate={handleValidate}
388
- onChange={() => {}}
389
- />,
390
- );
391
-
392
- // Assert
393
- expect(handleValidate).toHaveBeenCalledWith(errorMessage);
394
- });
395
-
396
- it("onKeyDown is called after keyboard key press", async () => {
397
- // Arrange
398
- const handleOnKeyDown = jest.fn(
399
- (event: React.KeyboardEvent<HTMLInputElement>) => {
400
- return event.key;
401
- },
402
- );
403
-
404
- render(
405
- <TextField
406
- id={"tf-1"}
407
- value="TextIsLongerThan8"
408
- onChange={() => {}}
409
- onKeyDown={handleOnKeyDown}
410
- />,
411
- );
412
-
413
- // Act
414
- await userEvent.type(await screen.findByRole("textbox"), "{enter}");
415
-
416
- // Assert
417
- expect(handleOnKeyDown).toHaveReturnedWith("Enter");
418
- });
419
-
420
- it("placeholder prop is passed to the input element", async () => {
421
- // Arrange
422
- const placeholder = "Placeholder";
423
-
424
- // Act
425
- render(
426
- <TextField
427
- id={"tf-1"}
428
- value="Text"
429
- placeholder={placeholder}
430
- onChange={() => {}}
431
- />,
432
- );
433
-
434
- // Assert
435
- const input = await screen.findByPlaceholderText(placeholder);
436
- expect(input).toBeInTheDocument();
437
- });
438
-
439
- it("testId is passed to the input element", async () => {
440
- // Arrange
441
- const testId = "some-test-id";
442
- render(
443
- <TextField
444
- id={"tf-1"}
445
- value="Text"
446
- onChange={() => {}}
447
- testId={testId}
448
- />,
449
- );
450
-
451
- // Act
452
-
453
- // Assert
454
- const input = await screen.findByRole("textbox");
455
- expect(input).toHaveAttribute("data-testid", testId);
456
- });
457
-
458
- it("aria props are passed to the input element", async () => {
459
- // Arrange
460
- const ariaLabel = "example-text-field";
461
- render(
462
- <TextField
463
- id={"tf-1"}
464
- value="Text"
465
- onChange={() => {}}
466
- aria-label={ariaLabel}
467
- />,
468
- );
469
-
470
- // Act
471
-
472
- // Assert
473
- const input = await screen.findByRole("textbox");
474
- expect(input).toHaveAttribute("aria-label", ariaLabel);
475
- });
476
-
477
- it("readOnly prop is passed to the input element", async () => {
478
- // Arrange
479
-
480
- // Act
481
- render(
482
- <TextField
483
- id={"tf-1"}
484
- value={"Text"}
485
- onChange={() => {}}
486
- readOnly={true}
487
- />,
488
- );
489
-
490
- // Assert
491
- const input = await screen.findByRole("textbox");
492
- expect(input).toHaveAttribute("readOnly");
493
- });
494
-
495
- it("autoComplete prop is passed to the input element", async () => {
496
- // Arrange
497
- const autoComplete = "name";
498
-
499
- // Act
500
- render(
501
- <TextField
502
- id={"tf-1"}
503
- value={"Text"}
504
- onChange={() => {}}
505
- autoComplete={autoComplete}
506
- />,
507
- );
508
-
509
- // Assert
510
- const input = await screen.findByRole("textbox");
511
- expect(input).toHaveAttribute("autoComplete", autoComplete);
512
- });
513
-
514
- test("has focus if autoFocus is true", async () => {
515
- // Arrange
516
- render(
517
- <View>
518
- <Button onClick={() => {}}>
519
- Some other focusable element.
520
- </Button>
521
- <TextField
522
- id="tf-auto-focus-true"
523
- autoFocus
524
- testId="search-field-test"
525
- onChange={() => {}}
526
- value=""
527
- />
528
- ,
529
- </View>,
530
- );
531
-
532
- // Act
533
- const searchField = await screen.findByTestId("search-field-test");
534
-
535
- // Assert
536
- expect(searchField).toHaveFocus();
537
- });
538
-
539
- test("does not have focus if autoFocus is undefined", async () => {
540
- // Arrange
541
- render(
542
- <View>
543
- <Button onClick={() => {}}>
544
- Some other focusable element.
545
- </Button>
546
- <TextField
547
- id="tf-auto-focus-undefined"
548
- testId="search-field-test"
549
- onChange={() => {}}
550
- value=""
551
- />
552
- ,
553
- </View>,
554
- );
555
-
556
- // Act
557
- const searchField = await screen.findByTestId("search-field-test");
558
-
559
- // Assert
560
- expect(searchField).not.toHaveFocus();
561
- });
562
- });