Skip to content

Commit 03a2eb5

Browse files
committed
wip tests
1 parent ccf8ff5 commit 03a2eb5

File tree

32 files changed

+345
-311
lines changed

32 files changed

+345
-311
lines changed

docs/requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
dash>=2.0.0
2-
dash_bootstrap_components==ci-fixes
1+
dash==3.0.0rc1
2+
# dash_bootstrap_components==1.7.1-dev
33
gunicorn
44
markdown
55
pandas

src/components/accordion/__tests__/Accordion.test.js

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import React from 'react';
6-
import {render} from '@testing-library/react';
6+
import {act, render, screen, waitFor} from '@testing-library/react';
77
import userEvent from '@testing-library/user-event';
88
import Accordion from '../Accordion';
99
import AccordionItem from '../AccordionItem';
@@ -91,7 +91,8 @@ describe('Accordion', () => {
9191
).not.toHaveClass('show');
9292
});
9393

94-
test('tracks most recently clicked item with "active_item" prop', () => {
94+
test('tracks most recently clicked item with "active_item" prop', async () => {
95+
const user = userEvent.setup({advanceTimers: jest.advanceTimersByTime});
9596
const mockSetProps = jest.fn();
9697
const {container, rerender} = render(
9798
<Accordion setProps={mockSetProps} active_item="item-0">
@@ -109,9 +110,7 @@ describe('Accordion', () => {
109110
accordionItems.children[1].querySelector('div.accordion-collapse')
110111
).not.toHaveClass('show');
111112

112-
userEvent.click(
113-
accordionItems.children[1].querySelector('h2.accordion-header > button')
114-
);
113+
await user.click(await screen.findByText('item-title-2'));
115114
expect(mockSetProps.mock.calls).toHaveLength(1);
116115

117116
rerender(
@@ -120,7 +119,7 @@ describe('Accordion', () => {
120119
<AccordionItem title="item-title-2">item-content-2</AccordionItem>
121120
</Accordion>
122121
);
123-
jest.runAllTimers();
122+
act(() => jest.runAllTimers());
124123

125124
expect(
126125
accordionItems.children[0].querySelector('div.accordion-collapse')
@@ -130,9 +129,7 @@ describe('Accordion', () => {
130129
).toHaveClass('show');
131130

132131
// clicking on an open item closes it
133-
userEvent.click(
134-
accordionItems.children[1].querySelector('h2.accordion-header > button')
135-
);
132+
await user.click(await screen.findByText('item-title-2'));
136133
expect(mockSetProps.mock.calls).toHaveLength(2);
137134

138135
rerender(
@@ -141,7 +138,7 @@ describe('Accordion', () => {
141138
<AccordionItem title="item-title-2">item-content-2</AccordionItem>
142139
</Accordion>
143140
);
144-
jest.runAllTimers();
141+
act(() => jest.runAllTimers());
145142

146143
expect(
147144
accordionItems.children[0].querySelector('div.accordion-collapse')
@@ -151,7 +148,8 @@ describe('Accordion', () => {
151148
).not.toHaveClass('show');
152149
});
153150

154-
test('keeps item open with "always_open" prop', () => {
151+
test('keeps item open with "always_open" prop', async () => {
152+
const user = userEvent.setup({advanceTimers: jest.advanceTimersByTime});
155153
const mockSetProps = jest.fn();
156154

157155
const {container} = render(
@@ -172,34 +170,31 @@ describe('Accordion', () => {
172170
).not.toHaveClass('show');
173171

174172
// Click on the second item
175-
userEvent.click(
176-
accordionItems.children[1].querySelector('h2.accordion-header > button')
177-
);
173+
await user.click(await screen.findByText('item-title-2'));
178174
expect(mockSetProps.mock.calls).toHaveLength(1);
179175

180-
// Allow the click to take effect
181-
jest.runAllTimers();
176+
// wait for transition to complete
177+
await waitFor(() =>
178+
expect(
179+
accordionItems.children[1].querySelector('div.accordion-collapse')
180+
).toHaveClass('show')
181+
);
182182

183183
// Check just the second item is open
184184
expect(
185185
accordionItems.children[0].querySelector('div.accordion-collapse')
186186
).not.toHaveClass('show');
187-
expect(
188-
accordionItems.children[1].querySelector('div.accordion-collapse')
189-
).toHaveClass('show');
190187

191188
// Click on the first item
192-
userEvent.click(
193-
accordionItems.children[0].querySelector('h2.accordion-header > button')
194-
);
189+
await user.click(await screen.findByText('item-title-1'));
195190
expect(mockSetProps.mock.calls).toHaveLength(2);
196-
// Allow the click to take effect
197-
jest.runAllTimers();
198191

199192
// Check that the first child is now open, and the second remains open
200-
expect(
201-
accordionItems.children[0].querySelector('div.accordion-collapse')
202-
).toHaveClass('show');
193+
await waitFor(() =>
194+
expect(
195+
accordionItems.children[0].querySelector('div.accordion-collapse')
196+
).toHaveClass('show')
197+
);
203198
expect(
204199
accordionItems.children[1].querySelector('div.accordion-collapse')
205200
).toHaveClass('show');
@@ -224,7 +219,8 @@ describe('Accordion', () => {
224219
).toHaveClass('show');
225220
});
226221

227-
test('tracks most recently clicked item with "active_item" prop when always_open', () => {
222+
test('tracks most recently clicked item with "active_item" prop when always_open', async () => {
223+
const user = userEvent.setup({advanceTimers: jest.advanceTimersByTime});
228224
const mockSetProps = jest.fn();
229225
const {container, rerender} = render(
230226
<Accordion setProps={mockSetProps} active_item={['item-0']} always_open>
@@ -248,9 +244,7 @@ describe('Accordion', () => {
248244
).not.toHaveClass('show');
249245

250246
// Click the middle option
251-
userEvent.click(
252-
accordionItems.children[1].querySelector('h2.accordion-header > button')
253-
);
247+
await user.click(await screen.getByText('item-title-2'));
254248
expect(mockSetProps.mock.calls).toHaveLength(1);
255249

256250
rerender(
@@ -264,7 +258,7 @@ describe('Accordion', () => {
264258
<AccordionItem title="item-title-3">item-content-3</AccordionItem>
265259
</Accordion>
266260
);
267-
jest.runAllTimers();
261+
act(() => jest.runAllTimers());
268262

269263
// Check first option stayed open, middle option now open but third still
270264
// closed
@@ -279,9 +273,7 @@ describe('Accordion', () => {
279273
).not.toHaveClass('show');
280274

281275
// clicking on 1st item closes it, but keeps second item open and 3rd closed
282-
userEvent.click(
283-
accordionItems.children[0].querySelector('h2.accordion-header > button')
284-
);
276+
await user.click(await screen.getByText('item-title-1'));
285277
expect(mockSetProps.mock.calls).toHaveLength(2);
286278

287279
rerender(
@@ -295,7 +287,7 @@ describe('Accordion', () => {
295287
<AccordionItem title="item-title-3">item-content-3</AccordionItem>
296288
</Accordion>
297289
);
298-
jest.runAllTimers();
290+
act(() => jest.runAllTimers());
299291

300292
// Check that 1 and 3 now closed, and 2 is open
301293
expect(

src/components/badge/__tests__/Badge.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ describe('Badge', () => {
5656
expect(badge.getAttribute('href')).toBe(href);
5757
});
5858

59-
test('tracks clicks with n_clicks', () => {
59+
test('tracks clicks with n_clicks', async () => {
60+
const user = userEvent.setup();
6061
const mockSetProps = jest.fn();
6162
const badge = render(<Badge setProps={mockSetProps}>Clickable</Badge>);
6263

6364
expect(mockSetProps.mock.calls).toHaveLength(0);
6465

65-
userEvent.click(badge.getByText('Clickable'));
66+
await user.click(badge.getByText('Clickable'));
6667

6768
expect(mockSetProps.mock.calls).toHaveLength(1);
6869
expect(mockSetProps.mock.calls[0][0].n_clicks).toBe(1);

src/components/button/Button.js

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,26 @@ import Link from '../../private/Link';
1212
* Use the `n_clicks` prop to trigger callbacks when the button has been
1313
* clicked.
1414
*/
15-
const Button = props => {
16-
const {
17-
children,
18-
disabled,
19-
href,
20-
loading_state,
21-
setProps,
22-
n_clicks,
23-
target,
24-
type,
25-
download,
26-
name,
27-
value,
28-
className,
29-
class_name,
30-
color,
31-
outline,
32-
onClick,
33-
rel,
34-
...otherProps
35-
} = props;
36-
15+
const Button = ({
16+
children,
17+
disabled,
18+
href,
19+
loading_state,
20+
setProps,
21+
target,
22+
type,
23+
download,
24+
name,
25+
value,
26+
className,
27+
class_name,
28+
color,
29+
outline,
30+
onClick,
31+
rel,
32+
n_clicks = 0,
33+
...otherProps
34+
}) => {
3735
const incrementClicks = () => {
3836
if (!disabled && setProps) {
3937
setProps({
@@ -73,11 +71,6 @@ const Button = props => {
7371
);
7472
};
7573

76-
Button.dashPersistence = {
77-
n_clicks: 0,
78-
n_clicks_timestamp: -1
79-
};
80-
8174
Button.propTypes = {
8275
/**
8376
* The ID of this component, used to identify dash components

src/components/button/__tests__/Button.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ describe('Button', () => {
8484
);
8585
});
8686

87-
test('tracks clicks with n_clicks', () => {
87+
test('tracks clicks with n_clicks', async () => {
88+
const user = userEvent.setup();
8889
const mockSetProps = jest.fn();
8990
const button = render(<Button setProps={mockSetProps}>Clickable</Button>);
9091

9192
expect(mockSetProps.mock.calls).toHaveLength(0);
9293

93-
userEvent.click(button.getByText('Clickable'));
94+
await user.click(button.getByText('Clickable'));
9495

9596
expect(mockSetProps.mock.calls).toHaveLength(1);
9697
expect(mockSetProps.mock.calls[0][0].n_clicks).toBe(1);

src/components/card/__tests__/CardLink.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ describe('CardLink', () => {
2020
expect(cardLink.container).toHaveTextContent('Some card link content');
2121
});
2222

23-
test('tracks clicks with n_clicks', () => {
23+
test('tracks clicks with n_clicks', async () => {
24+
const user = userEvent.setup();
2425
const mockSetProps = jest.fn();
2526
const cardLink = render(
2627
<CardLink setProps={mockSetProps}>Clickable</CardLink>
2728
);
2829

2930
expect(mockSetProps.mock.calls).toHaveLength(0);
3031

31-
userEvent.click(cardLink.getByText('Clickable'));
32+
await user.click(cardLink.getByText('Clickable'));
3233

3334
expect(mockSetProps.mock.calls).toHaveLength(1);
3435
expect(mockSetProps.mock.calls[0][0].n_clicks).toBe(1);

src/components/carousel/Carousel.js

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,19 @@ import Link from '../../private/Link';
1010
* Component for creating Bootstrap carousel. This component is a slideshow
1111
* for cycling through a series of content.
1212
*/
13-
const Carousel = props => {
14-
const {
15-
items,
16-
style,
17-
class_name,
18-
className,
19-
loading_state,
20-
setProps,
21-
interval,
22-
active_index = 0,
23-
controls = true,
24-
indicators = true,
25-
...otherProps
26-
} = props;
27-
13+
const Carousel = ({
14+
items,
15+
style,
16+
class_name,
17+
className,
18+
loading_state,
19+
setProps,
20+
interval,
21+
active_index = 0,
22+
controls = true,
23+
indicators = true,
24+
...otherProps
25+
}) => {
2826
const slides = items.map(item => {
2927
// note - the default 'd-block w-100' is from the examples in the Bootstrap docs.
3028
item.imgClassName =

src/components/carousel/__tests__/Carousel.test.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ describe('Carousel', () => {
4646
expect(items.children[1]).not.toHaveClass('active');
4747
});
4848

49-
test('tracks most recently clicked slide with "active_index" prop', () => {
49+
test('tracks most recently clicked slide with "active_index" prop', async () => {
50+
const user = userEvent.setup();
5051
const mockSetProps = jest.fn();
5152
const {container} = render(
5253
<Carousel items={slides} setProps={mockSetProps} active_index={0} />
@@ -59,7 +60,7 @@ describe('Carousel', () => {
5960

6061
const nextButton = container.querySelector('a.carousel-control-next');
6162

62-
userEvent.click(nextButton);
63+
await user.click(nextButton);
6364
expect(mockSetProps.mock.calls).toHaveLength(1);
6465
expect(mockSetProps.mock.calls[0][0].active_index).toBe(1);
6566
});
@@ -82,7 +83,7 @@ describe('Carousel', () => {
8283
{
8384
key: '0',
8485
src: '',
85-
alt: 'z',
86+
alt: 'this is the blank one',
8687
href: 'http://www.example.com',
8788
target: '_blank'
8889
},
@@ -99,13 +100,13 @@ describe('Carousel', () => {
99100
src: '',
100101
alt: 'z',
101102
href: 'http://www.example.com'
102-
},
103-
...slides
103+
}
104104
];
105105

106106
const carousel = render(<Carousel items={linkedSlides} />);
107107
const carouselItems = carousel.container.querySelectorAll('.carousel-item');
108108
const blankTargetItem = carouselItems[0];
109+
109110
expect(blankTargetItem).toHaveAttribute('target', '_blank');
110111
expect(blankTargetItem.tagName.toLowerCase()).toEqual('a');
111112

src/components/collapse/__tests__/Collapse.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import React from 'react';
6-
import {render} from '@testing-library/react';
6+
import {act, render} from '@testing-library/react';
77
import Collapse from '../Collapse';
88

99
jest.useFakeTimers();
@@ -44,7 +44,7 @@ describe('Collapse', () => {
4444
</Collapse>
4545
);
4646
expect(collapse.container.querySelector('div.collapsing')).not.toBe(null);
47-
jest.runAllTimers();
47+
act(() => jest.runAllTimers());
4848

4949
expect(collapse.container.querySelector('div.collapse.show')).not.toBe(
5050
null

0 commit comments

Comments
 (0)