@jterrazz/test 15.3.0 → 16.0.0
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 +120 -427
- package/dist/ambiguity.js +7 -6
- package/dist/appium.adapter.js +12 -11
- package/dist/artifacts.js +25 -1735
- package/dist/browser/index.js +256 -233
- package/dist/checker.d.ts +1 -1
- package/dist/checker.js +870 -73
- package/dist/fixtures.js +110 -0
- package/dist/index.d.ts +927 -971
- package/dist/index.js +2116 -2261
- package/dist/literate.js +1747 -0
- package/dist/match.js +625 -84
- package/dist/oxlint.cjs +3515 -1483
- package/dist/oxlint.d.cts +60 -48
- package/dist/oxlint.d.ts +60 -48
- package/dist/oxlint.js +3515 -1483
- package/dist/playwright.adapter.js +100 -6
- package/dist/{intercept.js → server.js} +2 -2
- package/dist/stream.js +6 -6
- package/dist/vitest.d.ts +67 -48
- package/dist/vitest.js +161 -85
- package/package.json +31 -11
- package/dist/spec-document.js +0 -651
package/dist/vitest.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { i as GROUND_EXPECTED } from "./fixtures.js";
|
|
2
|
+
import { i as SCREENSHOTS_DIR, n as COVERAGE_DIR, o as VITEST_ARTIFACTS_DIR, r as REPORTER_OUTPUT_FILES, t as ATTACHMENTS_DIR } from "./artifacts.js";
|
|
3
|
+
import { n as specDescription } from "./literate.js";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
6
|
import { basename, dirname, isAbsolute, resolve } from "node:path";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
import { configDefaults, mergeConfig } from "vitest/config";
|
|
8
|
-
//#region src/
|
|
9
|
+
//#region src/runner/literate-plugin.ts
|
|
9
10
|
/**
|
|
10
11
|
* The `literate()` vite plugin — door one of the spec-document format.
|
|
11
12
|
*
|
|
@@ -70,7 +71,7 @@ function literate(options) {
|
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
//#endregion
|
|
73
|
-
//#region src/
|
|
74
|
+
//#region src/runner/preset.ts
|
|
74
75
|
/**
|
|
75
76
|
* `defineSpecConfig()` — the shared vitest config every repository of the
|
|
76
77
|
* ecosystem starts from.
|
|
@@ -116,6 +117,27 @@ const HOOK_TIMEOUT_MS = 3e4;
|
|
|
116
117
|
*/
|
|
117
118
|
const EXCLUDE = [...configDefaults.exclude, "**/_fixtures/**"];
|
|
118
119
|
/**
|
|
120
|
+
* What a test may never carry into the next one, and the one policy the
|
|
121
|
+
* framework states rather than lints.
|
|
122
|
+
*
|
|
123
|
+
* `retry: 0` is the policy: a flaky test is fixed or deleted, never re-rolled
|
|
124
|
+
* until it passes. A retry turns a real defect into a slow one and hides the
|
|
125
|
+
* day it becomes permanent.
|
|
126
|
+
*
|
|
127
|
+
* The three restores are the other half of the same idea. `vi.spyOn`,
|
|
128
|
+
* `vi.stubGlobal` and `vi.stubEnv` each own a teardown, and a test that forgets
|
|
129
|
+
* one leaks into whatever runs next — a failure that appears in a FILE that did
|
|
130
|
+
* nothing wrong and disappears when that file is run alone. Turning them on
|
|
131
|
+
* here is what lets `clock.at()` and `vi.stubEnv()` be written without an
|
|
132
|
+
* `afterEach`, which is the shape rule J6w asks for.
|
|
133
|
+
*/
|
|
134
|
+
const HYGIENE = {
|
|
135
|
+
restoreMocks: true,
|
|
136
|
+
retry: 0,
|
|
137
|
+
unstubEnvs: true,
|
|
138
|
+
unstubGlobals: true
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
119
141
|
* Defaults a vitest PROJECT accepts. `coverage` and `reporters` are root-only
|
|
120
142
|
* options (vitest omits them from a project's config), so they are absent here
|
|
121
143
|
* on purpose — setting them would be silently dropped.
|
|
@@ -130,20 +152,64 @@ function projectDefaults() {
|
|
|
130
152
|
return {
|
|
131
153
|
cacheDir: VITEST_ARTIFACTS_DIR,
|
|
132
154
|
test: {
|
|
155
|
+
attachmentsDir: ATTACHMENTS_DIR,
|
|
133
156
|
exclude: EXCLUDE,
|
|
134
157
|
hookTimeout: HOOK_TIMEOUT_MS,
|
|
158
|
+
...HYGIENE,
|
|
135
159
|
testTimeout: TEST_TIMEOUT_MS
|
|
136
160
|
}
|
|
137
161
|
};
|
|
138
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Coverage, when `--coverage` asks for it.
|
|
165
|
+
*
|
|
166
|
+
* `v8` because it is the runtime's own counter: no instrumentation pass, no
|
|
167
|
+
* second transform of every file, and the numbers do not move when the bundler
|
|
168
|
+
* does. The provider is an OPTIONAL peer (`@vitest/coverage-v8`), so a project
|
|
169
|
+
* that never asks for coverage never installs it.
|
|
170
|
+
*
|
|
171
|
+
* `json-summary` is not a taste: it is the machine-readable report the ratchet
|
|
172
|
+
* reads. `text` is for the human running the command, and `html` for the one
|
|
173
|
+
* chasing a line. All three land under `.artifacts/vitest/coverage/`, the one
|
|
174
|
+
* directory the toolchain's page owns.
|
|
175
|
+
*
|
|
176
|
+
* What is EXCLUDED is the shape of the answer, not a way to raise the number:
|
|
177
|
+
* a type-only module has nothing to execute (v8 reports it as 0/0 or, worse,
|
|
178
|
+
* as uncovered lines that cannot be covered), and the CLI entries are proven
|
|
179
|
+
* by running the binary, not by importing it.
|
|
180
|
+
*/
|
|
181
|
+
const COVERAGE = {
|
|
182
|
+
exclude: [
|
|
183
|
+
"**/node_modules/**",
|
|
184
|
+
"specs/**",
|
|
185
|
+
"**/_fixtures/**",
|
|
186
|
+
"**/*.d.ts",
|
|
187
|
+
"**/*.test-d.ts",
|
|
188
|
+
"**/*.fixtures.ts",
|
|
189
|
+
"dist/**",
|
|
190
|
+
".artifacts/**",
|
|
191
|
+
"**/*.config.ts",
|
|
192
|
+
"**/*.config.mts"
|
|
193
|
+
],
|
|
194
|
+
provider: "v8",
|
|
195
|
+
reporter: [
|
|
196
|
+
"text",
|
|
197
|
+
"html",
|
|
198
|
+
"json-summary"
|
|
199
|
+
],
|
|
200
|
+
reportsDirectory: COVERAGE_DIR
|
|
201
|
+
};
|
|
139
202
|
/** Defaults for the root config — the project ones, plus what only a root carries. */
|
|
140
203
|
function rootDefaults() {
|
|
141
204
|
return {
|
|
142
205
|
cacheDir: VITEST_ARTIFACTS_DIR,
|
|
143
206
|
test: {
|
|
144
|
-
|
|
207
|
+
attachmentsDir: ATTACHMENTS_DIR,
|
|
208
|
+
coverage: COVERAGE,
|
|
145
209
|
exclude: EXCLUDE,
|
|
146
210
|
hookTimeout: HOOK_TIMEOUT_MS,
|
|
211
|
+
...HYGIENE,
|
|
212
|
+
outputFile: REPORTER_OUTPUT_FILES,
|
|
147
213
|
testTimeout: TEST_TIMEOUT_MS
|
|
148
214
|
}
|
|
149
215
|
};
|
|
@@ -173,7 +239,47 @@ function defineSpecConfig(config = {}) {
|
|
|
173
239
|
};
|
|
174
240
|
}
|
|
175
241
|
//#endregion
|
|
176
|
-
//#region src/
|
|
242
|
+
//#region src/runner/facet-project.ts
|
|
243
|
+
/** The globs a node facet collects, and the ones a caller stated instead. */
|
|
244
|
+
function facetProject(facet, options) {
|
|
245
|
+
return mergeConfig(projectDefaults(), { test: {
|
|
246
|
+
...options.exclude === void 0 ? {} : { exclude: options.exclude },
|
|
247
|
+
include: options.include ?? [`specs/${facet}/**/*.spec.ts`],
|
|
248
|
+
...options.serial === true ? { fileParallelism: false } : {},
|
|
249
|
+
name: facet,
|
|
250
|
+
sequence: { groupOrder: 0 },
|
|
251
|
+
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
252
|
+
} });
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/facets/api/api.project.ts
|
|
256
|
+
/** `api()` — the app met through HTTP. */
|
|
257
|
+
function api(options = {}) {
|
|
258
|
+
return facetProject("api", options);
|
|
259
|
+
}
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/facets/cli/cli.project.ts
|
|
262
|
+
/** The literate defaults — the path convention `cli()` assumes when nothing says otherwise. */
|
|
263
|
+
const CLI_SPECIFICATION = "./specs/cli/cli.specification.ts";
|
|
264
|
+
const CLI_DOCUMENTS = ["specs/cli/**/*.spec.yaml"];
|
|
265
|
+
/**
|
|
266
|
+
* A cli project collects the facet's `.test.ts` files AND its documents: a
|
|
267
|
+
* `<case>.spec.yaml` is a test file of its own (docs/07 § the literate door),
|
|
268
|
+
* so the plugin's glob has to join the include of the project that collects
|
|
269
|
+
* them — which is this one, never the root config.
|
|
270
|
+
*/
|
|
271
|
+
function cli(options = {}) {
|
|
272
|
+
const { literate: literateOptions, ...common } = options;
|
|
273
|
+
const project = facetProject("cli", common);
|
|
274
|
+
if (literateOptions === false) return project;
|
|
275
|
+
const documents = literateOptions?.include ?? CLI_DOCUMENTS;
|
|
276
|
+
return mergeConfig(project, { plugins: [literate({
|
|
277
|
+
include: documents,
|
|
278
|
+
specification: literateOptions?.specification ?? CLI_SPECIFICATION
|
|
279
|
+
})] });
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/seams/vitest-browser/commands.ts
|
|
177
283
|
/** Where a golden sits: `_expected/<name>` beside the test that asked for it. */
|
|
178
284
|
function goldenPath(testPath, name) {
|
|
179
285
|
if (testPath === void 0) throw new Error("golden: the command carries no test path — a golden is read from a test file.");
|
|
@@ -205,7 +311,7 @@ const COMPONENT_COMMANDS = {
|
|
|
205
311
|
goldenWrite
|
|
206
312
|
};
|
|
207
313
|
//#endregion
|
|
208
|
-
//#region src/
|
|
314
|
+
//#region src/facets/component/component.project.ts
|
|
209
315
|
/** The pipeline keys a consumer's Vite config contributes, and nothing else. */
|
|
210
316
|
const PIPELINE_KEYS = [
|
|
211
317
|
"assetsInclude",
|
|
@@ -459,39 +565,6 @@ function componentGlobs(options) {
|
|
|
459
565
|
};
|
|
460
566
|
}
|
|
461
567
|
/**
|
|
462
|
-
* A module test runs beside the module it covers: no DOM, no browser, no
|
|
463
|
-
* pipeline. `.test.tsx` is excluded because a rendered thing is a component
|
|
464
|
-
* test — a project's dependency scan reads every file its globs match, and a
|
|
465
|
-
* `.tsx` collected here would be optimised for a page that never opens.
|
|
466
|
-
*/
|
|
467
|
-
function unit(options = {}) {
|
|
468
|
-
const fromRoots = options.roots?.map((root) => `${root.replace(/\/+$/u, "")}/**/*.test.ts`);
|
|
469
|
-
return mergeConfig(projectDefaults(), { test: {
|
|
470
|
-
exclude: options.exclude ?? ["specs/**", "**/*.test.tsx"],
|
|
471
|
-
include: options.include ?? fromRoots ?? ["**/*.test.ts"],
|
|
472
|
-
...options.serial === true ? { fileParallelism: false } : {},
|
|
473
|
-
name: "unit",
|
|
474
|
-
sequence: { groupOrder: 0 },
|
|
475
|
-
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
476
|
-
} });
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* A website spec meets the assembled product through a served page, in the
|
|
480
|
-
* Chromium playwright drives. It opens a browser, so it is scheduled before the
|
|
481
|
-
* component project and never beside it: two Chromiums must not share a slot on
|
|
482
|
-
* a 2-vCPU runner.
|
|
483
|
-
*/
|
|
484
|
-
function website(options = {}) {
|
|
485
|
-
return mergeConfig(projectDefaults(), { test: {
|
|
486
|
-
...options.exclude === void 0 ? {} : { exclude: options.exclude },
|
|
487
|
-
...options.serial === true ? { fileParallelism: false } : {},
|
|
488
|
-
include: options.include ?? ["specs/website/**/*.test.ts"],
|
|
489
|
-
name: "website",
|
|
490
|
-
sequence: { groupOrder: 1 },
|
|
491
|
-
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
492
|
-
} });
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
568
|
* A component test renders in a real Chromium — the browser the website facet
|
|
496
569
|
* already drives through the same `playwright` peer.
|
|
497
570
|
*
|
|
@@ -511,17 +584,17 @@ async function component(options = {}) {
|
|
|
511
584
|
optimizeDeps: { include: SEAM_DEPENDENCIES.filter(resolves) },
|
|
512
585
|
plugins: [mswWorkerPlugin(), ...consumerPlugins],
|
|
513
586
|
test: {
|
|
514
|
-
attachmentsDir: `${VITEST_ARTIFACTS_DIR}/attachments`,
|
|
515
587
|
browser: {
|
|
516
588
|
commands: COMPONENT_COMMANDS,
|
|
517
589
|
enabled: true,
|
|
590
|
+
expect: { toMatchScreenshot: { screenshotDirectory: SCREENSHOTS_DIR } },
|
|
518
591
|
headless: true,
|
|
519
592
|
instances: [{ browser: "chromium" }],
|
|
520
593
|
provider: playwright({ contextOptions: {
|
|
521
594
|
locale: options.locale ?? "en-US",
|
|
522
595
|
timezoneId: options.timezone ?? "UTC"
|
|
523
596
|
} }),
|
|
524
|
-
screenshotDirectory:
|
|
597
|
+
screenshotDirectory: SCREENSHOTS_DIR,
|
|
525
598
|
viewport: viewportOf(options)
|
|
526
599
|
},
|
|
527
600
|
...componentGlobs(options),
|
|
@@ -535,39 +608,20 @@ async function component(options = {}) {
|
|
|
535
608
|
};
|
|
536
609
|
return mergeConfig(projectDefaults(), project);
|
|
537
610
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
* Chromiums never share a slot on a two-vCPU runner. `{ include, exclude,
|
|
544
|
-
* timeout, serial }` is what a repository states when its tree, its budget or
|
|
545
|
-
* its parallelism differs;
|
|
546
|
-
* everything else is the framework's.
|
|
547
|
-
*/
|
|
548
|
-
/** The globs a node facet collects, and the ones a caller stated instead. */
|
|
549
|
-
function facetProject(facet, options) {
|
|
550
|
-
return mergeConfig(projectDefaults(), { test: {
|
|
551
|
-
...options.exclude === void 0 ? {} : { exclude: options.exclude },
|
|
552
|
-
include: options.include ?? [`specs/${facet}/**/*.test.ts`],
|
|
553
|
-
...options.serial === true ? { fileParallelism: false } : {},
|
|
554
|
-
name: facet,
|
|
555
|
-
sequence: { groupOrder: 0 },
|
|
556
|
-
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
557
|
-
} });
|
|
558
|
-
}
|
|
559
|
-
/** `api()` — the app met through HTTP. */
|
|
560
|
-
function api(options = {}) {
|
|
561
|
-
return facetProject("api", options);
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/facets/integration/integration.project.ts
|
|
613
|
+
/** `integration()` — a module against real services, or against a golden. */
|
|
614
|
+
function integration(options = {}) {
|
|
615
|
+
return facetProject("integration", options);
|
|
562
616
|
}
|
|
617
|
+
//#endregion
|
|
618
|
+
//#region src/facets/jobs/jobs.project.ts
|
|
563
619
|
/** `jobs()` — what a name triggers in-process. */
|
|
564
620
|
function jobs(options = {}) {
|
|
565
621
|
return facetProject("jobs", options);
|
|
566
622
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
return facetProject("integration", options);
|
|
570
|
-
}
|
|
623
|
+
//#endregion
|
|
624
|
+
//#region src/facets/mobile/mobile.project.ts
|
|
571
625
|
/**
|
|
572
626
|
* `mobile()` — the app on a simulator. A simulator is the one thing that
|
|
573
627
|
* cannot share a machine with itself, so it runs last and alone (group 3).
|
|
@@ -575,23 +629,45 @@ function integration(options = {}) {
|
|
|
575
629
|
function mobile(options = {}) {
|
|
576
630
|
return mergeConfig(facetProject("mobile", options), { test: { sequence: { groupOrder: 3 } } });
|
|
577
631
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const CLI_DOCUMENTS = ["specs/cli/**/*.spec.yaml"];
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region src/facets/website/website.project.ts
|
|
581
634
|
/**
|
|
582
|
-
* A
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
635
|
+
* A website spec meets the assembled product through a served page, in the
|
|
636
|
+
* Chromium playwright drives. It opens a browser, so it is scheduled before the
|
|
637
|
+
* component project and never beside it: two Chromiums must not share a slot on
|
|
638
|
+
* a 2-vCPU runner.
|
|
586
639
|
*/
|
|
587
|
-
function
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
640
|
+
function website(options = {}) {
|
|
641
|
+
return mergeConfig(projectDefaults(), { test: {
|
|
642
|
+
...options.exclude === void 0 ? {} : { exclude: options.exclude },
|
|
643
|
+
...options.serial === true ? { fileParallelism: false } : {},
|
|
644
|
+
include: options.include ?? ["specs/website/**/*.spec.ts"],
|
|
645
|
+
name: "website",
|
|
646
|
+
sequence: { groupOrder: 1 },
|
|
647
|
+
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
648
|
+
} });
|
|
649
|
+
}
|
|
650
|
+
//#endregion
|
|
651
|
+
//#region src/runner/projects.ts
|
|
652
|
+
/**
|
|
653
|
+
* A module test runs beside the module it covers: no DOM, no browser, no
|
|
654
|
+
* pipeline. Its suffix is `.test.ts` and its place is OUTSIDE `specs/`, where
|
|
655
|
+
* the assembled product is specified in `.spec.ts` — the two exclusions say
|
|
656
|
+
* exactly that. `.test.tsx` is the third exclusion because a rendered thing is
|
|
657
|
+
* a component test: a project's dependency scan reads every file its globs
|
|
658
|
+
* match, and a `.tsx` collected here would be optimised for a page that never
|
|
659
|
+
* opens.
|
|
660
|
+
*/
|
|
661
|
+
function unit(options = {}) {
|
|
662
|
+
const fromRoots = options.roots?.map((root) => `${root.replace(/\/+$/u, "")}/**/*.test.ts`);
|
|
663
|
+
return mergeConfig(projectDefaults(), { test: {
|
|
664
|
+
exclude: options.exclude ?? ["specs/**", "**/*.test.tsx"],
|
|
665
|
+
include: options.include ?? fromRoots ?? ["**/*.test.ts"],
|
|
666
|
+
...options.serial === true ? { fileParallelism: false } : {},
|
|
667
|
+
name: "unit",
|
|
668
|
+
sequence: { groupOrder: 0 },
|
|
669
|
+
...options.timeout === void 0 ? {} : { testTimeout: options.timeout }
|
|
670
|
+
} });
|
|
595
671
|
}
|
|
596
672
|
//#endregion
|
|
597
673
|
export { api, cli, component, defineSpecConfig, integration, jobs, literate, mobile, unit, website };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jterrazz/test",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "16.0.0",
|
|
4
4
|
"description": "Declarative testing framework for HTTP APIs, CLIs, background jobs, websites, mobile apps and rendered components — one entry point, real infrastructure and a real browser, golden-file assertions, plus an oxlint convention plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api-testing",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"files": [
|
|
32
32
|
"dist",
|
|
33
33
|
"!dist/catalog.*",
|
|
34
|
+
"!dist/coverage.*",
|
|
34
35
|
"schema"
|
|
35
36
|
],
|
|
36
37
|
"type": "module",
|
|
@@ -64,15 +65,12 @@
|
|
|
64
65
|
"docs": "npm run build && node dist/catalog.js && typescript docs",
|
|
65
66
|
"lint": "typescript check && node dist/checker.js specs",
|
|
66
67
|
"lint:fix": "typescript fix && node dist/checker.js specs --fix",
|
|
67
|
-
"test": "vitest --run"
|
|
68
|
+
"test": "vitest --run",
|
|
69
|
+
"coverage": "npm run build && vitest --run --coverage && node dist/coverage.js --write",
|
|
70
|
+
"coverage:check": "node dist/coverage.js"
|
|
68
71
|
},
|
|
69
72
|
"dependencies": {
|
|
70
|
-
"better-sqlite3": "^12.11.1",
|
|
71
|
-
"mockdate": "^3.0.5",
|
|
72
73
|
"msw": "^2.15.0",
|
|
73
|
-
"pg": "^8.22.0",
|
|
74
|
-
"redis": "^6.1.0",
|
|
75
|
-
"testcontainers": "^12.0.4",
|
|
76
74
|
"vitest-mock-extended": "^5.0.0",
|
|
77
75
|
"yaml": "^2.9.0"
|
|
78
76
|
},
|
|
@@ -84,26 +82,36 @@
|
|
|
84
82
|
"@types/pg": "^8.20.0",
|
|
85
83
|
"@types/react": "^19.3.0",
|
|
86
84
|
"@types/react-dom": "^19.3.0",
|
|
87
|
-
"@vitest/browser-playwright": "
|
|
85
|
+
"@vitest/browser-playwright": "5.0.1",
|
|
86
|
+
"@vitest/coverage-v8": "^5.0.1",
|
|
87
|
+
"better-sqlite3": "^12.11.1",
|
|
88
88
|
"hono": "^4.12.30",
|
|
89
|
+
"oxlint": "^1.83.0",
|
|
90
|
+
"pg": "^8.22.0",
|
|
89
91
|
"playwright": "^1.49.0",
|
|
90
92
|
"react": "^19.3.0",
|
|
91
93
|
"react-dom": "^19.3.0",
|
|
92
94
|
"react-router": "^8.4.0",
|
|
95
|
+
"redis": "^6.1.0",
|
|
96
|
+
"testcontainers": "^12.0.4",
|
|
93
97
|
"tsdown": "^0.22.7",
|
|
94
98
|
"vite": "^8.1.4",
|
|
95
|
-
"vitest": "
|
|
99
|
+
"vitest": "5.0.1",
|
|
96
100
|
"vitest-browser-react": "^2.3.0",
|
|
97
101
|
"webdriverio": "^9.30.0"
|
|
98
102
|
},
|
|
99
103
|
"peerDependencies": {
|
|
100
104
|
"@vitest/browser-playwright": "*",
|
|
101
105
|
"appium": "^3.0.0",
|
|
106
|
+
"better-sqlite3": "^12.11.1",
|
|
107
|
+
"pg": "^8.22.0",
|
|
102
108
|
"playwright": "^1.49.0",
|
|
103
109
|
"react": "^18 || ^19",
|
|
104
110
|
"react-dom": "^18 || ^19",
|
|
111
|
+
"redis": "^6.1.0",
|
|
112
|
+
"testcontainers": "^12.0.4",
|
|
105
113
|
"vite": "^6.4.0 || ^7 || ^8",
|
|
106
|
-
"vitest": "^
|
|
114
|
+
"vitest": "^5",
|
|
107
115
|
"vitest-browser-react": "^2.3.0",
|
|
108
116
|
"webdriverio": "^9.30.0"
|
|
109
117
|
},
|
|
@@ -114,6 +122,12 @@
|
|
|
114
122
|
"appium": {
|
|
115
123
|
"optional": true
|
|
116
124
|
},
|
|
125
|
+
"better-sqlite3": {
|
|
126
|
+
"optional": true
|
|
127
|
+
},
|
|
128
|
+
"pg": {
|
|
129
|
+
"optional": true
|
|
130
|
+
},
|
|
117
131
|
"playwright": {
|
|
118
132
|
"optional": true
|
|
119
133
|
},
|
|
@@ -123,6 +137,12 @@
|
|
|
123
137
|
"react-dom": {
|
|
124
138
|
"optional": true
|
|
125
139
|
},
|
|
140
|
+
"redis": {
|
|
141
|
+
"optional": true
|
|
142
|
+
},
|
|
143
|
+
"testcontainers": {
|
|
144
|
+
"optional": true
|
|
145
|
+
},
|
|
126
146
|
"vite": {
|
|
127
147
|
"optional": true
|
|
128
148
|
},
|
|
@@ -134,6 +154,6 @@
|
|
|
134
154
|
}
|
|
135
155
|
},
|
|
136
156
|
"engines": {
|
|
137
|
-
"node": ">=
|
|
157
|
+
"node": ">=24"
|
|
138
158
|
}
|
|
139
159
|
}
|