@weft-js/cli 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -14
- package/bin/weft.mjs +8 -1
- package/docs/async.md +16 -6
- package/docs/browser.md +22 -8
- package/docs/config.md +39 -9
- package/docs/core.md +30 -0
- package/docs/deploy.md +108 -0
- package/docs/design.md +12 -3
- package/docs/entrypoints.md +79 -0
- package/docs/fonts.md +12 -2
- package/docs/icons.md +13 -7
- package/docs/lists.md +3 -1
- package/docs/meta.md +13 -3
- package/docs/plugins.md +32 -9
- package/docs/props.md +13 -2
- package/docs/reactivity.md +26 -0
- package/docs/rules.md +19 -12
- package/docs/rust.md +47 -17
- package/docs/start-short.md +3 -2
- package/docs/start.md +226 -52
- package/docs/state.md +33 -7
- package/docs/style.md +31 -8
- package/docs/surface.md +61 -15
- package/docs/testing.md +15 -5
- package/docs/theme.md +182 -0
- package/docs/ui-state.md +19 -6
- package/docs/verify.md +13 -0
- package/package.json +13 -4
- package/src/add/config.mjs +93 -0
- package/src/add/errors.mjs +2 -0
- package/src/add/setup.mjs +88 -0
- package/src/add-rust.mjs +82 -27
- package/src/add.mjs +209 -181
- package/src/agents-md.mjs +144 -43
- package/src/alias.mjs +16 -5
- package/src/audit/page.mjs +313 -0
- package/src/audit/report.mjs +69 -0
- package/src/audit/utils.mjs +5 -0
- package/src/audit.mjs +174 -188
- package/src/browser/cli.mjs +24 -5
- package/src/browser/client.mjs +189 -25
- package/src/browser/commands.mjs +166 -51
- package/src/catalog/audit.mjs +129 -0
- package/src/catalog/auth.mjs +40 -0
- package/src/catalog/compiler.mjs +337 -0
- package/src/catalog/contracts.mjs +18 -0
- package/src/catalog/database.mjs +52 -0
- package/src/catalog/deploy.mjs +117 -0
- package/src/catalog/design.mjs +159 -0
- package/src/catalog/forms.mjs +25 -0
- package/src/catalog/hydration.mjs +29 -0
- package/src/catalog/icons.mjs +24 -0
- package/src/catalog/media.mjs +163 -0
- package/src/catalog/metadata.mjs +116 -0
- package/src/catalog/plugins.mjs +228 -0
- package/src/catalog/realtime.mjs +195 -0
- package/src/catalog/rust.mjs +75 -0
- package/src/catalog/server-functions.mjs +92 -0
- package/src/catalog/state.mjs +39 -0
- package/src/catalog/style-groups.mjs +54 -0
- package/src/catalog/tests.mjs +127 -0
- package/src/catalog/text.mjs +200 -0
- package/src/catalog/ui-state.mjs +42 -0
- package/src/catalog.mjs +68 -444
- package/src/check/runtime.mjs +280 -0
- package/src/check.mjs +199 -207
- package/src/cli/authoring.mjs +213 -0
- package/src/cli/project.mjs +302 -0
- package/src/cli.mjs +228 -224
- package/src/config.mjs +1 -1
- package/src/contributions.mjs +75 -25
- package/src/db-layer.mjs +13 -5
- package/src/deploy/cdn.mjs +142 -0
- package/src/deploy/files.mjs +266 -0
- package/src/deploy/fit.mjs +166 -0
- package/src/deploy/hosts.mjs +126 -0
- package/src/deploy/index/cli.mjs +20 -0
- package/src/deploy/index/environment.mjs +69 -0
- package/src/deploy/index/steps.mjs +87 -0
- package/src/deploy/index.mjs +387 -0
- package/src/deploy/needs.mjs +149 -0
- package/src/design-checks/accessible-names.mjs +62 -0
- package/src/design-checks/contrast.mjs +43 -0
- package/src/design-checks/csp.mjs +60 -0
- package/src/design-checks/files.mjs +59 -0
- package/src/design-checks/heading-links.mjs +61 -0
- package/src/design-checks/interaction.mjs +65 -0
- package/src/design-checks/jsx.mjs +67 -0
- package/src/design-checks/layout-values.mjs +68 -0
- package/src/design-checks/native-controls.mjs +48 -0
- package/src/design-checks/outline.mjs +39 -0
- package/src/design-checks/reporter.mjs +37 -0
- package/src/design-checks/rules.mjs +274 -0
- package/src/design-checks/values.mjs +262 -0
- package/src/design-checks.mjs +10 -400
- package/src/diag.mjs +32 -8
- package/src/docs.mjs +138 -42
- package/src/doctor.mjs +20 -8
- package/src/files.mjs +18 -5
- package/src/fix.mjs +10 -2
- package/src/gate/after.mjs +40 -0
- package/src/gate/before.mjs +54 -0
- package/src/gate/classify.mjs +72 -0
- package/src/gate/mutation.mjs +209 -0
- package/src/gate/resolve-cases.mjs +22 -0
- package/src/gate/result.mjs +63 -0
- package/src/gate/run.mjs +75 -0
- package/src/gate.mjs +104 -202
- package/src/infer/box-props.cjs +140 -0
- package/src/infer/core-boxes.cjs +46 -0
- package/src/infer/derived-writes.cjs +95 -0
- package/src/infer/engine/checks.cjs +193 -0
- package/src/infer/engine/flow.cjs +293 -0
- package/src/infer/engine/report.cjs +158 -0
- package/src/infer/engine/utils.cjs +15 -0
- package/src/infer/engine.cjs +108 -368
- package/src/infer/facts/sites.cjs +114 -0
- package/src/infer/facts.cjs +210 -117
- package/src/infer/hosts.cjs +69 -22
- package/src/infer/lsp.mjs +149 -40
- package/src/infer/session.cjs +73 -17
- package/src/infer/shadow.cjs +13 -5
- package/src/infer/worker.cjs +57 -9
- package/src/jsx-scan.mjs +63 -21
- package/src/load-config/schema.mjs +281 -0
- package/src/load-config.mjs +144 -116
- package/src/map.mjs +93 -26
- package/src/mcp/browser-tools.mjs +155 -0
- package/src/mcp.mjs +147 -69
- package/src/meta-table.mjs +43 -8
- package/src/mutate.mjs +120 -36
- package/src/plugin-checks.mjs +52 -23
- package/src/plugins.mjs +125 -39
- package/src/project.mjs +170 -79
- package/src/props-checks.mjs +24 -6
- package/src/props-listener.mjs +27 -9
- package/src/react-checks.mjs +35 -4
- package/src/server-state-checks.mjs +34 -0
- package/src/share-checks.mjs +121 -37
- package/src/site.mjs +33 -6
- package/src/slots.mjs +104 -19
- package/src/start/build.mjs +116 -0
- package/src/start/routes.mjs +38 -0
- package/src/start.mjs +194 -92
- package/src/state-checks/core-state.mjs +223 -0
- package/src/state-checks/modules.mjs +17 -0
- package/src/state-checks/scan.mjs +232 -0
- package/src/state-checks/server-graph.mjs +65 -0
- package/src/state-checks.mjs +109 -133
- package/src/style/find.mjs +121 -0
- package/src/style.mjs +133 -127
- package/src/surface-checks.mjs +212 -46
- package/src/tailwind.mjs +5 -4
- package/src/tasks.mjs +189 -27
- package/src/test-rules/context.mjs +109 -0
- package/src/test-rules/file-rules.mjs +279 -0
- package/src/test-rules/rule-helpers.mjs +244 -0
- package/src/test-rules/syntax.mjs +223 -0
- package/src/test-rules/test-rules.mjs +127 -0
- package/src/testdiff.mjs +94 -32
- package/src/tests.mjs +31 -483
- package/src/text-checks.mjs +229 -69
- package/src/tokens.mjs +12 -4
- package/src/trust/scan.mjs +95 -0
- package/src/trust.mjs +214 -102
- package/src/weft.mjs +41 -9
- package/src/workspace.mjs +96 -19
- package/ts-plugin/context.js +57 -0
- package/ts-plugin/index.js +4 -124
- package/ts-plugin/mapping.js +65 -0
- package/ts-plugin/proxy.js +144 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { join, relative } from 'node:path'
|
|
3
|
+
import { diagnostic } from '../diag.mjs'
|
|
4
|
+
import { apply, changedLines, mutants as makeMutants, sample, suggest } from '../mutate.mjs'
|
|
5
|
+
import { isTestFile } from '../tests.mjs'
|
|
6
|
+
import { copyProject, removeCopy, runVitest, writeFiles } from '../workspace.mjs'
|
|
7
|
+
|
|
8
|
+
export async function mutate({
|
|
9
|
+
options,
|
|
10
|
+
root,
|
|
11
|
+
source,
|
|
12
|
+
testFiles,
|
|
13
|
+
importsOf,
|
|
14
|
+
code,
|
|
15
|
+
posix,
|
|
16
|
+
isSupport,
|
|
17
|
+
maxMutants,
|
|
18
|
+
byKey,
|
|
19
|
+
result,
|
|
20
|
+
log,
|
|
21
|
+
concurrency,
|
|
22
|
+
budgetSec,
|
|
23
|
+
started,
|
|
24
|
+
after,
|
|
25
|
+
bin,
|
|
26
|
+
compileError,
|
|
27
|
+
allowed,
|
|
28
|
+
diagnostics,
|
|
29
|
+
}) {
|
|
30
|
+
// Mutation: the changed source lines (or, with no source change, the source files the tests import).
|
|
31
|
+
if (options.mutation !== false) {
|
|
32
|
+
const targets = mutationTargets({
|
|
33
|
+
root,
|
|
34
|
+
source,
|
|
35
|
+
testFiles,
|
|
36
|
+
importsOf,
|
|
37
|
+
code,
|
|
38
|
+
posix,
|
|
39
|
+
isSupport,
|
|
40
|
+
result,
|
|
41
|
+
})
|
|
42
|
+
const all = targets.flatMap((t) => makeMutants(t.text, t.rel, t.lines))
|
|
43
|
+
const list = sample(all, maxMutants)
|
|
44
|
+
result.mutants.generated = all.length
|
|
45
|
+
result.mutants.sampled = list.length < all.length
|
|
46
|
+
const passing = [...byKey.values()].filter((t) => t.after === 'passed')
|
|
47
|
+
const files = [...new Set(passing.map((t) => t.file))]
|
|
48
|
+
if (list.length && files.length) {
|
|
49
|
+
log(
|
|
50
|
+
`gate: ${list.length}${result.mutants.sampled ? ` of ${all.length}` : ''} mutants on ${targets.length} files, ${concurrency} at a time, ${budgetSec}s budget`,
|
|
51
|
+
)
|
|
52
|
+
const outcomes = await runMutants({
|
|
53
|
+
root,
|
|
54
|
+
options,
|
|
55
|
+
targets,
|
|
56
|
+
started,
|
|
57
|
+
budgetSec,
|
|
58
|
+
after,
|
|
59
|
+
list,
|
|
60
|
+
result,
|
|
61
|
+
files,
|
|
62
|
+
bin,
|
|
63
|
+
concurrency,
|
|
64
|
+
})
|
|
65
|
+
recordMutants({ outcomes, result, compileError, passing, allowed, diagnostics })
|
|
66
|
+
} else if (!list.length) result.notes.push('no mutants on the changed lines')
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function mutationTargets({ root, source, testFiles, importsOf, code, posix, isSupport, result }) {
|
|
71
|
+
// Only code the changed tests can reach (runtime imports): a mutant nothing runs survives by definition.
|
|
72
|
+
const reach = (limit) => {
|
|
73
|
+
const seen = new Set()
|
|
74
|
+
const walk = (abs, depth) => {
|
|
75
|
+
if (seen.has(abs) || depth > limit || !existsSync(abs)) return
|
|
76
|
+
seen.add(abs)
|
|
77
|
+
for (const p of importsOf(abs, readFileSync(abs, 'utf8'))) walk(p, depth + 1)
|
|
78
|
+
}
|
|
79
|
+
for (const f of testFiles) walk(join(root, f), 0)
|
|
80
|
+
return seen
|
|
81
|
+
}
|
|
82
|
+
const reachable = reach(12)
|
|
83
|
+
const unreached = source
|
|
84
|
+
.filter((c) => c.after != null && code(c.rel) && !reachable.has(join(root, c.rel)))
|
|
85
|
+
.map((c) => c.rel)
|
|
86
|
+
if (unreached.length)
|
|
87
|
+
result.notes.push(`not mutated (no changed test imports them): ${unreached.join(', ')}`)
|
|
88
|
+
let targets = source
|
|
89
|
+
.filter((c) => c.after != null && reachable.has(join(root, c.rel)))
|
|
90
|
+
.map((c) => ({ rel: c.rel, text: c.after, lines: changedLines(c.before, c.after) }))
|
|
91
|
+
if (!source.length) {
|
|
92
|
+
targets = [...reach(3)]
|
|
93
|
+
.map((abs) => posix(relative(root, abs)))
|
|
94
|
+
.filter(
|
|
95
|
+
(rel) =>
|
|
96
|
+
!isTestFile(rel) &&
|
|
97
|
+
code(rel) &&
|
|
98
|
+
!isSupport(rel) &&
|
|
99
|
+
!rel.startsWith('..') &&
|
|
100
|
+
!rel.includes('node_modules'),
|
|
101
|
+
)
|
|
102
|
+
.map((rel) => {
|
|
103
|
+
const text = readFileSync(join(root, rel), 'utf8')
|
|
104
|
+
return { rel, text, lines: changedLines(null, text) }
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
return targets
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function runMutants({
|
|
111
|
+
root,
|
|
112
|
+
options,
|
|
113
|
+
targets,
|
|
114
|
+
started,
|
|
115
|
+
budgetSec,
|
|
116
|
+
after,
|
|
117
|
+
list,
|
|
118
|
+
result,
|
|
119
|
+
files,
|
|
120
|
+
bin,
|
|
121
|
+
concurrency,
|
|
122
|
+
}) {
|
|
123
|
+
const texts = Object.fromEntries(targets.map((t) => [t.rel, t.text]))
|
|
124
|
+
const deadline = started + budgetSec * 1000 + after.ms
|
|
125
|
+
const timeoutMs = Math.max(15_000, after.ms * 3)
|
|
126
|
+
const queue = [...list]
|
|
127
|
+
const outcomes = []
|
|
128
|
+
const worker = async (i) => {
|
|
129
|
+
const dir = copyProject(root, { exclude: options.exclude, id: `mutant-${i}` })
|
|
130
|
+
try {
|
|
131
|
+
for (let m; (m = queue.shift());) {
|
|
132
|
+
if (performance.now() > deadline) {
|
|
133
|
+
result.mutants.sampled = true
|
|
134
|
+
queue.length = 0
|
|
135
|
+
break
|
|
136
|
+
}
|
|
137
|
+
writeFiles(dir, { [m.file]: apply(texts[m.file], m) })
|
|
138
|
+
const res = await runVitest(dir, files, { bin, config: options.config, timeoutMs })
|
|
139
|
+
writeFiles(dir, { [m.file]: texts[m.file] })
|
|
140
|
+
outcomes.push({ m, res })
|
|
141
|
+
}
|
|
142
|
+
} finally {
|
|
143
|
+
removeCopy(dir)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, list.length) }, (_, i) => worker(i)))
|
|
147
|
+
return outcomes
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function recordMutants({ outcomes, result, compileError, passing, allowed, diagnostics }) {
|
|
151
|
+
for (const { m, res } of outcomes) {
|
|
152
|
+
result.mutants.run++
|
|
153
|
+
if (res.timedOut) {
|
|
154
|
+
result.mutants.timedOut++
|
|
155
|
+
result.mutants.killed++
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
const loadOnly = res.tests.size === 0 && res.loadErrors.size > 0
|
|
159
|
+
if (loadOnly && [...res.loadErrors.values()].some(compileError)) {
|
|
160
|
+
result.mutants.invalid++
|
|
161
|
+
continue
|
|
162
|
+
}
|
|
163
|
+
let killed = false
|
|
164
|
+
for (const t of passing) {
|
|
165
|
+
const st = res.loadErrors.has(t.file)
|
|
166
|
+
? 'failed'
|
|
167
|
+
: res.tests.get(`${t.file}::${t.name}`)?.status
|
|
168
|
+
if (st && st !== 'passed') {
|
|
169
|
+
t.kills++
|
|
170
|
+
killed = true
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (killed) result.mutants.killed++
|
|
174
|
+
else {
|
|
175
|
+
result.mutants.survived++
|
|
176
|
+
result.survivors.push({
|
|
177
|
+
file: m.file,
|
|
178
|
+
line: m.line,
|
|
179
|
+
column: m.column,
|
|
180
|
+
op: m.op,
|
|
181
|
+
original: m.original.slice(0, 80),
|
|
182
|
+
replacement: m.replacement,
|
|
183
|
+
suggestion: suggest(m),
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const valid = result.mutants.run - result.mutants.invalid
|
|
188
|
+
if (valid > 0)
|
|
189
|
+
for (const t of passing) {
|
|
190
|
+
if (t.kills > 0 || t.before === 'passed') continue
|
|
191
|
+
if (allowed('T011', t.file, t.line)) {
|
|
192
|
+
result.notes.push(`T011 allowed on "${t.name}"`)
|
|
193
|
+
continue
|
|
194
|
+
}
|
|
195
|
+
const partial = result.mutants.sampled
|
|
196
|
+
diagnostics.push(
|
|
197
|
+
diagnostic({
|
|
198
|
+
code: 'T011',
|
|
199
|
+
severity: partial ? 'warning' : 'error',
|
|
200
|
+
file: t.file,
|
|
201
|
+
span: [t.line, 1, t.line, 1],
|
|
202
|
+
why: `"${t.name}" killed none of the ${valid} mutants of the changed lines${partial ? ` (a sample of ${result.mutants.generated})` : ''}: it would still pass if that code were wrong`,
|
|
203
|
+
help: result.survivors[0]
|
|
204
|
+
? `Assert what the changed code computes. For example: ${result.survivors[0].suggestion}`
|
|
205
|
+
: 'Assert what the changed code computes',
|
|
206
|
+
}),
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function resolver(testFiles, cases) {
|
|
2
|
+
const resolveCases = (res) => {
|
|
3
|
+
// Static names map 1:1; results nobody claimed belong to the file's dynamic (`.each`) cases.
|
|
4
|
+
const out = new Map()
|
|
5
|
+
for (const f of testFiles) {
|
|
6
|
+
const mine = cases.filter((c) => c.file === f)
|
|
7
|
+
const keys = [...res.tests.keys()].filter((k) => k.startsWith(`${f}::`))
|
|
8
|
+
for (const c of mine.filter((x) => !x.dynamic))
|
|
9
|
+
out.set(
|
|
10
|
+
`${f}::${c.name}`,
|
|
11
|
+
res.loadErrors.has(f)
|
|
12
|
+
? { status: 'failed', message: res.loadErrors.get(f), load: true }
|
|
13
|
+
: (res.tests.get(`${f}::${c.name}`) ?? { status: 'missing' }),
|
|
14
|
+
)
|
|
15
|
+
if (mine.some((c) => c.dynamic))
|
|
16
|
+
for (const k of keys) if (!out.has(k)) out.set(k, res.tests.get(k))
|
|
17
|
+
}
|
|
18
|
+
return out
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return resolveCases
|
|
22
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { sortDiagnostics, summarize } from '../diag.mjs'
|
|
2
|
+
|
|
3
|
+
export function makeResult({
|
|
4
|
+
root,
|
|
5
|
+
options,
|
|
6
|
+
tests,
|
|
7
|
+
support,
|
|
8
|
+
source,
|
|
9
|
+
diagnostics,
|
|
10
|
+
budgetSec,
|
|
11
|
+
started,
|
|
12
|
+
}) {
|
|
13
|
+
const result = {
|
|
14
|
+
version: 1,
|
|
15
|
+
ok: true,
|
|
16
|
+
root,
|
|
17
|
+
base: options.changes ? null : (options.base ?? 'HEAD'),
|
|
18
|
+
files: {
|
|
19
|
+
tests: tests.map((c) => c.rel),
|
|
20
|
+
support: support.map((c) => c.rel),
|
|
21
|
+
source: source.map((c) => c.rel),
|
|
22
|
+
},
|
|
23
|
+
tests: [],
|
|
24
|
+
mutants: {
|
|
25
|
+
generated: 0,
|
|
26
|
+
run: 0,
|
|
27
|
+
killed: 0,
|
|
28
|
+
survived: 0,
|
|
29
|
+
timedOut: 0,
|
|
30
|
+
invalid: 0,
|
|
31
|
+
sampled: false,
|
|
32
|
+
budgetSec,
|
|
33
|
+
},
|
|
34
|
+
survivors: [],
|
|
35
|
+
diagnostics,
|
|
36
|
+
summary: null,
|
|
37
|
+
notes: [],
|
|
38
|
+
ms: 0,
|
|
39
|
+
}
|
|
40
|
+
const finish = () => {
|
|
41
|
+
sortDiagnostics(diagnostics)
|
|
42
|
+
// Each test's verdict: it ran green on the change, failed before it (when there was a before), and no error
|
|
43
|
+
// diagnostic falls inside it.
|
|
44
|
+
for (const t of result.tests) {
|
|
45
|
+
t.codes = diagnostics
|
|
46
|
+
.filter(
|
|
47
|
+
(d) =>
|
|
48
|
+
d.severity === 'error' &&
|
|
49
|
+
d.file === t.file &&
|
|
50
|
+
d.span[0] >= t.line &&
|
|
51
|
+
d.span[0] <= t.end,
|
|
52
|
+
)
|
|
53
|
+
.map((d) => d.code)
|
|
54
|
+
t.accepted = t.after === 'passed' && t.before !== 'passed' && !t.codes.length
|
|
55
|
+
}
|
|
56
|
+
result.summary = { changedTests: result.tests.length, ...summarize(diagnostics) }
|
|
57
|
+
result.ok = result.summary.errors === 0 && result.tests.every((t) => t.accepted)
|
|
58
|
+
result.ms = Math.round(performance.now() - started)
|
|
59
|
+
return result
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { result, finish }
|
|
63
|
+
}
|
package/src/gate/run.mjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { runVitest, vitestBin } from '../workspace.mjs'
|
|
2
|
+
import { afterRun } from './after.mjs'
|
|
3
|
+
import { beforeRun } from './before.mjs'
|
|
4
|
+
import { mutate } from './mutation.mjs'
|
|
5
|
+
|
|
6
|
+
export async function runGate({
|
|
7
|
+
root,
|
|
8
|
+
options,
|
|
9
|
+
cases,
|
|
10
|
+
testFiles,
|
|
11
|
+
log,
|
|
12
|
+
result,
|
|
13
|
+
source,
|
|
14
|
+
allowed,
|
|
15
|
+
diagnostics,
|
|
16
|
+
importsOf,
|
|
17
|
+
code,
|
|
18
|
+
posix,
|
|
19
|
+
isSupport,
|
|
20
|
+
maxMutants,
|
|
21
|
+
concurrency,
|
|
22
|
+
budgetSec,
|
|
23
|
+
started,
|
|
24
|
+
compileError,
|
|
25
|
+
}) {
|
|
26
|
+
const bin = vitestBin(root)
|
|
27
|
+
const run = (dir, files) =>
|
|
28
|
+
runVitest(dir, files, { bin, config: options.config, timeoutMs: 180_000 })
|
|
29
|
+
|
|
30
|
+
const { after, resolveCases, byKey } = await afterRun({
|
|
31
|
+
cases,
|
|
32
|
+
testFiles,
|
|
33
|
+
log,
|
|
34
|
+
root,
|
|
35
|
+
options,
|
|
36
|
+
run,
|
|
37
|
+
result,
|
|
38
|
+
})
|
|
39
|
+
await beforeRun({
|
|
40
|
+
source,
|
|
41
|
+
options,
|
|
42
|
+
log,
|
|
43
|
+
root,
|
|
44
|
+
run,
|
|
45
|
+
testFiles,
|
|
46
|
+
resolveCases,
|
|
47
|
+
byKey,
|
|
48
|
+
allowed,
|
|
49
|
+
result,
|
|
50
|
+
diagnostics,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
await mutate({
|
|
54
|
+
options,
|
|
55
|
+
root,
|
|
56
|
+
source,
|
|
57
|
+
testFiles,
|
|
58
|
+
importsOf,
|
|
59
|
+
code,
|
|
60
|
+
posix,
|
|
61
|
+
isSupport,
|
|
62
|
+
maxMutants,
|
|
63
|
+
byKey,
|
|
64
|
+
result,
|
|
65
|
+
log,
|
|
66
|
+
concurrency,
|
|
67
|
+
budgetSec,
|
|
68
|
+
started,
|
|
69
|
+
after,
|
|
70
|
+
bin,
|
|
71
|
+
compileError,
|
|
72
|
+
allowed,
|
|
73
|
+
diagnostics,
|
|
74
|
+
})
|
|
75
|
+
}
|