Skip to content

Commit 99c1cb5

Browse files
committed
add tests to 02
1 parent 9841c41 commit 99c1cb5

File tree

24 files changed

+413
-76
lines changed

24 files changed

+413
-76
lines changed

exercises/01.managing-ui-state/05.solution.cb/search-params.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2-
const { screen, fireEvent } = dtl
2+
const { screen } = dtl
33

4-
window.history.pushState({}, '', '?query=dog')
4+
const currentPath = window.location.pathname
5+
window.history.pushState({}, '', `${currentPath}?query=dog`)
56

67
await import('./index.tsx')
78

exercises/01.managing-ui-state/README.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ From there's a cycle of user interaction, state changes, and re-rendering. This
1414
is the core of how React works for interactive applications.
1515

1616
The `render` phase is what what we've done so far with creating React elements.
17-
Handling user interactions is what we've done with event listeners like
18-
`onSubmit`. Now we're going to get into the `state changes` bit.
17+
Handling user interactions is what we do with event listeners like `onChange`.
18+
Now we're going to get into the `state changes` bit.
1919

2020
In React, you use special functions called "hooks" to do this. Common built-in
2121
hooks include:

exercises/02.side-effects/01.problem.effects/index.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,7 @@ function App() {
2929

3030
return (
3131
<div className="app">
32-
<form
33-
onSubmit={e => {
34-
e.preventDefault()
35-
setGlobalSearchParams({ query })
36-
}}
37-
>
32+
<form action={() => setGlobalSearchParams({ query })}>
3833
<div>
3934
<label htmlFor="searchInput">Search:</label>
4035
<input
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, fireEvent } = dtl
3+
4+
import './index.tsx'
5+
6+
const searchBox = await testStep(
7+
'The user can see the search box',
8+
async () => {
9+
const result = await screen.findByRole('searchbox', { name: /search/i })
10+
expect(result).toHaveValue('')
11+
return result
12+
},
13+
)
14+
15+
const dogCheckbox = await testStep(
16+
'The user can see the dog checkbox',
17+
async () => {
18+
const result = await screen.findByRole('checkbox', { name: /dog/i })
19+
expect(result).not.toBeChecked()
20+
return result
21+
},
22+
)
23+
24+
await testStep('The user can search for a checkbox value', async () => {
25+
fireEvent.change(searchBox, { target: { value: 'dog' } })
26+
})
27+
28+
await testStep('checkbox is checked automatically', async () => {
29+
expect(dogCheckbox).toBeChecked()
30+
})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, fireEvent } = dtl
3+
4+
import './index.tsx'
5+
6+
const searchBox = await testStep(
7+
'The user can see the search box',
8+
async () => {
9+
const result = await screen.findByRole('searchbox', { name: /search/i })
10+
expect(result).toHaveValue('')
11+
return result
12+
},
13+
)
14+
15+
const dogCheckbox = await testStep(
16+
'The user can see the dog checkbox',
17+
async () => {
18+
const result = await screen.findByRole('checkbox', { name: /dog/i })
19+
expect(result).not.toBeChecked()
20+
return result
21+
},
22+
)
23+
24+
await testStep('The user can select the dog checkbox', async () => {
25+
fireEvent.click(dogCheckbox)
26+
expect(dogCheckbox).toBeChecked()
27+
})
28+
29+
await testStep(
30+
'Selecting the checkbox updates the search and results',
31+
async () => {
32+
// Check that the search box value has been updated
33+
expect(searchBox).toHaveValue('dog')
34+
35+
// Check that the results have been filtered
36+
await dtl.waitFor(async () => {
37+
await screen.findByText(/the joy of owning a dog/i)
38+
39+
const catResult = screen.queryByText(/caring for your feline friend/i)
40+
expect(catResult).not.toBeInTheDocument()
41+
})
42+
},
43+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, fireEvent } = dtl
3+
4+
import './index.tsx'
5+
6+
const searchBox = await testStep(
7+
'The user can see the search box',
8+
async () => {
9+
const result = await screen.findByRole('searchbox', { name: /search/i })
10+
expect(result).toHaveValue('')
11+
return result
12+
},
13+
)
14+
15+
const catResult = await testStep('The user can see the results', async () => {
16+
const result = screen.getByText(/caring for your feline friend/i)
17+
expect(result).toBeInTheDocument()
18+
return result
19+
})
20+
21+
await testStep('The user can search for a term', async () => {
22+
fireEvent.change(searchBox, { target: { value: 'dog' } })
23+
})
24+
25+
await testStep('The results are filtered', async () => {
26+
await dtl.waitFor(() => {
27+
expect(catResult).not.toBeInTheDocument()
28+
})
29+
await screen.findByText(/the joy of owning a dog/i)
30+
})

