@khanacademy/wonder-blocks-button 2.9.13

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.
@@ -0,0 +1,826 @@
1
+ // @flow
2
+ import * as React from "react";
3
+ import {MemoryRouter, Route, Switch} from "react-router-dom";
4
+ import {mount} from "enzyme";
5
+
6
+ import Button from "../button.js";
7
+
8
+ const wait = (delay: number = 0) =>
9
+ new Promise((resolve, reject) => {
10
+ // eslint-disable-next-line no-restricted-syntax
11
+ return setTimeout(resolve, delay);
12
+ });
13
+
14
+ const keyCodes = {
15
+ tab: 9,
16
+ enter: 13,
17
+ space: 32,
18
+ };
19
+
20
+ describe("Button", () => {
21
+ test("client-side navigation", () => {
22
+ // Arrange
23
+ const wrapper = mount(
24
+ <MemoryRouter>
25
+ <div>
26
+ <Button href="/foo">Click me!</Button>
27
+ <Switch>
28
+ <Route path="/foo">
29
+ <div id="foo">Hello, world!</div>
30
+ </Route>
31
+ </Switch>
32
+ </div>
33
+ </MemoryRouter>,
34
+ );
35
+
36
+ // Act
37
+ const buttonWrapper = wrapper.find("Button");
38
+ buttonWrapper.simulate("click", {button: 0});
39
+
40
+ // Assert
41
+ expect(wrapper.find("#foo")).toExist();
42
+ });
43
+
44
+ test("beforeNav rejection blocks client-side navigation", async () => {
45
+ // Arrange
46
+ const wrapper = mount(
47
+ <MemoryRouter>
48
+ <div>
49
+ <Button href="/foo" beforeNav={(e) => Promise.reject()}>
50
+ Click me!
51
+ </Button>
52
+ <Switch>
53
+ <Route path="/foo">
54
+ <div id="foo">Hello, world!</div>
55
+ </Route>
56
+ </Switch>
57
+ </div>
58
+ </MemoryRouter>,
59
+ );
60
+
61
+ // Act
62
+ const buttonWrapper = wrapper.find("Button");
63
+ buttonWrapper.simulate("click", {button: 0});
64
+ await wait(0);
65
+ buttonWrapper.update();
66
+
67
+ // Assert
68
+ expect(wrapper.find("#foo")).not.toExist();
69
+ });
70
+
71
+ test("beforeNav rejection blocks calling safeWithNav", async () => {
72
+ // Arrange
73
+ const safeWithNavMock = jest.fn();
74
+ const wrapper = mount(
75
+ <MemoryRouter>
76
+ <div>
77
+ <Button
78
+ href="/foo"
79
+ beforeNav={(e) => Promise.reject()}
80
+ safeWithNav={safeWithNavMock}
81
+ >
82
+ Click me!
83
+ </Button>
84
+ <Switch>
85
+ <Route path="/foo">
86
+ <div id="foo">Hello, world!</div>
87
+ </Route>
88
+ </Switch>
89
+ </div>
90
+ </MemoryRouter>,
91
+ );
92
+
93
+ // Act
94
+ const buttonWrapper = wrapper.find("Button");
95
+ buttonWrapper.simulate("click", {button: 0});
96
+ await wait(0);
97
+ buttonWrapper.update();
98
+
99
+ // Assert
100
+ expect(safeWithNavMock).not.toHaveBeenCalled();
101
+ });
102
+
103
+ test("beforeNav resolution results in client-side navigation", async () => {
104
+ // Arrange
105
+ const wrapper = mount(
106
+ <MemoryRouter>
107
+ <div>
108
+ <Button href="/foo" beforeNav={(e) => Promise.resolve()}>
109
+ Click me!
110
+ </Button>
111
+ <Switch>
112
+ <Route path="/foo">
113
+ <div id="foo">Hello, world!</div>
114
+ </Route>
115
+ </Switch>
116
+ </div>
117
+ </MemoryRouter>,
118
+ );
119
+
120
+ // Act
121
+ const buttonWrapper = wrapper.find("Button");
122
+ buttonWrapper.simulate("click", {button: 0});
123
+ await wait(0);
124
+ buttonWrapper.update();
125
+
126
+ // Assert
127
+ expect(wrapper.find("#foo")).toExist();
128
+ });
129
+
130
+ test("beforeNav resolution results in safeWithNav being called", async () => {
131
+ // Arrange
132
+ const safeWithNavMock = jest.fn();
133
+ const wrapper = mount(
134
+ <MemoryRouter>
135
+ <div>
136
+ <Button
137
+ href="/foo"
138
+ beforeNav={(e) => Promise.resolve()}
139
+ safeWithNav={safeWithNavMock}
140
+ >
141
+ Click me!
142
+ </Button>
143
+ <Switch>
144
+ <Route path="/foo">
145
+ <div id="foo">Hello, world!</div>
146
+ </Route>
147
+ </Switch>
148
+ </div>
149
+ </MemoryRouter>,
150
+ );
151
+
152
+ // Act
153
+ const buttonWrapper = wrapper.find("Button");
154
+ buttonWrapper.simulate("click", {button: 0});
155
+ await wait(0);
156
+ buttonWrapper.update();
157
+
158
+ // Assert
159
+ expect(safeWithNavMock).toHaveBeenCalled();
160
+ });
161
+
162
+ test("show circular spinner before beforeNav resolves", async () => {
163
+ // Arrange
164
+ const wrapper = mount(
165
+ <MemoryRouter>
166
+ <div>
167
+ <Button href="/foo" beforeNav={(e) => Promise.resolve()}>
168
+ Click me!
169
+ </Button>
170
+ <Switch>
171
+ <Route path="/foo">
172
+ <div id="foo">Hello, world!</div>
173
+ </Route>
174
+ </Switch>
175
+ </div>
176
+ </MemoryRouter>,
177
+ );
178
+
179
+ // Act
180
+ const buttonWrapper = wrapper.find("Button");
181
+ buttonWrapper.simulate("click", {button: 0});
182
+
183
+ // Assert
184
+ // We want the button to look exactly the same as if someone had passed
185
+ // `spinner={true}` as a prop.
186
+ expect(wrapper.find("ButtonCore")).toHaveProp({spinner: true});
187
+ expect(wrapper.find("CircularSpinner")).toExist();
188
+ });
189
+
190
+ test("safeWithNav with skipClientNav=true waits for promise resolution", async () => {
191
+ // Arrange
192
+ jest.spyOn(window.location, "assign");
193
+ const wrapper = mount(
194
+ <MemoryRouter>
195
+ <div>
196
+ <Button
197
+ href="/foo"
198
+ safeWithNav={(e) => Promise.resolve()}
199
+ skipClientNav={true}
200
+ >
201
+ Click me!
202
+ </Button>
203
+ <Switch>
204
+ <Route path="/foo">
205
+ <div id="foo">Hello, world!</div>
206
+ </Route>
207
+ </Switch>
208
+ </div>
209
+ </MemoryRouter>,
210
+ );
211
+
212
+ // Act
213
+ const buttonWrapper = wrapper.find("Button");
214
+ buttonWrapper.simulate("click", {button: 0});
215
+ await wait(0);
216
+ buttonWrapper.update();
217
+
218
+ // Assert
219
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
220
+ });
221
+
222
+ test("safeWithNav with skipClientNav=true shows spinner", async () => {
223
+ // Arrange
224
+ jest.spyOn(window.location, "assign");
225
+ const wrapper = mount(
226
+ <MemoryRouter>
227
+ <div>
228
+ <Button
229
+ href="/foo"
230
+ safeWithNav={(e) => Promise.resolve()}
231
+ skipClientNav={true}
232
+ >
233
+ Click me!
234
+ </Button>
235
+ <Switch>
236
+ <Route path="/foo">
237
+ <div id="foo">Hello, world!</div>
238
+ </Route>
239
+ </Switch>
240
+ </div>
241
+ </MemoryRouter>,
242
+ );
243
+
244
+ // Act
245
+ const buttonWrapper = wrapper.find("Button");
246
+ buttonWrapper.simulate("click", {button: 0});
247
+
248
+ // Assert
249
+ expect(wrapper.find("CircularSpinner")).toExist();
250
+ });
251
+
252
+ test("beforeNav resolution and safeWithNav with skipClientNav=true waits for promise resolution", async () => {
253
+ // Arrange
254
+ jest.spyOn(window.location, "assign");
255
+ const wrapper = mount(
256
+ <MemoryRouter>
257
+ <div>
258
+ <Button
259
+ href="/foo"
260
+ beforeNav={(e) => Promise.resolve()}
261
+ safeWithNav={(e) => Promise.resolve()}
262
+ skipClientNav={true}
263
+ >
264
+ Click me!
265
+ </Button>
266
+ <Switch>
267
+ <Route path="/foo">
268
+ <div id="foo">Hello, world!</div>
269
+ </Route>
270
+ </Switch>
271
+ </div>
272
+ </MemoryRouter>,
273
+ );
274
+
275
+ // Act
276
+ const buttonWrapper = wrapper.find("Button");
277
+ buttonWrapper.simulate("click", {button: 0});
278
+ await wait(0);
279
+ buttonWrapper.update();
280
+ await wait(0);
281
+ buttonWrapper.update();
282
+
283
+ // Assert
284
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
285
+ });
286
+
287
+ test("safeWithNav with skipClientNav=true waits for promise rejection", async () => {
288
+ // Arrange
289
+ jest.spyOn(window.location, "assign");
290
+ const wrapper = mount(
291
+ <MemoryRouter>
292
+ <div>
293
+ <Button
294
+ href="/foo"
295
+ safeWithNav={(e) => Promise.reject()}
296
+ skipClientNav={true}
297
+ >
298
+ Click me!
299
+ </Button>
300
+ <Switch>
301
+ <Route path="/foo">
302
+ <div id="foo">Hello, world!</div>
303
+ </Route>
304
+ </Switch>
305
+ </div>
306
+ </MemoryRouter>,
307
+ );
308
+
309
+ // Act
310
+ const buttonWrapper = wrapper.find("Button");
311
+ buttonWrapper.simulate("click", {button: 0});
312
+ await wait(0);
313
+ buttonWrapper.update();
314
+
315
+ // Assert
316
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
317
+ });
318
+
319
+ test("safeWithNav with skipClientNav=false calls safeWithNav but doesn't wait to navigate", async () => {
320
+ // Arrange
321
+ jest.spyOn(window.location, "assign");
322
+ const safeWithNavMock = jest.fn();
323
+ const wrapper = mount(
324
+ <MemoryRouter>
325
+ <div>
326
+ <Button
327
+ href="/foo"
328
+ safeWithNav={safeWithNavMock}
329
+ skipClientNav={false}
330
+ >
331
+ Click me!
332
+ </Button>
333
+ <Switch>
334
+ <Route path="/foo">
335
+ <div id="foo">Hello, world!</div>
336
+ </Route>
337
+ </Switch>
338
+ </div>
339
+ </MemoryRouter>,
340
+ );
341
+
342
+ // Act
343
+ const buttonWrapper = wrapper.find("Button");
344
+ buttonWrapper.simulate("click", {button: 0});
345
+
346
+ // Assert
347
+ expect(safeWithNavMock).toHaveBeenCalled();
348
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
349
+ });
350
+
351
+ test("safeWithNav with beforeNav resolution and skipClientNav=false calls safeWithNav but doesn't wait to navigate", async () => {
352
+ // Arrange
353
+ jest.spyOn(window.location, "assign");
354
+ const safeWithNavMock = jest.fn();
355
+ const wrapper = mount(
356
+ <MemoryRouter>
357
+ <div>
358
+ <Button
359
+ href="/foo"
360
+ beforeNav={() => Promise.resolve()}
361
+ safeWithNav={safeWithNavMock}
362
+ skipClientNav={false}
363
+ >
364
+ Click me!
365
+ </Button>
366
+ <Switch>
367
+ <Route path="/foo">
368
+ <div id="foo">Hello, world!</div>
369
+ </Route>
370
+ </Switch>
371
+ </div>
372
+ </MemoryRouter>,
373
+ );
374
+
375
+ // Act
376
+ const buttonWrapper = wrapper.find("Button");
377
+ buttonWrapper.simulate("click", {button: 0});
378
+ await wait(0);
379
+ buttonWrapper.update();
380
+
381
+ // Assert
382
+ expect(safeWithNavMock).toHaveBeenCalled();
383
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
384
+ });
385
+
386
+ test("client-side navigation with unknown URL fails", () => {
387
+ // Arrange
388
+ const wrapper = mount(
389
+ <MemoryRouter>
390
+ <div>
391
+ <Button href="/unknown">Click me!</Button>
392
+ <Switch>
393
+ <Route path="/foo">
394
+ <div id="foo">Hello, world!</div>
395
+ </Route>
396
+ </Switch>
397
+ </div>
398
+ </MemoryRouter>,
399
+ );
400
+
401
+ // Act
402
+ const buttonWrapper = wrapper.find("Button");
403
+ buttonWrapper.simulate("click", {button: 0});
404
+
405
+ // Assert
406
+ expect(wrapper.find("#foo")).not.toExist();
407
+ });
408
+
409
+ test("client-side navigation with `skipClientNav` set to `true` fails", () => {
410
+ // Arrange
411
+ const wrapper = mount(
412
+ <MemoryRouter>
413
+ <div>
414
+ <Button href="/foo" skipClientNav>
415
+ Click me!
416
+ </Button>
417
+ <Switch>
418
+ <Route path="/foo">
419
+ <div id="foo">Hello, world!</div>
420
+ </Route>
421
+ </Switch>
422
+ </div>
423
+ </MemoryRouter>,
424
+ );
425
+
426
+ // Act
427
+ const buttonWrapper = wrapper.find("Button");
428
+ buttonWrapper.simulate("click", {button: 0});
429
+
430
+ // Assert
431
+ expect(wrapper.find("#foo")).not.toExist();
432
+ });
433
+
434
+ test("disallow navigation when href and disabled are both set", () => {
435
+ // Arrange
436
+ const wrapper = mount(
437
+ <MemoryRouter>
438
+ <div>
439
+ <Button href="/foo" disabled={true}>
440
+ Click me!
441
+ </Button>
442
+ <Switch>
443
+ <Route path="/foo">
444
+ <div id="foo">Hello, world!</div>
445
+ </Route>
446
+ </Switch>
447
+ </div>
448
+ </MemoryRouter>,
449
+ );
450
+
451
+ // Act
452
+ const buttonWrapper = wrapper.find("Button");
453
+ buttonWrapper.simulate("click", {button: 0});
454
+
455
+ // Assert
456
+ expect(wrapper.find("#foo")).not.toExist();
457
+ });
458
+
459
+ test("don't call beforeNav when href and disabled are both set", () => {
460
+ // Arrange
461
+ const beforeNavMock = jest.fn();
462
+ const wrapper = mount(
463
+ <MemoryRouter>
464
+ <div>
465
+ <Button
466
+ href="/foo"
467
+ disabled={true}
468
+ beforeNav={beforeNavMock}
469
+ >
470
+ Click me!
471
+ </Button>
472
+ <Switch>
473
+ <Route path="/foo">
474
+ <div id="foo">Hello, world!</div>
475
+ </Route>
476
+ </Switch>
477
+ </div>
478
+ </MemoryRouter>,
479
+ );
480
+
481
+ // Act
482
+ const buttonWrapper = wrapper.find("Button");
483
+ buttonWrapper.simulate("click", {button: 0});
484
+
485
+ // Assert
486
+ expect(beforeNavMock).not.toHaveBeenCalled();
487
+ });
488
+
489
+ test("don't call safeWithNav when href and disabled are both set", () => {
490
+ // Arrange
491
+ const safeWithNavMock = jest.fn();
492
+ const wrapper = mount(
493
+ <MemoryRouter>
494
+ <div>
495
+ <Button
496
+ href="/foo"
497
+ disabled={true}
498
+ safeWithNav={safeWithNavMock}
499
+ >
500
+ Click me!
501
+ </Button>
502
+ <Switch>
503
+ <Route path="/foo">
504
+ <div id="foo">Hello, world!</div>
505
+ </Route>
506
+ </Switch>
507
+ </div>
508
+ </MemoryRouter>,
509
+ );
510
+
511
+ // Act
512
+ const buttonWrapper = wrapper.find("Button");
513
+ buttonWrapper.simulate("click", {button: 0});
514
+
515
+ // Assert
516
+ expect(safeWithNavMock).not.toHaveBeenCalled();
517
+ });
518
+
519
+ it("should set label on the underlying button", () => {
520
+ // Arrange
521
+ const wrapper = mount(
522
+ <Button id="foo" onClick={() => {}}>
523
+ Click me!
524
+ </Button>,
525
+ );
526
+
527
+ expect(wrapper.find("button")).toHaveProp({id: "foo"});
528
+ });
529
+
530
+ it("should set label on the underlying link", () => {
531
+ // Arrange
532
+ const wrapper = mount(
533
+ <Button id="foo" href="/bar">
534
+ Click me!
535
+ </Button>,
536
+ );
537
+
538
+ expect(wrapper.find("a")).toHaveProp({id: "foo"});
539
+ });
540
+
541
+ describe("client-side navigation with keyboard", () => {
542
+ it("should navigate on pressing the space key", () => {
543
+ // Arrange
544
+ const wrapper = mount(
545
+ <MemoryRouter>
546
+ <div>
547
+ <Button href="/foo">Click me!</Button>
548
+ <Switch>
549
+ <Route path="/foo">
550
+ <div id="foo">Hello, world!</div>
551
+ </Route>
552
+ </Switch>
553
+ </div>
554
+ </MemoryRouter>,
555
+ );
556
+
557
+ // Act
558
+ const buttonWrapper = wrapper.find("Button");
559
+ buttonWrapper.simulate("keydown", {
560
+ keyCode: keyCodes.space,
561
+ });
562
+ buttonWrapper.simulate("keyup", {
563
+ keyCode: keyCodes.space,
564
+ });
565
+
566
+ // Assert
567
+ expect(wrapper.find("#foo")).toExist();
568
+ });
569
+
570
+ it("should navigate on pressing the enter key", () => {
571
+ // Arrange
572
+ const wrapper = mount(
573
+ <MemoryRouter>
574
+ <div>
575
+ <Button href="/foo">Click me!</Button>
576
+ <Switch>
577
+ <Route path="/foo">
578
+ <div id="foo">Hello, world!</div>
579
+ </Route>
580
+ </Switch>
581
+ </div>
582
+ </MemoryRouter>,
583
+ );
584
+
585
+ // Act
586
+ const buttonWrapper = wrapper.find("Button");
587
+ buttonWrapper.simulate("keydown", {
588
+ keyCode: keyCodes.enter,
589
+ });
590
+ buttonWrapper.simulate("keyup", {
591
+ keyCode: keyCodes.enter,
592
+ });
593
+
594
+ // Assert
595
+ expect(wrapper.find("#foo")).toExist();
596
+ });
597
+
598
+ test("beforeNav rejection blocks client-side navigation ", async () => {
599
+ // Arrange
600
+ const wrapper = mount(
601
+ <MemoryRouter>
602
+ <div>
603
+ <Button href="/foo" beforeNav={(e) => Promise.reject()}>
604
+ Click me!
605
+ </Button>
606
+ <Switch>
607
+ <Route path="/foo">
608
+ <div id="foo">Hello, world!</div>
609
+ </Route>
610
+ </Switch>
611
+ </div>
612
+ </MemoryRouter>,
613
+ );
614
+
615
+ // Act
616
+ const buttonWrapper = wrapper.find("Button");
617
+ buttonWrapper.simulate("keydown", {
618
+ keyCode: keyCodes.enter,
619
+ });
620
+ buttonWrapper.simulate("keyup", {
621
+ keyCode: keyCodes.enter,
622
+ });
623
+ await wait(0);
624
+ buttonWrapper.update();
625
+
626
+ // Assert
627
+ expect(wrapper.find("#foo")).not.toExist();
628
+ });
629
+
630
+ test("beforeNav resolution results in client-side navigation", async () => {
631
+ // Arrange
632
+ const wrapper = mount(
633
+ <MemoryRouter>
634
+ <div>
635
+ <Button
636
+ href="/foo"
637
+ beforeNav={(e) => Promise.resolve()}
638
+ >
639
+ Click me!
640
+ </Button>
641
+ <Switch>
642
+ <Route path="/foo">
643
+ <div id="foo">Hello, world!</div>
644
+ </Route>
645
+ </Switch>
646
+ </div>
647
+ </MemoryRouter>,
648
+ );
649
+
650
+ // Act
651
+ const buttonWrapper = wrapper.find("Button");
652
+ buttonWrapper.simulate("keydown", {
653
+ keyCode: keyCodes.enter,
654
+ });
655
+ buttonWrapper.simulate("keyup", {
656
+ keyCode: keyCodes.enter,
657
+ });
658
+ await wait(0);
659
+ buttonWrapper.update();
660
+
661
+ // Assert
662
+ expect(wrapper.find("#foo")).toExist();
663
+ });
664
+
665
+ test("safeWithNav with skipClientNav=true waits for promise resolution", async () => {
666
+ // Arrange
667
+ jest.spyOn(window.location, "assign");
668
+ const wrapper = mount(
669
+ <MemoryRouter>
670
+ <div>
671
+ <Button
672
+ href="/foo"
673
+ safeWithNav={(e) => Promise.resolve()}
674
+ skipClientNav={true}
675
+ >
676
+ Click me!
677
+ </Button>
678
+ <Switch>
679
+ <Route path="/foo">
680
+ <div id="foo">Hello, world!</div>
681
+ </Route>
682
+ </Switch>
683
+ </div>
684
+ </MemoryRouter>,
685
+ );
686
+
687
+ // Act
688
+ const buttonWrapper = wrapper.find("Button");
689
+ buttonWrapper.simulate("keydown", {
690
+ keyCode: keyCodes.enter,
691
+ });
692
+ buttonWrapper.simulate("keyup", {
693
+ keyCode: keyCodes.enter,
694
+ });
695
+ await wait(0);
696
+ buttonWrapper.update();
697
+
698
+ // Assert
699
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
700
+ });
701
+
702
+ test("safeWithNav with skipClientNav=true waits for promise rejection", async () => {
703
+ // Arrange
704
+ jest.spyOn(window.location, "assign");
705
+ const wrapper = mount(
706
+ <MemoryRouter>
707
+ <div>
708
+ <Button
709
+ href="/foo"
710
+ safeWithNav={(e) => Promise.reject()}
711
+ skipClientNav={true}
712
+ >
713
+ Click me!
714
+ </Button>
715
+ <Switch>
716
+ <Route path="/foo">
717
+ <div id="foo">Hello, world!</div>
718
+ </Route>
719
+ </Switch>
720
+ </div>
721
+ </MemoryRouter>,
722
+ );
723
+
724
+ // Act
725
+ const buttonWrapper = wrapper.find("Button");
726
+ buttonWrapper.simulate("keydown", {
727
+ keyCode: keyCodes.enter,
728
+ });
729
+ buttonWrapper.simulate("keyup", {
730
+ keyCode: keyCodes.enter,
731
+ });
732
+ await wait(0);
733
+ buttonWrapper.update();
734
+
735
+ // Assert
736
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
737
+ });
738
+
739
+ test("safeWithNav with skipClientNav=false calls safeWithNav but doesn't wait to navigate", async () => {
740
+ // Arrange
741
+ jest.spyOn(window.location, "assign");
742
+ const safeWithNavMock = jest.fn();
743
+ const wrapper = mount(
744
+ <MemoryRouter>
745
+ <div>
746
+ <Button
747
+ href="/foo"
748
+ safeWithNav={safeWithNavMock}
749
+ skipClientNav={false}
750
+ >
751
+ Click me!
752
+ </Button>
753
+ <Switch>
754
+ <Route path="/foo">
755
+ <div id="foo">Hello, world!</div>
756
+ </Route>
757
+ </Switch>
758
+ </div>
759
+ </MemoryRouter>,
760
+ );
761
+
762
+ // Act
763
+ const buttonWrapper = wrapper.find("Button");
764
+ buttonWrapper.simulate("keydown", {
765
+ keyCode: keyCodes.enter,
766
+ });
767
+ buttonWrapper.simulate("keyup", {
768
+ keyCode: keyCodes.enter,
769
+ });
770
+
771
+ // Assert
772
+ expect(safeWithNavMock).toHaveBeenCalled();
773
+ expect(window.location.assign).toHaveBeenCalledWith("/foo");
774
+ });
775
+ });
776
+
777
+ describe("type='submit'", () => {
778
+ test("submit button within form via click", () => {
779
+ // Arrange
780
+ const submitFnMock = jest.fn();
781
+ const wrapper = mount(
782
+ <form onSubmit={submitFnMock}>
783
+ <Button type="submit">Click me!</Button>
784
+ </form>,
785
+ );
786
+
787
+ // Act
788
+ wrapper.find("button").simulate("click");
789
+
790
+ // Assert
791
+ expect(submitFnMock).toHaveBeenCalled();
792
+ });
793
+
794
+ test("submit button within form via keyboard", () => {
795
+ // Arrange
796
+ const submitFnMock = jest.fn();
797
+ const wrapper = mount(
798
+ <form onSubmit={submitFnMock}>
799
+ <Button type="submit">Click me!</Button>
800
+ </form>,
801
+ );
802
+
803
+ // Act
804
+ wrapper.find("button").simulate("keydown", {
805
+ keyCode: keyCodes.enter,
806
+ });
807
+ wrapper.find("button").simulate("keyup", {
808
+ keyCode: keyCodes.enter,
809
+ });
810
+
811
+ // Assert
812
+ expect(submitFnMock).toHaveBeenCalled();
813
+ });
814
+
815
+ test("submit button doesn't break if it's not in a form", () => {
816
+ // Arrange
817
+ const wrapper = mount(<Button type="submit">Click me!</Button>);
818
+
819
+ // Act
820
+ expect(() => {
821
+ // Assert
822
+ wrapper.find("button").simulate("click");
823
+ }).not.toThrow();
824
+ });
825
+ });
826
+ });