Skip to content

Commit 679a1bd

Browse files
committed
finish tests for exercise 5
1 parent 3e8cd05 commit 679a1bd

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

exercises/05.responsive/01.solution.deferred/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ function SearchResults({
106106
search: string
107107
onSelection: (shipName: string) => void
108108
}) {
109-
const shipResults = use(searchShips(search))
109+
// 🦉 feel free to adjust the search delay to see how it affects the UI
110+
// 🚨 the tests kinda rely on the search delay being longer than the spin-delay
111+
const shipResults = use(searchShips(search, 500))
110112
return shipResults.ships.map((ship) => (
111113
<li key={ship.name}>
112114
<button onClick={() => onSelection(ship.name)}>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitFor, fireEvent, within } = dtl
3+
4+
import './index.tsx'
5+
6+
await testStep('Initial render', async () => {
7+
await screen.findByRole('heading', { name: /Dreadnought/i })
8+
await screen.findByPlaceholderText(/filter ships/i)
9+
})
10+
11+
await testStep('Search input is responsive during search', async () => {
12+
const searchInput = screen.getByPlaceholderText(/filter ships/i)
13+
14+
// Type slowly to simulate user input
15+
fireEvent.change(searchInput, { target: { value: 'S' } })
16+
await new Promise((resolve) => setTimeout(resolve, 100))
17+
fireEvent.change(searchInput, { target: { value: 'St' } })
18+
await new Promise((resolve) => setTimeout(resolve, 100))
19+
fireEvent.change(searchInput, { target: { value: 'Sta' } })
20+
21+
// Check if the input value updates basically immediately
22+
await new Promise((resolve) => setTimeout(resolve, 0))
23+
expect(searchInput).toHaveValue('Sta')
24+
25+
// Wait for the search results to update
26+
await waitFor(
27+
() => {
28+
expect(screen.getByText(/Star Hopper/i)).toBeInTheDocument()
29+
expect(screen.getByText(/Star Destroyer/i)).toBeInTheDocument()
30+
},
31+
{ timeout: 2000 },
32+
)
33+
})
34+
35+
await testStep('Pending UI is shown during search', async () => {
36+
const searchInput = screen.getByPlaceholderText(/filter ships/i)
37+
38+
fireEvent.change(searchInput, { target: { value: 'Infinity' } })
39+
40+
const resultsContainer = within(document.querySelector('.search')!).getByRole(
41+
'list',
42+
)
43+
44+
// Check for pending UI (lowered opacity)
45+
await waitFor(() => {
46+
expect(resultsContainer).toHaveStyle({ opacity: '0.6' })
47+
})
48+
49+
// Wait for the search results to update
50+
await waitFor(
51+
() => {
52+
expect(screen.getByText(/Infinity Drifter/i)).toBeInTheDocument()
53+
expect(resultsContainer).toHaveStyle({ opacity: '1' })
54+
},
55+
{ timeout: 2000 },
56+
)
57+
})
58+
59+
await testStep('User can interrupt pending state', async () => {
60+
const searchInput = screen.getByPlaceholderText(/filter ships/i)
61+
62+
fireEvent.change(searchInput, { target: { value: 'Gal' } })
63+
await new Promise((resolve) => setTimeout(resolve, 100))
64+
fireEvent.change(searchInput, { target: { value: 'Pla' } })
65+
66+
// Check if the input value updates immediately
67+
expect(searchInput).toHaveValue('Pla')
68+
69+
// Wait for the search results to update to the latest input
70+
await waitFor(
71+
() => {
72+
expect(screen.getByText(/Planet Hopper/i)).toBeInTheDocument()
73+
},
74+
{ timeout: 2000 },
75+
)
76+
})

0 commit comments

Comments
 (0)