Skip to content

Commit 6800b71

Browse files
committed
03/02: finish the solution
1 parent 1499940 commit 6800b71

File tree

5 files changed

+54
-25
lines changed

5 files changed

+54
-25
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ data.db
1111
**/tsconfig.tsbuildinfo
1212
**/*.tsbuildinfo
1313
__screenshots__
14+
*.sqlite
1415

1516
# in a real app you'd want to not commit the .env
1617
# file as well, but since this is for a workshop

exercises/03.context/02.solution.automatic-fixtures/src/example.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import { test } from '../test-extend'
2+
import { queryUser } from './query-user'
23

34
test('throws if the user is not found', async () => {
4-
const { queryUser } = await import('./query-user')
5-
65
await expect(queryUser('abc-123')).resolves.toBeUndefined()
76
})
87

98
test('returns the user by id', async ({ createMockDatabase }) => {
10-
const { queryUser } = await import('./query-user')
11-
129
await createMockDatabase((db, done) => {
1310
db.run(
1411
'INSERT INTO users (id, name) VALUES (?, ?)',

exercises/03.context/02.solution.automatic-fixtures/src/query-user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { client } from './db'
1+
import { client } from './database'
22

33
export interface User {
44
id: string

exercises/03.context/02.solution.automatic-fixtures/test-extend.ts

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,74 @@
1+
import * as fs from 'node:fs'
2+
import * as path from 'node:path'
13
import { test as testBase } from 'vitest'
24
import sqlite3, { type Database } from 'sqlite3'
5+
import * as databaseModule from './src/database'
36

47
interface Fixtures {
58
createMockDatabase: (
6-
init: (database: Database, done: () => void) => void,
9+
seed: (database: Database, handle: CallbackHandle) => void,
710
) => Promise<void>
811
}
912

13+
type CallbackHandle = (error?: Error | null, ...args: Array<any>) => void
14+
15+
function toPromise<T>(init: (handle: CallbackHandle) => T): Promise<T> {
16+
return new Promise<T>((resolve, reject) => {
17+
const result = init((error) => {
18+
if (error) {
19+
return reject(error)
20+
}
21+
resolve(result)
22+
})
23+
})
24+
}
25+
1026
export const test = testBase.extend<Fixtures>({
1127
createMockDatabase: [
12-
async ({ task }, use) => {
13-
const db = new sqlite3.Database(':memory:')
28+
async ({ task, onTestFinished }, use) => {
29+
const dbFile = `${task.file.filepath}-${task.id}.sqlite`
30+
31+
if (fs.existsSync(dbFile)) {
32+
await fs.promises.rm(dbFile)
33+
}
34+
35+
const mockDatabase = await toPromise((handle) => {
36+
return new sqlite3.Database(dbFile, handle)
37+
})
1438

15-
vi.doMock(import('./src/db'), async (importOriginal) => {
16-
const original = await importOriginal()
17-
const mockClient = new original.DatabaseClient(db)
39+
onTestFinished(async ({ task }) => {
40+
await toPromise((handle) => mockDatabase.close(handle))
1841

19-
return {
20-
...original,
21-
client: mockClient,
42+
if (task.type !== 'test') {
43+
return
44+
}
45+
46+
if (task.result?.state === 'pass') {
47+
await fs.promises.rm(dbFile)
48+
} else {
49+
task.result?.errors?.push({
50+
name: 'Mock database',
51+
message: 'See the database state:',
52+
codeFrame: path.relative(process.cwd(), dbFile),
53+
})
2254
}
2355
})
2456

25-
await new Promise<void>((resolve) => {
26-
db.serialize(() => {
27-
db.run('CREATE TABLE users (id TEXT, name TEXT)', resolve)
28-
})
57+
const clientSpy = vi
58+
.spyOn(databaseModule, 'client', 'get')
59+
.mockReturnValue(new databaseModule.DatabaseClient(mockDatabase))
60+
61+
await toPromise((handle) => {
62+
mockDatabase.run('CREATE TABLE users (id TEXT, name TEXT)', handle)
2963
})
3064

31-
await use((initDatabase) => {
32-
return new Promise((resolve) => {
33-
initDatabase(db, resolve)
65+
await use((seed) => {
66+
return toPromise((handle) => {
67+
seed(mockDatabase, handle)
3468
})
3569
})
3670

37-
await new Promise<void>((resolve) => {
38-
db.close(() => resolve())
39-
})
40-
vi.doUnmock(import('./src/db'))
71+
clientSpy.mockRestore()
4172
},
4273
{
4374
auto: true,

0 commit comments

Comments
 (0)