Skip to content

Commit f3c70b5

Browse files
committed
01/01: add solution readme
1 parent 1b9c8b0 commit f3c70b5

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

exercises/01.sunsetting-jsdom/01.problem.break-jsdom/src/file-preview.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { test, expect } from 'vitest'
22
import { render, screen } from '@testing-library/react'
33

4-
test('displays the preview card', async () => {
4+
test('displays the preview card', () => {
55
// 🐨 Render the `FilePreview` component.
66
// 💰 render(<MyComponent />)
77
// Provide a new `File` instance as the value of the `file` prop.
Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
# Break JSDOM
22

3-
0. You have a tiny React app with Vite.
4-
1. Install Vitest and JSDOM, and write a basic integration test for your React component.
5-
1. Run it to see it _failing_ even on this simple test.
3+
I start with rendering the `<FilePreview />` component in my test:
4+
5+
```tsx add=1,4
6+
import { test, expect } from 'vitest'
7+
import { render, screen } from '@testing-library/react'
8+
import { FilePreview } from './file-review.js'
9+
10+
test('displays the preview card', () => {
11+
render(<FilePreview file={new File(['hello world'], 'file.txt')} />)
12+
})
13+
```
14+
15+
I am using the `render()` function from React Testing Library as usual. Since my component requires the `file` prop, I am creating a dummy file instance using the [`File` API](https://developer.mozilla.org/en-US/docs/Web/API/File/File) and providing it as the input to my component.
16+
17+
This test case doesn't involve any interaction with the component so I jump straight to the assertion step.
18+
19+
Here, two things have my interest:
20+
21+
1. The component must render the name of the previewed file (i.e. `file.txt`);
22+
1. The component must render the content of the previewed file.
23+
24+
I reflect those two expectations like so:
25+
26+
```tsx
27+
expect(screen.getByText('file.txt')).toBeTruthy()
28+
expect(screen.getByText('hello world')).toBeTruthy()
29+
```
30+
31+
Looks like the first test is done. All that's left is to run via `npm test` and... Oh, no.
32+
33+
```sh
34+
FAIL src/file-preview.test.tsx > displays the preview card
35+
TypeError: file.text is not a function
36+
❯ src/file-preview.tsx:7:8
37+
5|
38+
6| useEffect(() => {
39+
7| file.text().then(setPreviewText)
40+
| ^
41+
8| }, [file])
42+
```
43+
44+
😱 Something must be terribly wrong here...
45+
46+
Except it's not. The `<FilePreview />` component calls the [`Blob.prototype.text`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/text) (`File` inherits from `Blob`) method to retrieve the file's content correctly. The test is also exceptionally short to have any hidden pitfalls. **All except for one**.
47+
48+
Turns out, the `Blob.prototype.text` method isn't implemented in JSDOM. You can reproduce this in isolation as well by running this code:
49+
50+
```ts
51+
import { JSDOM } from 'jsdom'
52+
53+
const dom = new JSDOM()
54+
const blob = new dom.window.Blob(['hello world'])
55+
await blob.text()
56+
// TypeError: (intermediate value).text is not a function
57+
```
58+
59+
This is just one of the examples how introducing a custom, browser-like environment hurts your trust to your automated tests and the value you get from them. I really cannot stress this enough: _a valid test for a valid JavaScript code results in an error_. This test will run in Node.js as it will run in the browser, but not in JSDOM.

exercises/01.sunsetting-jsdom/01.solution.break-jsdom/src/file-preview.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { test, expect } from 'vitest'
22
import { render, screen } from '@testing-library/react'
33
import { FilePreview } from './file-preview.tsx'
44

5-
test('displays the preview card', async () => {
5+
test('displays the preview card', () => {
66
render(<FilePreview file={new File(['hello world'], 'file.txt')} />)
77

88
expect(screen.getByText('file.txt')).toBeTruthy()

0 commit comments

Comments
 (0)