Repository navigation
Expand file tree
/
Copy pathvitest.config.ts
More file actions
155 lines (148 loc) · 5.48 KB
/
Copy pathvitest.config.ts
File metadata and controls
155 lines (148 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import { cloudflareTest } from '@cloudflare/vitest-pool-workers';
import { existsSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { defineConfig } from 'vitest/config';
import { wasmBytes } from './scripts/vite-wasm-bytes.ts';
const root = import.meta.dirname;
/**
* Every compiled module in `dist/`, read from the directory rather than listed here.
*
* The list used to be written out, and adding `text.js` to the package broke the workers lane with
* `No such module` on every test rather than on the one that needed it. Miniflare takes an explicit
* list and does not resolve imports itself, so the list has to be complete; deriving it is the only
* way it stays that way.
*
* A missing `dist/` yields nothing instead of throwing. This runs when the config loads, so it ran
* for the node project too, and that project imports `src/ts/` and has no reason to build the
* package: the CI job that runs it builds only the wasm, so the whole lane died at startup with
* `ENOENT: scandir dist`. The workers lane cannot reach the empty case, because `test:workers`
* builds `dist/` before calling vitest.
*/
function compiledModules() {
if (!existsSync(join(root, 'dist'))) return [];
return readdirSync(join(root, 'dist'))
.filter((name) => name.endsWith('.js'))
.sort()
.map((name) => ({
type: 'ESModule' as const,
path: join(root, 'dist', name)
}));
}
/**
* The worker that holds the module, as a miniflare service.
*
* Not the pool's `main`: workerd refuses `WebAssembly.Module(bytes)` outright, so the module has to
* arrive as a `CompiledWasm` module in a worker's own bundle and be instantiated during that worker's
* startup. An auxiliary worker has its own startup, and is the shape a deployed tinyimg Worker has.
*/
const probe = {
name: 'tinyimg-probe',
compatibilityDate: '2026-08-22',
modulesRoot: root,
modules: [
{ type: 'ESModule' as const, path: join(root, 'tests/workers/fixtures/probe-worker.mjs') },
{ type: 'CompiledWasm' as const, path: join(root, 'bin/tinyimg.wasm') }
]
};
/**
* A second worker holding a second instance, for the tests that decode.
*
* Separate from the probe worker because an instance outlives every request it serves: a decode
* grows linear memory, and the probe worker's assertions about its initial page count would then
* depend on which test ran first.
*/
const codec = {
name: 'tinyimg-codec',
compatibilityDate: '2026-08-22',
modulesRoot: root,
modules: [
{ type: 'ESModule' as const, path: join(root, 'tests/workers/fixtures/codec-worker.mjs') },
{ type: 'CompiledWasm' as const, path: join(root, 'bin/tinyimg.wasm') }
]
};
/**
* A third worker running the shipped wrapper rather than the raw exports.
*
* It imports `dist/`, not `src/ts/`, and that is the point: the other two prove the C works inside
* workerd, and this proves the package a caller installs does. Miniflare takes an explicit module
* list and does not transpile, so the compiled output is also the only thing it could load.
*
* `bun run test:workers` builds `dist/` first for this reason.
*/
const wrapper = {
name: 'tinyimg-wrapper',
compatibilityDate: '2026-08-22',
modulesRoot: root,
modules: [
{
type: 'ESModule' as const,
path: join(root, 'tests/workers/fixtures/wrapper-worker.mjs')
},
...compiledModules(),
{ type: 'CompiledWasm' as const, path: join(root, 'bin/tinyimg.wasm') }
]
};
export default defineConfig({
test: {
coverage: {
/*
* The node lane is the only one coverage can measure, for two reasons that stack.
*
* This provider cannot collect anything under workerd: it reads counters through
* `node:inspector`, which workerd does not implement, so the workers lane reports 0%
* even for a function the test imports and calls directly. Measured, not assumed.
*
* Switching that lane to `istanbul`, which instruments at transform time and needs no
* inspector, lifts it to 1.87% of 481 statements and no further. Those tests reach the
* library through `env.PROBE`, `env.CODEC` and `env.WRAPPER`: service bindings to
* separate workers that miniflare instantiates from file paths, in their own isolates,
* with no transform applied. Nothing under test is in the instrumented module graph.
*
* So the workers lane is a behavior check on the package a caller installs, and it
* emits JUnit results and no coverage; see `test:workers:junit`. A 2% report on a lane
* that exercises the whole package end to end is worse than none.
*/
provider: 'v8',
reporter: ['text', 'lcov'],
reportsDirectory: './coverage/node',
include: ['src/ts/**/*.ts'],
exclude: ['**/*.d.ts'],
reportOnFailure: true
},
projects: [
{
plugins: [wasmBytes()],
test: {
name: 'node',
include: ['tests/node/*.spec.ts'],
environment: 'node',
// the spec files run in parallel and several of them are real image work:
// a lossless round trip of one fixture at four channel counts is seconds of
// transform, and the 5 second default was decided by whichever files happened
// to be running beside it
testTimeout: 30_000
}
},
{
plugins: [
wasmBytes(),
cloudflareTest({
miniflare: {
compatibilityDate: '2026-08-22',
serviceBindings: {
PROBE: 'tinyimg-probe',
CODEC: 'tinyimg-codec',
WRAPPER: 'tinyimg-wrapper'
},
workers: [probe, codec, wrapper]
}
})
],
test: {
name: 'workers',
include: ['tests/workers/*.spec.ts']
}
}
]
}
});