@khanacademy/wonder-blocks-form 3.1.5 → 3.1.7

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.
@@ -1,54 +1,37 @@
1
1
  //@flow
2
2
  import * as React from "react";
3
- import {mount} from "enzyme";
4
- import "jest-enzyme";
5
- import {render, screen} from "@testing-library/react";
3
+ import {render, screen, fireEvent} from "@testing-library/react";
6
4
  import userEvent from "@testing-library/user-event";
7
5
 
8
6
  import {StyleSheet} from "aphrodite";
9
7
  import LabeledTextField from "../labeled-text-field.js";
10
8
 
11
- const wait = (delay: number = 0) =>
12
- new Promise((resolve, reject) => {
13
- // eslint-disable-next-line no-restricted-syntax
14
- return setTimeout(resolve, delay);
15
- });
16
-
17
9
  describe("LabeledTextField", () => {
18
10
  it("labeledtextfield becomes focused", () => {
19
11
  // Arrange
20
- const wrapper = mount(
21
- <LabeledTextField label="Label" value="" onChange={() => {}} />,
22
- );
23
- const field = wrapper.find("TextFieldInternal");
12
+ render(<LabeledTextField label="Label" value="" onChange={() => {}} />);
13
+ const field = screen.getByRole("textbox");
24
14
 
25
15
  // Act
26
- field.simulate("focus");
16
+ userEvent.tab();
27
17
 
28
18
  // Assert
29
- expect(wrapper.find("LabeledTextFieldInternal")).toHaveState(
30
- "focused",
31
- true,
32
- );
19
+ expect(field).toHaveFocus();
33
20
  });
34
21
 
35
22
  it("labeledtextfield becomes blurred", async () => {
36
23
  // Arrange
37
- const wrapper = mount(
38
- <LabeledTextField label="Label" value="" onChange={() => {}} />,
39
- );
40
- const field = wrapper.find("TextFieldInternal");
24
+ render(<LabeledTextField label="Label" value="" onChange={() => {}} />);
25
+
26
+ // focus
27
+ userEvent.tab();
41
28
 
42
29
  // Act
43
- field.simulate("focus");
44
- await wait(0);
45
- field.simulate("blur");
30
+ // blur
31
+ userEvent.tab();
46
32
 
47
33
  // Assert
48
- expect(wrapper.find("LabeledTextFieldInternal")).toHaveState(
49
- "focused",
50
- false,
51
- );
34
+ expect(screen.getByRole("textbox")).not.toHaveFocus();
52
35
  });
53
36
 
54
37
  it("id prop is passed to input", () => {
@@ -56,7 +39,7 @@ describe("LabeledTextField", () => {
56
39
  const id = "exampleid";
57
40
 
58
41
  // Act
59
- const wrapper = mount(
42
+ render(
60
43
  <LabeledTextField
61
44
  id={id}
62
45
  label="Label"
@@ -67,23 +50,21 @@ describe("LabeledTextField", () => {
67
50
  );
68
51
 
69
52
  // Assert
70
- const input = wrapper.find("input");
71
- expect(input).toContainMatchingElement(`[id="${id}-field"]`);
53
+ const input = screen.getByRole("textbox");
54
+ expect(input).toHaveAttribute("id", `${id}-field`);
72
55
  });
73
56
 
74
57
  it("auto-generated id is passed to input when id prop is not set", () => {
75
58
  // Arrange
76
59
 
77
60
  // Act
78
- const wrapper = mount(
79
- <LabeledTextField label="Label" value="" onChange={() => {}} />,
80
- );
61
+ render(<LabeledTextField label="Label" value="" onChange={() => {}} />);
81
62
 
82
63
  // Assert
83
64
  // Since the generated id is unique, we cannot know what it will be.
84
65
  // We only test if the id attribute starts with "uid-" and ends with "-field".
85
- const input = wrapper.find("input");
86
- expect(input.props()["id"]).toMatch(/uid-.*-field/);
66
+ const input = screen.getByRole("textbox");
67
+ expect(input.getAttribute("id")).toMatch(/uid-.*-field/);
87
68
  });
88
69
 
89
70
  it("type prop is passed to input", () => {
@@ -91,7 +72,7 @@ describe("LabeledTextField", () => {
91
72
  const type = "email";
92
73
 
93
74
  // Act
94
- const wrapper = mount(
75
+ render(
95
76
  <LabeledTextField
96
77
  type={type}
97
78
  label="Label"
@@ -101,8 +82,8 @@ describe("LabeledTextField", () => {
101
82
  );
102
83
 
103
84
  // Assert
104
- const input = wrapper.find("input");
105
- expect(input).toContainMatchingElement(`[type="${type}"]`);
85
+ const input = screen.getByRole("textbox");
86
+ expect(input).toHaveAttribute("type", type);
106
87
  });
107
88
 
108
89
  it("label prop is rendered", () => {
@@ -110,12 +91,10 @@ describe("LabeledTextField", () => {
110
91
  const label = "Label";
111
92
 
112
93
  // Act
113
- const wrapper = mount(
114
- <LabeledTextField label={label} value="" onChange={() => {}} />,
115
- );
94
+ render(<LabeledTextField label={label} value="" onChange={() => {}} />);
116
95
 
117
96
  // Assert
118
- expect(wrapper).toIncludeText(label);
97
+ expect(screen.getByText(label)).toBeInTheDocument();
119
98
  });
120
99
 
121
100
  it("description prop is rendered", () => {
@@ -123,7 +102,7 @@ describe("LabeledTextField", () => {
123
102
  const description = "Description";
124
103
 
125
104
  // Act
126
- const wrapper = mount(
105
+ render(
127
106
  <LabeledTextField
128
107
  label="Label"
129
108
  description={description}
@@ -133,7 +112,7 @@ describe("LabeledTextField", () => {
133
112
  );
134
113
 
135
114
  // Assert
136
- expect(wrapper).toIncludeText(description);
115
+ expect(screen.getByText(description)).toBeInTheDocument();
137
116
  });
138
117
 
139
118
  it("value prop is set on mount", () => {
@@ -141,7 +120,7 @@ describe("LabeledTextField", () => {
141
120
  const value = "Value";
142
121
 
143
122
  // Act
144
- const wrapper = mount(
123
+ render(
145
124
  <LabeledTextField
146
125
  label="Label"
147
126
  value={value}
@@ -150,32 +129,38 @@ describe("LabeledTextField", () => {
150
129
  );
151
130
 
152
131
  // Assert
153
- const input = wrapper.find("input");
154
- expect(input).toHaveValue(value);
132
+ const input = screen.getByRole("textbox");
133
+ expect(input).toHaveAttribute("value", value);
155
134
  });
156
135
 
157
136
  it("value prop change from parent reflects on input value", async () => {
158
137
  // Arrange
159
138
  const handleChange = jest.fn((newValue: string) => {});
160
139
 
161
- const wrapper = mount(
140
+ const {rerender} = render(
162
141
  <LabeledTextField label="Label" value="" onChange={handleChange} />,
163
142
  );
164
143
 
165
144
  // Act
166
145
  const newValue = "new value";
167
- wrapper.setProps({value: newValue});
146
+ rerender(
147
+ <LabeledTextField
148
+ label="Label"
149
+ value={newValue}
150
+ onChange={handleChange}
151
+ />,
152
+ );
168
153
 
169
154
  // Assert
170
- const input = wrapper.find("input");
171
- expect(input).toHaveValue(newValue);
155
+ const input = screen.getByRole("textbox");
156
+ expect(input).toHaveAttribute("value", newValue);
172
157
  });
173
158
 
174
159
  it("disabled prop disables the input", () => {
175
160
  // Arrange
176
161
 
177
162
  // Act
178
- const wrapper = mount(
163
+ render(
179
164
  <LabeledTextField
180
165
  label="Label"
181
166
  value=""
@@ -185,7 +170,7 @@ describe("LabeledTextField", () => {
185
170
  );
186
171
 
187
172
  // Assert
188
- const input = wrapper.find("input");
173
+ const input = screen.getByRole("textbox");
189
174
  expect(input).toBeDisabled();
190
175
  });
191
176
 
@@ -235,7 +220,7 @@ describe("LabeledTextField", () => {
235
220
  it("validate prop is called when input changes", () => {
236
221
  // Arrange
237
222
  const validate = jest.fn((value: string): ?string => {});
238
- const wrapper = mount(
223
+ render(
239
224
  <LabeledTextField
240
225
  label="Label"
241
226
  value=""
@@ -246,8 +231,11 @@ describe("LabeledTextField", () => {
246
231
 
247
232
  // Act
248
233
  const newValue = "New Value";
249
- const input = wrapper.find("input");
250
- input.simulate("change", {target: {value: newValue}});
234
+ const input = screen.getByRole("textbox");
235
+ // @see https://testing-library.com/docs/react-testing-library/faq
236
+ // How do I test input onChange handlers?
237
+ // eslint-disable-next-line testing-library/prefer-user-event
238
+ fireEvent.change(input, {target: {value: newValue}});
251
239
 
252
240
  // Assert
253
241
  expect(validate).toHaveBeenCalledWith(newValue);
@@ -264,7 +252,7 @@ describe("LabeledTextField", () => {
264
252
  }
265
253
  };
266
254
 
267
- const wrapper = mount(
255
+ render(
268
256
  <LabeledTextField
269
257
  label="Label"
270
258
  value="LongerThan8Chars"
@@ -275,8 +263,8 @@ describe("LabeledTextField", () => {
275
263
  );
276
264
 
277
265
  // Act
278
- const input = wrapper.find("input");
279
- input.simulate("change", {target: {value: "Short"}});
266
+ // Select all text and replace it with the new value.
267
+ userEvent.type(screen.getByRole("textbox"), `{selectall}Short`);
280
268
 
281
269
  // Assert
282
270
  expect(handleValidate).toHaveBeenCalledWith(errorMessage);
@@ -286,14 +274,17 @@ describe("LabeledTextField", () => {
286
274
  // Arrange
287
275
  const handleChange = jest.fn((newValue: string) => {});
288
276
 
289
- const wrapper = mount(
277
+ render(
290
278
  <LabeledTextField label="Label" value="" onChange={handleChange} />,
291
279
  );
292
280
 
293
281
  // Act
294
282
  const newValue = "new value";
295
- const input = wrapper.find("input");
296
- input.simulate("change", {target: {value: newValue}});
283
+ const input = screen.getByRole("textbox");
284
+ // @see https://testing-library.com/docs/react-testing-library/faq
285
+ // How do I test input onChange handlers?
286
+ // eslint-disable-next-line testing-library/prefer-user-event
287
+ fireEvent.change(input, {target: {value: newValue}});
297
288
 
298
289
  // Assert
299
290
  expect(handleChange).toHaveBeenCalledWith(newValue);
@@ -307,7 +298,7 @@ describe("LabeledTextField", () => {
307
298
  },
308
299
  );
309
300
 
310
- const wrapper = mount(
301
+ render(
311
302
  <LabeledTextField
312
303
  label="Label"
313
304
  value=""
@@ -317,18 +308,16 @@ describe("LabeledTextField", () => {
317
308
  );
318
309
 
319
310
  // Act
320
- const key = "Enter";
321
- const input = wrapper.find("input");
322
- input.simulate("keyDown", {key: key});
311
+ userEvent.type(screen.getByRole("textbox"), "{enter}");
323
312
 
324
313
  // Assert
325
- expect(handleKeyDown).toHaveReturnedWith(key);
314
+ expect(handleKeyDown).toHaveReturnedWith("Enter");
326
315
  });
327
316
 
328
317
  it("onFocus prop is called when field is focused", () => {
329
318
  // Arrange
330
319
  const handleFocus = jest.fn(() => {});
331
- const wrapper = mount(
320
+ render(
332
321
  <LabeledTextField
333
322
  label="Label"
334
323
  value=""
@@ -338,8 +327,8 @@ describe("LabeledTextField", () => {
338
327
  );
339
328
 
340
329
  // Act
341
- const field = wrapper.find("TextFieldInternal");
342
- field.simulate("focus");
330
+ const field = screen.getByRole("textbox");
331
+ field.focus();
343
332
 
344
333
  // Assert
345
334
  expect(handleFocus).toHaveBeenCalled();
@@ -348,7 +337,7 @@ describe("LabeledTextField", () => {
348
337
  it("onBlur prop is called when field is blurred", async () => {
349
338
  // Arrange
350
339
  const handleBlur = jest.fn(() => {});
351
- const wrapper = mount(
340
+ render(
352
341
  <LabeledTextField
353
342
  label="Label"
354
343
  value=""
@@ -357,11 +346,12 @@ describe("LabeledTextField", () => {
357
346
  />,
358
347
  );
359
348
 
349
+ // focus
350
+ userEvent.tab();
351
+
360
352
  // Act
361
- const field = wrapper.find("TextFieldInternal");
362
- field.simulate("focus");
363
- await wait(0);
364
- field.simulate("blur");
353
+ // blur
354
+ userEvent.tab();
365
355
 
366
356
  // Assert
367
357
  expect(handleBlur).toHaveBeenCalled();
@@ -372,7 +362,7 @@ describe("LabeledTextField", () => {
372
362
  const placeholder = "Placeholder";
373
363
 
374
364
  // Act
375
- const wrapper = mount(
365
+ render(
376
366
  <LabeledTextField
377
367
  label="Label"
378
368
  value=""
@@ -382,17 +372,15 @@ describe("LabeledTextField", () => {
382
372
  );
383
373
 
384
374
  // Assert
385
- const input = wrapper.find("input");
386
- expect(input).toContainMatchingElement(
387
- `[placeholder="${placeholder}"]`,
388
- );
375
+ const input = screen.getByPlaceholderText(placeholder);
376
+ expect(input).toBeInTheDocument();
389
377
  });
390
378
 
391
379
  it("light prop is passed to textfield", async () => {
392
380
  // Arrange
393
381
 
394
382
  // Act
395
- const wrapper = mount(
383
+ render(
396
384
  <LabeledTextField
397
385
  label="Label"
398
386
  value=""
@@ -401,9 +389,11 @@ describe("LabeledTextField", () => {
401
389
  />,
402
390
  );
403
391
 
392
+ const textField = screen.getByRole("textbox");
393
+ textField.focus();
394
+
404
395
  // Assert
405
- const textField = wrapper.find("TextFieldInternal");
406
- expect(textField).toHaveProp("light", true);
396
+ expect(textField.getAttribute("class")).toMatch(/light/i);
407
397
  });
408
398
 
409
399
  it("style prop is passed to fieldheading", async () => {
@@ -416,7 +406,7 @@ describe("LabeledTextField", () => {
416
406
  });
417
407
 
418
408
  // Act
419
- const wrapper = mount(
409
+ const {container} = render(
420
410
  <LabeledTextField
421
411
  label="Label"
422
412
  value=""
@@ -426,8 +416,8 @@ describe("LabeledTextField", () => {
426
416
  );
427
417
 
428
418
  // Assert
429
- const fieldHeading = wrapper.find("FieldHeading");
430
- expect(fieldHeading).toHaveStyle(styles.style1);
419
+ const fieldHeading = container.childNodes[0];
420
+ expect(fieldHeading).toHaveStyle("min-width: 250px");
431
421
  });
432
422
 
433
423
  it("testId prop is passed to textfield", async () => {
@@ -435,7 +425,7 @@ describe("LabeledTextField", () => {
435
425
  const testId = "example-testid";
436
426
 
437
427
  // Act
438
- const wrapper = mount(
428
+ render(
439
429
  <LabeledTextField
440
430
  label="Label"
441
431
  value=""
@@ -445,15 +435,15 @@ describe("LabeledTextField", () => {
445
435
  );
446
436
 
447
437
  // Assert
448
- const textField = wrapper.find(`[data-test-id="${testId}-field"]`);
449
- expect(textField).toExist();
438
+ const input = screen.getByRole("textbox");
439
+ expect(input).toHaveAttribute("data-test-id", `${testId}-field`);
450
440
  });
451
441
 
452
442
  it("readOnly prop is passed to textfield", async () => {
453
443
  // Arrange
454
444
 
455
445
  // Act
456
- const wrapper = mount(
446
+ render(
457
447
  <LabeledTextField
458
448
  label="Label"
459
449
  value=""
@@ -463,8 +453,8 @@ describe("LabeledTextField", () => {
463
453
  );
464
454
 
465
455
  // Assert
466
- const textField = wrapper.find("TextFieldInternal");
467
- expect(textField).toHaveProp("readOnly", true);
456
+ const input = screen.getByRole("textbox");
457
+ expect(input).toHaveAttribute("readOnly");
468
458
  });
469
459
 
470
460
  it("autoComplete prop is passed to textfield", async () => {
@@ -472,7 +462,7 @@ describe("LabeledTextField", () => {
472
462
  const autoComplete = "name";
473
463
 
474
464
  // Act
475
- const wrapper = mount(
465
+ render(
476
466
  <LabeledTextField
477
467
  label="Label"
478
468
  value=""
@@ -482,8 +472,8 @@ describe("LabeledTextField", () => {
482
472
  );
483
473
 
484
474
  // Assert
485
- const textField = wrapper.find("TextFieldInternal");
486
- expect(textField).toHaveProp("autoComplete", autoComplete);
475
+ const input = screen.getByRole("textbox");
476
+ expect(input).toHaveAttribute("autoComplete", autoComplete);
487
477
  });
488
478
  });
489
479