@shivaedev/quality 0.26.0 → 0.27.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/CHANGELOG.md +11 -0
- package/README.md +4 -2
- package/dist/domEnvironment.config.d.ts +4 -0
- package/dist/domEnvironment.config.d.ts.map +1 -0
- package/dist/domEnvironment.config.js +17 -0
- package/dist/domEnvironment.config.js.map +1 -0
- package/dist/testProjects.d.ts +4 -1
- package/dist/testProjects.d.ts.map +1 -1
- package/dist/testProjects.js +23 -3
- package/dist/testProjects.js.map +1 -1
- package/package.json +2 -1
- package/src/domEnvironment.config.ts +13 -0
- package/src/testProjects.ts +27 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.27.0 - 2026-10-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `testProjects()` selects test-story's DOM environment for DOM tests and specs, preserving Node host constructors alongside the happy-dom window without a project remap.
|
|
8
|
+
- `testProjects({ coverage: true })` enables V8 coverage for selected projects, including unvisited source files and excluding tests and fixtures. The exported `TestProjectsOptions` type also accepts native Vitest coverage options through `coverage` to customize the report.
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- DOM projects use test-story's environment instead of plain happy-dom. Install `@shivaedev/test-story` alongside `happy-dom`, and target the DOM window when stubbing browser APIs. Storage fixtures should bind global storage reads to `window.localStorage`; the Node host and DOM window keep separate constructors.
|
|
13
|
+
|
|
3
14
|
## 0.26.0 - 2026-10-18
|
|
4
15
|
|
|
5
16
|
### Added
|
package/README.md
CHANGED
|
@@ -258,7 +258,7 @@ The TypeScript base leaves `types`, `jsx`, `paths`, `include` and output directo
|
|
|
258
258
|
}
|
|
259
259
|
```
|
|
260
260
|
|
|
261
|
-
For Vitest, install `vitest` and `happy-dom` when the repository has DOM tests, then use:
|
|
261
|
+
For Vitest, install `vitest`, and add `@shivaedev/test-story` and `happy-dom` when the repository has DOM tests, then use:
|
|
262
262
|
|
|
263
263
|
```ts
|
|
264
264
|
import { testProjects } from "@shivaedev/quality/testProjects.ts";
|
|
@@ -267,7 +267,9 @@ import { defineConfig } from "vitest/config";
|
|
|
267
267
|
export default defineConfig({ test: testProjects() });
|
|
268
268
|
```
|
|
269
269
|
|
|
270
|
-
`testProjects` runs unit tests and specs in Node and `.dom` tests and specs in
|
|
270
|
+
`testProjects` runs unit tests and specs in Node and `.dom` tests and specs in test-story's DOM environment by default. The DOM environment keeps Node's host constructors separate from the happy-dom window, so DOM specs need no project remap. Each test gets 30 seconds instead of Vitest's 5, because tests that start servers, browsers or CLIs take seconds on a busy CI runner. `.slow` tests run only when `--project slow` asks for them. Type tests are excluded from Vitest and belong in the compiler's input.
|
|
271
|
+
|
|
272
|
+
Coverage is opt-in: `testProjects({ coverage: true })` enables Vitest's V8 provider across the selected projects. Install `@vitest/coverage-v8` at the same version as Vitest. The report includes unvisited `src/**/*.ts` and `src/**/*.tsx` files and excludes declarations, tests, specs and `test-support`. To customize it, pass native Vitest coverage options, for example `testProjects({ coverage: { reporter: ["lcov", "text-summary"] } })`. No separate coverage config is needed.
|
|
271
273
|
|
|
272
274
|
Outside CI, `testProjects` sets `silent: "passed-only"` so local runs show logs only from failing tests. When `CI` is set to a nonempty value, it sets `silent: false` so CI keeps all test logs. It leaves `reporters` unset so Vitest can auto-detect its agent reporter. If a repository adds a reporter, spread `configDefaults.reporters` instead of replacing the defaults:
|
|
273
275
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domEnvironment.config.d.ts","sourceRoot":"","sources":["../src/domEnvironment.config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,QAAA,MAAiB,WAAW,aAE3B,CAAC;eAEa,WAAW"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import process from "node:process";
|
|
12
|
+
import { pathToFileURL } from "node:url";
|
|
13
|
+
// Resolve the DOM plugin from the consumer; depending on test-story would cycle through its Quality tooling.
|
|
14
|
+
const consumer = createRequire(join(process.cwd(), "package.json"));
|
|
15
|
+
const { default: environment } = await import(__rewriteRelativeImportExtension(pathToFileURL(consumer.resolve("@shivaedev/test-story/domEnvironment.config.ts")).href));
|
|
16
|
+
export default environment;
|
|
17
|
+
//# sourceMappingURL=domEnvironment.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domEnvironment.config.js","sourceRoot":"","sources":["../src/domEnvironment.config.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,6GAA6G;AAC7G,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;AACpE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAsC,MAAM,MAAM,kCAC/E,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC,CAAC,IAAI,EACtF,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/dist/testProjects.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { type TestUserConfig } from "vitest/config";
|
|
2
|
-
export
|
|
2
|
+
export interface TestProjectsOptions {
|
|
3
|
+
readonly coverage?: boolean | NonNullable<TestUserConfig["coverage"]>;
|
|
4
|
+
}
|
|
5
|
+
export declare function testProjects({ coverage }?: TestProjectsOptions): TestUserConfig;
|
|
3
6
|
//# sourceMappingURL=testProjects.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testProjects.d.ts","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"testProjects.d.ts","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0C,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAe5F,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;CACtE;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAgB,EAAE,GAAE,mBAAwB,GAAG,cAAc,CAgC3F"}
|
package/dist/testProjects.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import { Config, ConfigProvider, Effect } from "effect";
|
|
2
|
-
import { defaultExclude } from "vitest/config";
|
|
3
|
+
import { coverageConfigDefaults, defaultExclude } from "vitest/config";
|
|
3
4
|
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
4
5
|
const TYPECHECK_ALONE = `**/typecheck.test.${EXTENSION}`;
|
|
5
6
|
function named(environment) {
|
|
@@ -8,13 +9,32 @@ function named(environment) {
|
|
|
8
9
|
function excluding(...patterns) {
|
|
9
10
|
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
10
11
|
}
|
|
11
|
-
export function testProjects() {
|
|
12
|
+
export function testProjects({ coverage = false } = {}) {
|
|
12
13
|
const ci = Effect.runSync(Config.String("CI").pipe(Config.withDefault("")).parse(ConfigProvider.fromEnv()));
|
|
13
14
|
return {
|
|
15
|
+
...(coverage === false
|
|
16
|
+
? {}
|
|
17
|
+
: {
|
|
18
|
+
coverage: {
|
|
19
|
+
enabled: true,
|
|
20
|
+
exclude: [...coverageConfigDefaults.exclude, "**/*.d.ts", "**/*.test.*", "**/*.spec.*", "**/test-support/**"],
|
|
21
|
+
include: ["src/**/*.{ts,tsx}"],
|
|
22
|
+
provider: "v8",
|
|
23
|
+
...(coverage === true ? {} : coverage),
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
14
26
|
project: ["unit", "dom"],
|
|
15
27
|
projects: [
|
|
16
28
|
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
17
|
-
{
|
|
29
|
+
{
|
|
30
|
+
extends: true,
|
|
31
|
+
test: {
|
|
32
|
+
environment: fileURLToPath(import.meta.resolve("#domEnvironment.config.ts")),
|
|
33
|
+
exclude: excluding(named("slow")),
|
|
34
|
+
include: [named("dom")],
|
|
35
|
+
name: "dom",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
18
38
|
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
19
39
|
],
|
|
20
40
|
silent: ci ? false : "passed-only",
|
package/dist/testProjects.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testProjects.js","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"testProjects.js","sourceRoot":"","sources":["../src/testProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AAG5F,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC,MAAM,eAAe,GAAG,qBAAqB,SAAS,EAAE,CAAC;AAEzD,SAAS,KAAK,CAAC,WAAyB;IACvC,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC,CAAC,QAAQ,WAAW,iBAAiB,SAAS,EAAE,CAAC;AACvH,CAAC;AAED,SAAS,SAAS,CAAC,GAAG,QAA2B;IAChD,OAAO,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,eAAe,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC9E,CAAC;AAMD,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAwB,EAAE;IAC1E,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC5G,OAAO;QACN,GAAG,CAAC,QAAQ,KAAK,KAAK;YACrB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACA,QAAQ,EAAE;oBACT,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,CAAC,GAAG,sBAAsB,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC;oBAC7G,OAAO,EAAE,CAAC,mBAAmB,CAAC;oBAC9B,QAAQ,EAAE,IAAI;oBACd,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;iBACtC;aACD,CAAC;QACJ,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;QACxB,QAAQ,EAAE;YACT,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACnI;gBACC,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE;oBACL,WAAW,EAAE,aAAa,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;oBAC5E,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBACjC,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBACvB,IAAI,EAAE,KAAK;iBACX;aACD;YACD,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;SAC9G;QACD,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa;QAClC,+IAA+I;QAC/I,WAAW,EAAE,MAAM;KACnB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/quality",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Repository quality gate with typed rules, a baseline of existing debt and a registry of reasoned exceptions",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/quality#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"./tsconfig/base.json": "./tsconfig/base.json",
|
|
33
33
|
"./tsconfig/package.json": "./tsconfig/package.json",
|
|
34
34
|
"./package.json": "./package.json",
|
|
35
|
+
"./domEnvironment.config.ts": null,
|
|
35
36
|
"./imports/isTooling.ts": null,
|
|
36
37
|
"./rules/imports/bundleInputs.ts": null
|
|
37
38
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import type { Environment } from "vitest/runtime";
|
|
6
|
+
|
|
7
|
+
// Resolve the DOM plugin from the consumer; depending on test-story would cycle through its Quality tooling.
|
|
8
|
+
const consumer = createRequire(join(process.cwd(), "package.json"));
|
|
9
|
+
const { default: environment }: { readonly default: Environment } = await import(
|
|
10
|
+
pathToFileURL(consumer.resolve("@shivaedev/test-story/domEnvironment.config.ts")).href
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export default environment;
|
package/src/testProjects.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import { Config, ConfigProvider, Effect } from "effect";
|
|
2
|
-
import { defaultExclude, type TestUserConfig } from "vitest/config";
|
|
3
|
+
import { coverageConfigDefaults, defaultExclude, type TestUserConfig } from "vitest/config";
|
|
3
4
|
import type { Environment } from "#naming/testName.ts";
|
|
4
5
|
|
|
5
6
|
const EXTENSION = "?(c|m)[jt]s?(x)";
|
|
@@ -14,13 +15,36 @@ function excluding(...patterns: readonly string[]): string[] {
|
|
|
14
15
|
return [...defaultExclude, named("typecheck"), TYPECHECK_ALONE, ...patterns];
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export
|
|
18
|
+
export interface TestProjectsOptions {
|
|
19
|
+
readonly coverage?: boolean | NonNullable<TestUserConfig["coverage"]>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function testProjects({ coverage = false }: TestProjectsOptions = {}): TestUserConfig {
|
|
18
23
|
const ci = Effect.runSync(Config.String("CI").pipe(Config.withDefault("")).parse(ConfigProvider.fromEnv()));
|
|
19
24
|
return {
|
|
25
|
+
...(coverage === false
|
|
26
|
+
? {}
|
|
27
|
+
: {
|
|
28
|
+
coverage: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
exclude: [...coverageConfigDefaults.exclude, "**/*.d.ts", "**/*.test.*", "**/*.spec.*", "**/test-support/**"],
|
|
31
|
+
include: ["src/**/*.{ts,tsx}"],
|
|
32
|
+
provider: "v8",
|
|
33
|
+
...(coverage === true ? {} : coverage),
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
20
36
|
project: ["unit", "dom"],
|
|
21
37
|
projects: [
|
|
22
38
|
{ extends: true, test: { environment: "node", exclude: excluding(named("dom"), named("slow")), include: [named()], name: "unit" } },
|
|
23
|
-
{
|
|
39
|
+
{
|
|
40
|
+
extends: true,
|
|
41
|
+
test: {
|
|
42
|
+
environment: fileURLToPath(import.meta.resolve("#domEnvironment.config.ts")),
|
|
43
|
+
exclude: excluding(named("slow")),
|
|
44
|
+
include: [named("dom")],
|
|
45
|
+
name: "dom",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
24
48
|
{ extends: true, test: { environment: "node", exclude: excluding(), include: [named("slow")], name: "slow" } },
|
|
25
49
|
],
|
|
26
50
|
silent: ci ? false : "passed-only",
|