Skip to content

Commit 880c649

Browse files
committed
added testing ids to preferences component and wrote test cases for a few UI elements in preferences
1 parent 9687be8 commit 880c649

File tree

2 files changed

+319
-1
lines changed

2 files changed

+319
-1
lines changed

client/modules/IDE/components/Preferences/index.jsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,17 @@ class Preferences extends React.Component {
170170
onClick={this.decreaseFontSize}
171171
aria-label={this.props.t('Preferences.DecreaseFontARIA')}
172172
disabled={this.state.fontSize <= 8}
173+
data-testid="font-minus-button"
173174
>
174175
<MinusIcon focusable="false" aria-hidden="true" />
175176
<h6 className="preference__label">
176177
{this.props.t('Preferences.DecreaseFont')}
177178
</h6>
178179
</button>
179-
<form onSubmit={this.onFontInputSubmit}>
180+
<form
181+
onSubmit={this.onFontInputSubmit}
182+
data-testid="font-size-form"
183+
>
180184
<input
181185
className="preference__value"
182186
aria-live="polite"
@@ -190,13 +194,15 @@ class Preferences extends React.Component {
190194
onClick={() => {
191195
this.fontSizeInput.select();
192196
}}
197+
data-testid="font-size-text-field"
193198
/>
194199
</form>
195200
<button
196201
className="preference__plus-button"
197202
onClick={this.increaseFontSize}
198203
aria-label={this.props.t('Preferences.IncreaseFontARIA')}
199204
disabled={this.state.fontSize >= 36}
205+
data-testid="font-plus-button"
200206
>
201207
<PlusIcon focusable="false" aria-hidden="true" />
202208
<h6 className="preference__label">
@@ -218,6 +224,7 @@ class Preferences extends React.Component {
218224
className="preference__radio-button"
219225
value="On"
220226
checked={this.props.autosave}
227+
data-testid="autosave-true-radio"
221228
/>
222229
<label htmlFor="autosave-on" className="preference__option">
223230
{this.props.t('Preferences.On')}
@@ -231,6 +238,7 @@ class Preferences extends React.Component {
231238
className="preference__radio-button"
232239
value="Off"
233240
checked={!this.props.autosave}
241+
data-testid="autosave-false-radio"
234242
/>
235243
<label htmlFor="autosave-off" className="preference__option">
236244
{this.props.t('Preferences.Off')}
@@ -253,6 +261,7 @@ class Preferences extends React.Component {
253261
className="preference__radio-button"
254262
value="On"
255263
checked={this.props.autocloseBracketsQuotes}
264+
data-testid="autoclose-true-radio"
256265
/>
257266
<label
258267
htmlFor="autoclosebracketsquotes-on"
@@ -271,6 +280,7 @@ class Preferences extends React.Component {
271280
className="preference__radio-button"
272281
value="Off"
273282
checked={!this.props.autocloseBracketsQuotes}
283+
data-testid="autoclose-false-radio"
274284
/>
275285
<label
276286
htmlFor="autoclosebracketsquotes-off"
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
import React from 'react';
2+
import { unmountComponentAtNode } from 'react-dom';
3+
import { act } from 'react-dom/test-utils';
4+
import { fireEvent, render, screen, waitFor } from '../../../../test-utils';
5+
import Preferences from './index';
6+
7+
/* props to pass in:
8+
* - this.props.fontSize : number
9+
* - this.props.autosave : bool
10+
* - this.props.autocloseBracketsQuotes : bool
11+
* - this.props.linewrap : bool
12+
* - this.props.lineNumbers : bool
13+
* - this.props.theme : string
14+
* - this.props.lintWarning : bool
15+
* - this.props.textOutput : bool
16+
* - this.props.gridOutput : bool
17+
* - this.props.soundOutput : bool
18+
* - t from internationalization
19+
*
20+
* - this.props.setFontSize(fontsize : number)
21+
* - this.props.setAutosave(value : bool)
22+
* - this.props.setAutocloseBracketsQuotes(value: bool)
23+
* - this.props.setLinewrap(value : bool)
24+
* - this.props.setLineNumbers(value : bool)
25+
* - this.props.setTheme(color : string) -> can be {"light", "dark", "contrast"}
26+
* - this.props.setLintWarning(value : bool)
27+
* - this.props.setTextOutput(value : bool)
28+
* - this.props.setGridOutput(value : bool)
29+
* - this.props.setSoundOutput(value : bool)
30+
* -
31+
*/
32+
33+
const renderComponent = (extraProps = {}, container) => {
34+
// if we want to overwrite any of these props, we can do it with extraProps
35+
// later keys overwrite earlier ones in the spread operator
36+
const props = {
37+
t: jest.fn(),
38+
fontSize: 12,
39+
autosave: false,
40+
autocloseBracketsQuotes: false,
41+
linewrap: false,
42+
lineNumbers: false,
43+
theme: 'contrast',
44+
lintWarning: false,
45+
textOutput: false,
46+
gridOutput: false,
47+
soundOutput: false,
48+
setFontSize: jest.fn(),
49+
setAutosave: jest.fn(),
50+
setAutocloseBracketsQuotes: jest.fn(),
51+
setLinewrap: jest.fn(),
52+
setLineNumbers: jest.fn(),
53+
setTheme: jest.fn(),
54+
setLintWarning: jest.fn(),
55+
setTextOutput: jest.fn(),
56+
setGridOutput: jest.fn(),
57+
setSoundOutput: jest.fn(),
58+
...extraProps
59+
};
60+
render(<Preferences {...props} />, container);
61+
62+
return props;
63+
};
64+
65+
describe('<Preferences />', () => {
66+
let container = null;
67+
beforeEach(() => {
68+
// setup a DOM element as a render target
69+
container = document.createElement('div');
70+
document.body.appendChild(container);
71+
});
72+
73+
afterEach(() => {
74+
// cleanup on exiting
75+
unmountComponentAtNode(container);
76+
container.remove();
77+
container = null;
78+
});
79+
80+
it('font size increase button says increase', () => {
81+
let props;
82+
// render the component with autosave set to false as default
83+
act(() => {
84+
props = renderComponent({ fontSize: 12 }, container);
85+
});
86+
87+
// get ahold of the radio buttons for toggling autosave
88+
const fontPlusButton = screen.getByTestId('font-plus-button');
89+
90+
// make button says "Increase"
91+
expect(fontPlusButton.textContent.toLowerCase()).toBe('increase');
92+
});
93+
94+
it('increase font size by 2 when clicking plus button', () => {
95+
let props;
96+
// render the component with autosave set to false as default
97+
act(() => {
98+
props = renderComponent({ fontSize: 12 }, container);
99+
});
100+
101+
// get ahold of the radio buttons for toggling autosave
102+
const fontPlusButton = screen.getByTestId('font-plus-button');
103+
104+
act(() => {
105+
fireEvent.click(fontPlusButton);
106+
});
107+
108+
expect(props.setFontSize).toHaveBeenCalledTimes(1);
109+
expect(props.setFontSize.mock.calls[0][0]).toBe(14);
110+
});
111+
112+
it('font size decrease button says decrease', () => {
113+
let props;
114+
// render the component with autosave set to false as default
115+
act(() => {
116+
props = renderComponent({ fontSize: 12 }, container);
117+
});
118+
119+
// get ahold of the radio buttons for toggling autosave
120+
const fontPlusButton = screen.getByTestId('font-minus-button');
121+
122+
// make button says "decrease"
123+
expect(fontPlusButton.textContent.toLowerCase()).toBe('decrease');
124+
});
125+
126+
it('decrease font size by 2 when clicking minus button', () => {
127+
let props;
128+
// render the component with autosave set to false as default
129+
act(() => {
130+
props = renderComponent({ fontSize: 12 }, container);
131+
});
132+
133+
// get ahold of the radio buttons for toggling autosave
134+
const fontMinusButton = screen.getByTestId('font-minus-button');
135+
136+
act(() => {
137+
fireEvent.click(fontMinusButton);
138+
});
139+
140+
expect(props.setFontSize).toHaveBeenCalledTimes(1);
141+
expect(props.setFontSize.mock.calls[0][0]).toBe(10);
142+
});
143+
144+
it('font text field changes on manual text input', () => {
145+
let props;
146+
// render the component with autosave set to false as default
147+
act(() => {
148+
props = renderComponent({ fontSize: 12 }, container);
149+
});
150+
151+
// get ahold of the radio buttons for toggling autosave
152+
const input = screen.getByTestId('font-size-text-field');
153+
154+
act(() => {
155+
fireEvent.change(input, { target: { value: '24' } });
156+
});
157+
act(() => {
158+
fireEvent.submit(screen.getByTestId('font-size-form'));
159+
});
160+
161+
expect(props.setFontSize).toHaveBeenCalledTimes(1);
162+
expect(props.setFontSize.mock.calls[0][0]).toBe(24);
163+
});
164+
165+
it('autosave toggle, starting at false', () => {
166+
let props;
167+
// render the component with autosave set to false as default
168+
act(() => {
169+
props = renderComponent({}, container);
170+
});
171+
172+
// get ahold of the radio buttons for toggling autosave
173+
const autosaveRadioFalse = screen.getByTestId('autosave-false-radio');
174+
const autosaveRadioTrue = screen.getByTestId('autosave-true-radio');
175+
176+
// make sure one is false and the other is true
177+
expect(autosaveRadioFalse.checked).toBe(true);
178+
expect(autosaveRadioTrue.checked).toBe(false);
179+
180+
// click om the one already selected, the false one
181+
act(() => {
182+
fireEvent.click(autosaveRadioFalse);
183+
});
184+
185+
// the value has not changed so OnChange has not been called
186+
expect(props.setAutosave).toHaveBeenCalledTimes(0);
187+
// this radio buttons should still be the same
188+
expect(autosaveRadioFalse.checked).toBe(true);
189+
expect(autosaveRadioTrue.checked).toBe(false);
190+
191+
// now we click the other one that's not yet selected
192+
act(() => {
193+
fireEvent.click(autosaveRadioTrue);
194+
});
195+
196+
// expect that the setAutosave function was called with the value true
197+
expect(props.setAutosave).toHaveBeenCalledTimes(1);
198+
expect(props.setAutosave.mock.calls[0][0]).toBe(true);
199+
});
200+
201+
it('autosave toggle, starting at true', () => {
202+
let props;
203+
// render the component with autosave prop set to true
204+
act(() => {
205+
props = renderComponent({ autosave: true }, container);
206+
});
207+
208+
// get ahold of the radio buttons for toggling autosave
209+
const autosaveRadioFalse = screen.getByTestId('autosave-false-radio');
210+
const autosaveRadioTrue = screen.getByTestId('autosave-true-radio');
211+
212+
// make sure one is false and the other is true
213+
expect(autosaveRadioFalse.checked).toBe(false);
214+
expect(autosaveRadioTrue.checked).toBe(true);
215+
216+
// click om the one already selected, the false one
217+
act(() => {
218+
fireEvent.click(autosaveRadioTrue);
219+
});
220+
221+
// the value has not changed so OnChange has not been called
222+
expect(props.setAutosave).toHaveBeenCalledTimes(0);
223+
// this radio buttons should still be the same
224+
expect(autosaveRadioFalse.checked).toBe(false);
225+
expect(autosaveRadioTrue.checked).toBe(true);
226+
227+
// now we click the other one that's not yet selected
228+
act(() => {
229+
fireEvent.click(autosaveRadioFalse);
230+
});
231+
232+
// expect that the setAutosave function was called with the value false
233+
expect(props.setAutosave).toHaveBeenCalledTimes(1);
234+
expect(props.setAutosave.mock.calls[0][0]).toBe(false);
235+
});
236+
237+
it('autocloseBracketsQuotes toggle, starting at false', () => {
238+
let props;
239+
// render the component with autocloseBracketsQuotes prop set to false
240+
act(() => {
241+
props = renderComponent({}, container);
242+
});
243+
244+
// get ahold of the radio buttons for toggling autocloseBracketsQuotes
245+
const autocloseRadioFalse = screen.getByTestId('autoclose-false-radio');
246+
const autocloseRadioTrue = screen.getByTestId('autoclose-true-radio');
247+
248+
// make sure one is false and the other is true
249+
expect(autocloseRadioFalse.checked).toBe(true);
250+
expect(autocloseRadioTrue.checked).toBe(false);
251+
252+
// click on the one already selected, the false one
253+
act(() => {
254+
fireEvent.click(autocloseRadioFalse);
255+
});
256+
257+
// the value has not changed so OnChange has not been called
258+
expect(props.setAutocloseBracketsQuotes).toHaveBeenCalledTimes(0);
259+
// this radio buttons should still be the same
260+
expect(autocloseRadioFalse.checked).toBe(true);
261+
expect(autocloseRadioTrue.checked).toBe(false);
262+
263+
// now we click the other one that's not yet selected
264+
act(() => {
265+
fireEvent.click(autocloseRadioTrue);
266+
});
267+
268+
// expect that the setautoclose function was called with the value false
269+
expect(props.setAutocloseBracketsQuotes).toHaveBeenCalledTimes(1);
270+
expect(props.setAutocloseBracketsQuotes.mock.calls[0][0]).toBe(true);
271+
});
272+
273+
it('autocloseBracketsQuotes toggle, starting at true', () => {
274+
let props;
275+
// render the component with autocloseBracketsQuotes prop set to false
276+
act(() => {
277+
props = renderComponent({ autocloseBracketsQuotes: true }, container);
278+
});
279+
280+
// get ahold of the radio buttons for toggling autocloseBracketsQuotes
281+
const autocloseRadioFalse = screen.getByTestId('autoclose-false-radio');
282+
const autocloseRadioTrue = screen.getByTestId('autoclose-true-radio');
283+
284+
// make sure one is false and the other is true
285+
expect(autocloseRadioFalse.checked).toBe(false);
286+
expect(autocloseRadioTrue.checked).toBe(true);
287+
288+
// click on the one already selected, the false one
289+
act(() => {
290+
fireEvent.click(autocloseRadioTrue);
291+
});
292+
293+
// the value has not changed so OnChange has not been called
294+
expect(props.setAutocloseBracketsQuotes).toHaveBeenCalledTimes(0);
295+
// this radio buttons should still be the same
296+
expect(autocloseRadioFalse.checked).toBe(false);
297+
expect(autocloseRadioTrue.checked).toBe(true);
298+
299+
// now we click the other one that's not yet selected
300+
act(() => {
301+
fireEvent.click(autocloseRadioFalse);
302+
});
303+
304+
// expect that the setautoclose function was called with the value false
305+
expect(props.setAutocloseBracketsQuotes).toHaveBeenCalledTimes(1);
306+
expect(props.setAutocloseBracketsQuotes.mock.calls[0][0]).toBe(false);
307+
});
308+
});

0 commit comments

Comments
 (0)