Skip to content

Commit a160138

Browse files
committed
03/01: add solution code
1 parent 14a4b5a commit a160138

File tree

7 files changed

+95
-3
lines changed

7 files changed

+95
-3
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
11
# Custom fixtures
2+
3+
## Curiosities
4+
5+
- `use` is _always async_! Await it.
6+
- Fixtures can be anything: values and functions.
7+
- Test context object _must_ be destructed (`test(n, ({ like, so }))`). Vitest (and Playwright) use the getters to know if you've referenced fixtures to initialize them lazily.
8+
9+
## Important
10+
11+
- Do NOT put values you use for input into fixtures.
12+
13+
```ts
14+
test('...', ({ cart }) => {
15+
// What is `cart`?? Why does it equal to `something` in this case? Idk.
16+
expect(transform(cart)).toBe(something)
17+
})
18+
```
19+
20+
This is a _bad_ idea. Your test isn't isolated and depends on the fixture. Besides, you don't see the input so you cannot reason about the expected output. Just don't do this.
21+
22+
_Instead_, either create fixtures _inline_ in the test, or use helper fixtures to abstract complex creation logic (but still expose input control through arguments).
23+
24+
- I think you can put a value into a fixture if it's a _domain-specific value_ that is _never going to change_. Otherwise, you're better off.

exercises/03.context/01.solution.custom-fixtures/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"build": "vite build"
88
},
99
"devDependencies": {
10+
"@faker-js/faker": "^9.6.0",
1011
"vite": "^6.0.7",
1112
"vitest": "^3.0.5"
1213
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export type Cart = Array<CartItem>
2+
3+
export interface CartItem {
4+
id: string
5+
name: string
6+
price: number
7+
quantity: number
8+
}
9+
10+
export function getTotalPrice(cart: Cart): number {
11+
return cart.reduce((total, item) => {
12+
return total + item.price * item.quantity
13+
}, 0)
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { test } from '../test-extend'
2+
import { getTotalPrice } from './cart-utils'
3+
4+
test('returns the total price for the cart', ({ createMockCart }) => {
5+
const cart = createMockCart([
6+
{ price: 5, quantity: 10 },
7+
{ price: 8, quantity: 4 },
8+
])
9+
10+
expect(getTotalPrice(cart)).toBe(82)
11+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { test as testBase } from 'vitest'
2+
import { faker } from '@faker-js/faker'
3+
import type { Cart, CartItem } from './src/cart-utils'
4+
5+
interface Fixtures {
6+
createMockCart: (items: Array<Partial<CartItem>>) => Cart
7+
}
8+
9+
export const test = testBase.extend<Fixtures>({
10+
async createMockCart({}, use) {
11+
await use((items) => {
12+
return items.map((item) => ({
13+
id: faker.string.ulid(),
14+
name: faker.commerce.productName(),
15+
price: faker.number.int({ min: 1, max: 25 }),
16+
quantity: faker.number.int({ min: 1, max: 10 }),
17+
...item,
18+
}))
19+
})
20+
},
21+
})

exercises/03.context/01.solution.custom-fixtures/tsconfig.test.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"extends": "./tsconfig.app.json",
3-
"include": ["src/**/*", "src/**/*.test.ts*"],
3+
"include": ["test-extend.ts", "src/**/*", "src/**/*.test.ts*"],
44
"exclude": [],
55
"compilerOptions": {
66
"types": ["vitest/globals"]

package-lock.json

Lines changed: 24 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)