exercises/02.side-effects/01.solution.effects/index.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,7 @@ function App() {
2828

2929
return (
3030
<div className="app">
31-
<form
32-
onSubmit={e => {
33-
e.preventDefault()
34-
setGlobalSearchParams({ query })
35-
}}
36-
>
31+
<form action={() => setGlobalSearchParams({ query })}>
3732
<div>
3833
<label htmlFor="searchInput">Search:</label>
3934
<input
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, fireEvent } = dtl
3+
4+
const currentPath = window.location.pathname
5+
window.history.pushState({}, '', `${currentPath}?query=dog`)
6+
7+
await import('./index.tsx')
8+
9+
await testStep(
10+
'The search box is initialized with URL query parameter',
11+
async () => {
12+
const searchBox = await screen.findByRole('searchbox', { name: /search/i })
13+
expect(searchBox).toHaveValue('dog')
14+
},
15+
)
16+
17+
// wait for the event handler to be set up
18+
// for some reason it takes a bit
19+
await new Promise(resolve => setTimeout(resolve, 100))
20+
21+
await testStep(
22+
'The search box updates when popstate event is triggered',
23+
async () => {
24+
// Simulate navigation to a new URL
25+
const currentPath = window.location.pathname
26+
window.history.pushState({}, '', `${currentPath}?query=cat`)
27+
28+
// Trigger popstate event
29+
fireEvent.popState(window)
30+
31+
// Check if the search box value is updated
32+
await dtl.waitFor(async () =>
33+
expect(
34+
await screen.findByRole('searchbox', { name: /search/i }),
35+
).toHaveValue('cat'),
36+
)
37+
},
38+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, fireEvent } = dtl
3+
4+
window.history.pushState({}, '', '?query=dog')
5+
6+
await import('./index.tsx')
7+
8+
await testStep(
9+
'The search box is initialized with URL query parameter',
10+
async () => {
11+
const searchBox = await screen.findByRole('searchbox', { name: /search/i })
12+
expect(searchBox).toHaveValue('dog')
13+
},
14+
)

exercises/02.side-effects/02.problem.cleanup/README.mdx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,16 @@ You can add `console.log` statements to make sure things are being called (unles
6161
you want to open up the memory profiling tab in your dev tools and click the
6262
checkbox a bunch of times to see the memory usage go up 😅).
6363

64-
💯 If you really do want to test this out, I've added a couple lines you can
65-
uncomment to allocate huge amounts of memory to huge arrays. If you uncomment
66-
those, then watch the quick climb of the memory in the
64+
🚨 To test this, I've added a couple lines to allocate huge amounts of memory to
65+
huge arrays. Watch the quick climb of the memory in the
6766
[Memory tab of dev tools](https://developer.chrome.com/docs/devtools/memory) or
6867
[Browser Task manager](https://developer.chrome.com/docs/devtools/memory-problems#monitor_memory_use_in_realtime_with_the_chrome_task_manager)
69-
every time you check and uncheck the box.
68+
every time you check and uncheck the box. The test toggles the checkbox many
69+
times and then checks that the memory usage is a reasonable increase of the
70+
initial memory usage.
71+
72+
<callout-warning>
73+
Testing memory leaks is tricky. It's possible the memory usage starts out
74+
higher than it should leading to a test that passes but should not. Try
75+
running the test a few times to be certain you've got it right.
76+
</callout-warning>

0 commit comments

Comments
 (0)