Skip to content

Commit 31f5ba8

Browse files
committed
wut
1 parent b8c38ac commit 31f5ba8

File tree

19 files changed

+5752
-226
lines changed

19 files changed

+5752
-226
lines changed

epicshop/playwright.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export default defineConfig({
2121
use: {
2222
baseURL: `http://localhost:${PORT}/`,
2323
trace: 'retain-on-failure',
24+
// Some errors are expected, e.g. when a ship is not found
25+
ignoreHTTPSErrors: true,
26+
contextOptions: {
27+
ignoreHTTPErrors: true,
28+
},
2429
},
2530

2631
projects: [
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitForElementToBeRemoved } = dtl
3+
4+
import './index.tsx'
5+
6+
const fallbackImage = await testStep(
7+
'Suspense boundary renders ShipFallback',
8+
async () => {
9+
const image = await screen.findByAltText('Dreadnought')
10+
if (!(image instanceof HTMLImageElement)) {
11+
throw new Error('Fallback image not found')
12+
}
13+
expect(
14+
image.src,
15+
'🚨 make sure to render the suspense boundary with the fallback',
16+
).toContain('/img/fallback-ship.png')
17+
return image
18+
},
19+
)
20+
21+
await testStep('ShipFallback contains loading placeholders', async () => {
22+
const [loadingItem] = await screen.findAllByText('loading')
23+
expect(loadingItem).toBeInTheDocument()
24+
})
25+
26+
await testStep('Actual content loads and replaces fallback', async () => {
27+
await waitForElementToBeRemoved(() => screen.queryAllByText('loading'), {
28+
timeout: 5000,
29+
})
30+
})
31+
32+
await testStep('Actual ship details are rendered', async () => {
33+
const image = await screen.findByAltText('Dreadnought')
34+
if (!(image instanceof HTMLImageElement)) {
35+
throw new Error('Ship image not found')
36+
}
37+
expect(image.src).not.toContain('/img/fallback-ship.png')
38+
expect(image).not.toBe(fallbackImage)
39+
})
40+
41+
await testStep('Weapon items are displayed', async () => {
42+
const weaponItems = await screen.findAllByRole('listitem')
43+
expect(weaponItems.length).toBeGreaterThan(0)
44+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitForElementToBeRemoved } = dtl
3+
4+
import './index.tsx'
5+
6+
await testStep(
7+
'Error boundary renders ShipError when ship is not found',
8+
async () => {
9+
// Check for the error message
10+
const errorMessage = await screen.findByText('There was an error')
11+
expect(errorMessage).toBeInTheDocument()
12+
13+
// Check for the specific error message including the ship name
14+
const specificErrorMessage = await screen.findByText(
15+
'There was an error loading "Dreadyacht"',
16+
)
17+
expect(specificErrorMessage).toBeInTheDocument()
18+
19+
// Check for the broken ship image
20+
const brokenShipImage = await screen.findByAltText('broken ship')
21+
if (!(brokenShipImage instanceof HTMLImageElement)) {
22+
throw new Error('Broken ship image not found')
23+
}
24+
expect(brokenShipImage.src).toContain('/img/broken-ship.webp')
25+
},
26+
)

exercises/01.fetching/03.problem.status/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import * as ReactDOM from 'react-dom/client'
33
import { ErrorBoundary } from 'react-error-boundary'
44
import { getImageUrlForShip, getShip, type Ship } from './utils.tsx'
55

6-
const shipName = 'Dreadyacht'
6+
const shipName = 'Dreadnought'
7+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
8+
// const shipName = 'Dreadyacht'
79

810
function App() {
911
return (

exercises/01.fetching/03.solution.status/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import * as ReactDOM from 'react-dom/client'
33
import { ErrorBoundary } from 'react-error-boundary'
44
import { getImageUrlForShip, getShip, type Ship } from './utils.tsx'
55

6-
const shipName = 'Dreadyacht'
6+
const shipName = 'Dreadnought'
7+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
8+
// const shipName = 'Dreadyacht'
79

810
function App() {
911
return (
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitForElementToBeRemoved } = dtl
3+
4+
import './index.tsx'
5+
6+
const shipName = await Promise.race([
7+
screen.findByText('Dreadnought').then(() => 'Dreadnought'),
8+
screen.findByText('Dreadyacht').then(() => 'Dreadyacht'),
9+
])
10+
11+
if (shipName === 'Dreadyacht') {
12+
await testStep(
13+
'Error boundary renders ShipError when ship is not found',
14+
async () => {
15+
// Check for the error message
16+
const errorMessage = await screen.findByText('There was an error')
17+
expect(errorMessage).toBeInTheDocument()
18+
19+
// Check for the specific error message including the ship name
20+
const specificErrorMessage = await screen.findByText(
21+
'There was an error loading "Dreadyacht"',
22+
)
23+
expect(specificErrorMessage).toBeInTheDocument()
24+
25+
// Check for the broken ship image
26+
const brokenShipImage = await screen.findByAltText('broken ship')
27+
if (!(brokenShipImage instanceof HTMLImageElement)) {
28+
throw new Error('Broken ship image not found')
29+
}
30+
expect(brokenShipImage.src).toContain('/img/broken-ship.webp')
31+
},
32+
)
33+
} else {
34+
const fallbackImage = await testStep(
35+
'Suspense boundary renders ShipFallback',
36+
async () => {
37+
const image = await screen.findByAltText('Dreadnought')
38+
if (!(image instanceof HTMLImageElement)) {
39+
throw new Error('Fallback image not found')
40+
}
41+
expect(
42+
image.src,
43+
'🚨 make sure to render the suspense boundary with the fallback',
44+
).toContain('/img/fallback-ship.png')
45+
return image
46+
},
47+
)
48+
49+
await testStep('ShipFallback contains loading placeholders', async () => {
50+
const [loadingItem] = await screen.findAllByText('loading')
51+
expect(loadingItem).toBeInTheDocument()
52+
})
53+
54+
await testStep('Actual content loads and replaces fallback', async () => {
55+
await waitForElementToBeRemoved(() => screen.queryAllByText('loading'), {
56+
timeout: 5000,
57+
})
58+
})
59+
60+
await testStep('Actual ship details are rendered', async () => {
61+
const image = await screen.findByAltText('Dreadnought')
62+
if (!(image instanceof HTMLImageElement)) {
63+
throw new Error('Ship image not found')
64+
}
65+
expect(image.src).not.toContain('/img/fallback-ship.png')
66+
expect(image).not.toBe(fallbackImage)
67+
})
68+
69+
await testStep('Weapon items are displayed', async () => {
70+
const weaponItems = await screen.findAllByRole('listitem')
71+
expect(weaponItems.length).toBeGreaterThan(0)
72+
})
73+
}

exercises/01.fetching/04.problem.util/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type UsePromise<Value> = Promise<Value> & {
2121
// - then throw usePromise
2222

2323
const shipName = 'Dreadnought'
24+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
25+
// const shipName = 'Dreadyacht'
2426

2527
function App() {
2628
return (

exercises/01.fetching/04.solution.util/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ function use<Value>(promise: Promise<Value>): Value {
3434
}
3535

3636
const shipName = 'Dreadnought'
37+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
38+
// const shipName = 'Dreadyacht'
3739

3840
function App() {
3941
return (
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitForElementToBeRemoved } = dtl
3+
4+
import './index.tsx'
5+
6+
const shipName = await Promise.race([
7+
screen.findByText('Dreadnought').then(() => 'Dreadnought'),
8+
screen.findByText('Dreadyacht').then(() => 'Dreadyacht'),
9+
])
10+
11+
if (shipName === 'Dreadyacht') {
12+
await testStep(
13+
'Error boundary renders ShipError when ship is not found',
14+
async () => {
15+
// Check for the error message
16+
const errorMessage = await screen.findByText('There was an error')
17+
expect(errorMessage).toBeInTheDocument()
18+
19+
// Check for the specific error message including the ship name
20+
const specificErrorMessage = await screen.findByText(
21+
'There was an error loading "Dreadyacht"',
22+
)
23+
expect(specificErrorMessage).toBeInTheDocument()
24+
25+
// Check for the broken ship image
26+
const brokenShipImage = await screen.findByAltText('broken ship')
27+
if (!(brokenShipImage instanceof HTMLImageElement)) {
28+
throw new Error('Broken ship image not found')
29+
}
30+
expect(brokenShipImage.src).toContain('/img/broken-ship.webp')
31+
},
32+
)
33+
} else {
34+
const fallbackImage = await testStep(
35+
'Suspense boundary renders ShipFallback',
36+
async () => {
37+
const image = await screen.findByAltText('Dreadnought')
38+
if (!(image instanceof HTMLImageElement)) {
39+
throw new Error('Fallback image not found')
40+
}
41+
expect(
42+
image.src,
43+
'🚨 make sure to render the suspense boundary with the fallback',
44+
).toContain('/img/fallback-ship.png')
45+
return image
46+
},
47+
)
48+
49+
await testStep('ShipFallback contains loading placeholders', async () => {
50+
const [loadingItem] = await screen.findAllByText('loading')
51+
expect(loadingItem).toBeInTheDocument()
52+
})
53+
54+
await testStep('Actual content loads and replaces fallback', async () => {
55+
await waitForElementToBeRemoved(() => screen.queryAllByText('loading'), {
56+
timeout: 5000,
57+
})
58+
})
59+
60+
await testStep('Actual ship details are rendered', async () => {
61+
const image = await screen.findByAltText('Dreadnought')
62+
if (!(image instanceof HTMLImageElement)) {
63+
throw new Error('Ship image not found')
64+
}
65+
expect(image.src).not.toContain('/img/fallback-ship.png')
66+
expect(image).not.toBe(fallbackImage)
67+
})
68+
69+
await testStep('Weapon items are displayed', async () => {
70+
const weaponItems = await screen.findAllByRole('listitem')
71+
expect(weaponItems.length).toBeGreaterThan(0)
72+
})
73+
}

exercises/01.fetching/05.problem.use/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ function use<Value>(promise: Promise<Value>): Value {
3939
}
4040

4141
const shipName = 'Dreadnought'
42+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
43+
// const shipName = 'Dreadyacht'
4244

4345
function App() {
4446
return (

exercises/01.fetching/05.solution.use/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { ErrorBoundary } from 'react-error-boundary'
44
import { getImageUrlForShip, getShip } from './utils.tsx'
55

66
const shipName = 'Dreadnought'
7+
// 🚨 If you want to to test out the error state, change this to 'Dreadyacht'
8+
// const shipName = 'Dreadyacht'
79

810
function App() {
911
return (
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { expect, testStep, dtl } from '@epic-web/workshop-utils/test'
2+
const { screen, waitForElementToBeRemoved } = dtl
3+
4+
import './index.tsx'
5+
6+
const shipName = await Promise.race([
7+
screen.findByText('Dreadnought').then(() => 'Dreadnought'),
8+
screen.findByText('Dreadyacht').then(() => 'Dreadyacht'),
9+
])
10+
11+
if (shipName === 'Dreadyacht') {
12+
await testStep(
13+
'Error boundary renders ShipError when ship is not found',
14+
async () => {
15+
// Check for the error message
16+
const errorMessage = await screen.findByText('There was an error')
17+
expect(errorMessage).toBeInTheDocument()
18+
19+
// Check for the specific error message including the ship name
20+
const specificErrorMessage = await screen.findByText(
21+
'There was an error loading "Dreadyacht"',
22+
)
23+
expect(specificErrorMessage).toBeInTheDocument()
24+
25+
// Check for the broken ship image
26+
const brokenShipImage = await screen.findByAltText('broken ship')
27+
if (!(brokenShipImage instanceof HTMLImageElement)) {
28+
throw new Error('Broken ship image not found')
29+
}
30+
expect(brokenShipImage.src).toContain('/img/broken-ship.webp')
31+
},
32+
)
33+
} else {
34+
const fallbackImage = await testStep(
35+
'Suspense boundary renders ShipFallback',
36+
async () => {
37+
const image = await screen.findByAltText('Dreadnought')
38+
if (!(image instanceof HTMLImageElement)) {
39+
throw new Error('Fallback image not found')
40+
}
41+
expect(
42+
image.src,
43+
'🚨 make sure to render the suspense boundary with the fallback',
44+
).toContain('/img/fallback-ship.png')
45+
return image
46+
},
47+
)
48+
49+
await testStep('ShipFallback contains loading placeholders', async () => {
50+
const [loadingItem] = await screen.findAllByText('loading')
51+
expect(loadingItem).toBeInTheDocument()
52+
})
53+
54+
await testStep('Actual content loads and replaces fallback', async () => {
55+
await waitForElementToBeRemoved(() => screen.queryAllByText('loading'), {
56+
timeout: 5000,
57+
})
58+
})
59+
60+
await testStep('Actual ship details are rendered', async () => {
61+
const image = await screen.findByAltText('Dreadnought')
62+
if (!(image instanceof HTMLImageElement)) {
63+
throw new Error('Ship image not found')
64+
}
65+
expect(image.src).not.toContain('/img/fallback-ship.png')
66+
expect(image).not.toBe(fallbackImage)
67+
})
68+
69+
await testStep('Weapon items are displayed', async () => {
70+
const weaponItems = await screen.findAllByRole('listitem')
71+
expect(weaponItems.length).toBeGreaterThan(0)
72+
})
73+
}

0 commit comments

Comments
 (0)