Skip to content

Commit 8861e53

Browse files
committed
02/05: add solution
1 parent ca8d5ea commit 8861e53

File tree

31 files changed

+472
-16
lines changed

31 files changed

+472
-16
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Multiple workspaces
2+
3+
The way you have Vitest configured right now will run _all tests_ using the Browser Mode. This may be not what you want, especially if you are using Vitest for unit testing or integration testing in Node.js in the same project that needs in-browser component tests as well.
4+
5+
You can fix this by introducing _different workspaces_ for differnt types of tests. In fact, I think this is just the right task for you...
6+
7+
👨‍💼 In this one, you will expand on the Vitest configuration to support running multiple types of tests in the same project. This will be a multi-step process to make sure you have the Vitest and TypeScript configured correctly for your tests.
8+
9+
🐨 First, update <InlineFile file="vite.config.ts">`vite.config.ts`</InlineFile> to list multiple [workspaces](https://main.vitest.dev/guide/workspace.html#configuration). Define one for unit tests and the other for component tests.
10+
11+
🐨 Next, rename <InlineFile file="tsconfig.test.json">`tsconfig.test.json`</InlineFile> to `tsconfig.test.browser.json`. This TypeScript configuration will apply only to the component tests now.
12+
13+
🐨 To have proper type-checking in unit tests, create a new <InlineFile file="tsconfig.test.unit.json">`tsconfig.test.unit.json`</InlineFile> file and list there the properties necessary for the unit tests. You can use this as an example:
14+
15+
```json filename=tsconfig.test.unit.json
16+
{
17+
"extends": "./tsconfig.base.json",
18+
"include": ["**/*.test.ts*"],
19+
"exclude": ["**/*.browser.test.ts*"],
20+
"compilerOptions": {
21+
"target": "esnext",
22+
"module": "preserve",
23+
"types": ["node", "vitest/globals"]
24+
}
25+
}
26+
```
27+
28+
🐨 You might've noticed that this config relies on `@types/node` to expose Node.js type in unit tests, but that dependency is missing! Install `@types/node` as a dev dependency to fix that.
29+
30+
🐨 Finally, rename the existing `file-preview.test.tsx` component test to `file-preview.browser.test.tsx` to be picked up by the proper workspace in Vitest.
31+
32+
See you on the other side once you're done to go through each step in more detail.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite App</title>
8+
<link rel="preconnect" href="https://fonts.googleapis.com" />
9+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10+
</head>
11+
<body>
12+
<div id="root"></div>
13+
<script type="module" src="/src/main.tsx"></script>
14+
</body>
15+
</html>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"type": "module",
3+
"name": "exercises_02.vitest-browser-mode_05.problem.multiple-workspaces",
4+
"scripts": {
5+
"dev": "vite",
6+
"test": "vitest"
7+
},
8+
"dependencies": {
9+
"react": "^19.0.0",
10+
"react-dom": "^19.0.0"
11+
},
12+
"devDependencies": {
13+
"@testing-library/dom": "^10.4.0",
14+
"@testing-library/react": "^16.1.0",
15+
"@types/react": "^19.0.6",
16+
"@types/react-dom": "^19.0.3",
17+
"@vitejs/plugin-react": "^4.3.4",
18+
"@vitest/browser": "^3.0.0-beta.4",
19+
"autoprefixer": "^10.4.20",
20+
"playwright": "^1.49.1",
21+
"postcss": "^8.4.49",
22+
"tailwindcss": "^3.4.17",
23+
"vite": "^6.0.7",
24+
"vitest": "^3.0.0-beta.4"
25+
}
26+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { useState } from 'react'
2+
import { FilePreview } from './file-preview.jsx'
3+
4+
export function App() {
5+
const [file, setFile] = useState<File>()
6+
7+
return (
8+
<div>
9+
{file ? (
10+
<div className="flex flex-col items-center">
11+
<FilePreview file={file} />
12+
<button
13+
className="mt-10 rounded-full bg-slate-800 px-6 py-2 text-sm font-bold text-white hover:bg-slate-600"
14+
onClick={() => setFile(undefined)}
15+
>
16+
Preview another file
17+
</button>
18+
</div>
19+
) : (
20+
<div className="rounded-md border border-slate-200 bg-white p-4 shadow-lg shadow-slate-200">
21+
<input
22+
type="file"
23+
name="file"
24+
required
25+
className="text-sm font-medium"
26+
onChange={(event) => {
27+
const [selectedFile] = event.currentTarget.files || []
28+
29+
if (selectedFile) {
30+
setFile(selectedFile)
31+
}
32+
}}
33+
/>
34+
</div>
35+
)}
36+
</div>
37+
)
38+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { page } from '@vitest/browser/context'
2+
import { render } from 'vitest-browser-react'
3+
import { FilePreview } from './file-preview.tsx'
4+
5+
test('displays the preview card', async () => {
6+
render(<FilePreview file={new File(['hello world'], 'file.txt')} />)
7+
8+
await expect.element(page.getByText('file.txt')).toBeVisible()
9+
await expect.element(page.getByText('hello world')).toBeVisible()
10+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useEffect, useState } from 'react'
2+
3+
export function FilePreview({ file }: { file: File }) {
4+
const [previewText, setPreviewText] = useState<string>()
5+
6+
useEffect(() => {
7+
file.text().then(setPreviewText)
8+
}, [file])
9+
10+
return (
11+
<div>
12+
<div className="w-full max-w-2xl overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg shadow-slate-200">
13+
<p className="border-b border-slate-200 bg-slate-50 px-4 py-2 font-bold text-slate-600">
14+
{file.name}
15+
</p>
16+
<pre className="max-h-[28ch] overflow-scroll p-4">{previewText}</pre>
17+
</div>
18+
</div>
19+
)
20+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap');
2+
3+
@tailwind base;
4+
@tailwind components;
5+
@tailwind utilities;
6+
7+
html {
8+
@apply flex size-full items-center justify-center bg-slate-100 p-10;
9+
10+
font-family:
11+
'DM Sans',
12+
system-ui,
13+
-apple-system,
14+
BlinkMacSystemFont,
15+
'Segoe UI',
16+
Roboto,
17+
Oxygen,
18+
Ubuntu,
19+
Cantarell,
20+
'Open Sans',
21+
'Helvetica Neue',
22+
sans-serif;
23+
font-style: normal;
24+
font-optical-sizing: auto;
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { StrictMode } from 'react'
2+
import { createRoot } from 'react-dom/client'
3+
import './index.css'
4+
import { App } from './app.jsx'
5+
6+
createRoot(document.getElementById('root')!).render(
7+
<StrictMode>
8+
<App />
9+
</StrictMode>,
10+
)

0 commit comments

Comments
 (0)