1 | import {
|
2 | isElementFocusable,
|
3 | isElementTabbable,
|
4 | focusFirstFocusableElement,
|
5 | stopEvent,
|
6 | } from './utils';
|
7 |
|
8 | describe('isElementFocusable', () => {
|
9 | const myBtn = () => document.querySelector('button');
|
10 | const myInput = () => document.querySelector('input');
|
11 |
|
12 | beforeEach(() => {
|
13 | document.body.innerHTML = '';
|
14 | });
|
15 |
|
16 | it('should return true for a button', () => {
|
17 | document.body.innerHTML = '<button> My Button </button>';
|
18 |
|
19 | expect(isElementFocusable(myBtn())).toBe(true);
|
20 | });
|
21 |
|
22 | it('should return false for an element with a z-index of -1', () => {
|
23 | document.body.innerHTML = '<button z-index="-1"> My Button </button>';
|
24 |
|
25 | expect(isElementFocusable(myBtn())).toBe(false);
|
26 | });
|
27 |
|
28 | it('should return true for an input', () => {
|
29 | document.body.innerHTML = '<input type="text" />';
|
30 |
|
31 | expect(isElementFocusable(myInput())).toBe(true);
|
32 | });
|
33 |
|
34 | it('should return false for an input with a type hidden', () => {
|
35 | document.body.innerHTML = '<input type="hidden" />';
|
36 |
|
37 | expect(isElementFocusable(myInput())).toBe(false);
|
38 | });
|
39 |
|
40 | it('should return false for a disabled button', () => {
|
41 | document.body.innerHTML = '<button disabled> My Button </button>';
|
42 |
|
43 | expect(isElementFocusable(myBtn())).toBe(false);
|
44 | });
|
45 |
|
46 | it('should return true for an anchor tag with an href attribute', () => {
|
47 | document.body.innerHTML = '<a href="mylink"> My Link </a>';
|
48 | const myAnchor = document.querySelector('a');
|
49 |
|
50 | expect(isElementFocusable(myAnchor)).toBe(true);
|
51 | });
|
52 |
|
53 | it('should return true for an anchor tag without an href attribute', () => {
|
54 | document.body.innerHTML = '<a href=""> My Link </a>';
|
55 | const myAnchor = document.querySelector('a');
|
56 |
|
57 | expect(isElementFocusable(myAnchor)).toBe(false);
|
58 | });
|
59 | });
|
60 |
|
61 | describe('isElementTabbable', () => {
|
62 | const myDiv = () => document.querySelector('div');
|
63 |
|
64 | beforeEach(() => {
|
65 | document.body.innerHTML = '';
|
66 | });
|
67 |
|
68 | it('should return false for a div without tabindex', () => {
|
69 | document.body.innerHTML = '<div> Fake button </div>';
|
70 |
|
71 | expect(isElementTabbable(myDiv())).toBe(false);
|
72 | });
|
73 |
|
74 | it('should return false for a div with a tabindex less than 0', () => {
|
75 | document.body.innerHTML = '<div tabindex="-1"> Fake button </div>';
|
76 |
|
77 | expect(isElementTabbable(myDiv())).toBe(false);
|
78 | });
|
79 |
|
80 | it('should return true for a div with a tabindex equal to 0', () => {
|
81 | document.body.innerHTML = '<div tabindex="0"> Fake button </div>';
|
82 |
|
83 | expect(isElementTabbable(myDiv())).toBe(true);
|
84 | });
|
85 |
|
86 | it('should return true for a div with a tabindex greater than 0', () => {
|
87 | document.body.innerHTML = '<div tabindex="0"> Fake button </div>';
|
88 |
|
89 | expect(isElementTabbable(myDiv())).toBe(true);
|
90 | });
|
91 | });
|
92 |
|
93 | describe('focusFirstFocusableElement', () => {
|
94 | const myBtn = () => document.querySelector('button');
|
95 | const myInput = () => document.querySelector('input');
|
96 |
|
97 | beforeEach(() => {
|
98 | document.body.innerHTML = '';
|
99 | });
|
100 |
|
101 | it('Focus the first element of the list if available', () => {
|
102 | document.body.innerHTML = '<div><div><button></button><input /></div></div>';
|
103 |
|
104 | focusFirstFocusableElement([myBtn(), myInput()]);
|
105 |
|
106 | expect(document.activeElement).toBe(myBtn());
|
107 | });
|
108 |
|
109 | it('Focus the second element of the list if the first is not valid', () => {
|
110 | document.body.innerHTML = '<div><div><button disabled></button><input /></div></div>';
|
111 |
|
112 | focusFirstFocusableElement([myBtn(), myInput()]);
|
113 |
|
114 | expect(document.activeElement).toBe(myInput());
|
115 | });
|
116 | });
|
117 |
|
118 | describe('stopEvent', () => {
|
119 | beforeEach(() => {
|
120 | jest.clearAllMocks();
|
121 | });
|
122 |
|
123 | const event = {
|
124 | preventDefault: jest.fn(),
|
125 | stopPropagation: jest.fn(),
|
126 | stopImmediatePropagation: jest.fn(),
|
127 | };
|
128 |
|
129 | it('calls preventDefault and stopPropagation by default', () => {
|
130 | stopEvent(event);
|
131 |
|
132 | expect(event.preventDefault).toHaveBeenCalledTimes(1);
|
133 | expect(event.stopPropagation).toHaveBeenCalledTimes(1);
|
134 | expect(event.stopImmediatePropagation).not.toHaveBeenCalled();
|
135 | });
|
136 |
|
137 | it('completely stops the event when stopImmediatePropagation is true', () => {
|
138 | stopEvent(event, { stopImmediatePropagation: true });
|
139 |
|
140 | expect(event.preventDefault).toHaveBeenCalledTimes(1);
|
141 | expect(event.stopPropagation).toHaveBeenCalledTimes(1);
|
142 | expect(event.stopImmediatePropagation).toHaveBeenCalledTimes(1);
|
143 | });
|
144 |
|
145 | it('calls event stop methods set to true', () => {
|
146 | stopEvent(event, {
|
147 | preventDefault: false,
|
148 | stopPropagation: false,
|
149 | stopImmediatePropagation: true,
|
150 | });
|
151 |
|
152 | expect(event.preventDefault).not.toHaveBeenCalled();
|
153 | expect(event.stopPropagation).not.toHaveBeenCalled();
|
154 | expect(event.stopImmediatePropagation).toHaveBeenCalledTimes(1);
|
155 | });
|
156 | });
|