@hublo/sentinel 1.4.0-alpha.53 → 1.4.0-alpha.55
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/dist/bin/sentinel.js
CHANGED
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
palette,
|
|
16
16
|
registerAdapters,
|
|
17
17
|
resolve
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-OT2TWYRV.js";
|
|
19
19
|
import {
|
|
20
20
|
resolveContext
|
|
21
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-2X26HWRL.js";
|
|
22
22
|
import "../chunk-O7REVMOC.js";
|
|
23
23
|
import "../chunk-QXFCZON7.js";
|
|
24
24
|
import {
|
|
@@ -145,7 +145,7 @@ async function runValidate(ctx) {
|
|
|
145
145
|
);
|
|
146
146
|
}
|
|
147
147
|
if (!ctx.targets.includes("test")) return 1;
|
|
148
|
-
const { validateModuleTests } = await import("../validate-
|
|
148
|
+
const { validateModuleTests } = await import("../validate-SWE3M6WK.js");
|
|
149
149
|
const outcomes = modules.flatMap(
|
|
150
150
|
(module) => validateModuleTests(module.name, module.root)
|
|
151
151
|
);
|
|
@@ -980,15 +980,6 @@ function walk(node, visit) {
|
|
|
980
980
|
}
|
|
981
981
|
var MEMBER_TYPES = /* @__PURE__ */ new Set(["MemberExpression", "StaticMemberExpression"]);
|
|
982
982
|
|
|
983
|
-
// src/roles/test/codemod/edits.ts
|
|
984
|
-
function applyEdits(source, edits) {
|
|
985
|
-
let result = source;
|
|
986
|
-
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
987
|
-
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
988
|
-
}
|
|
989
|
-
return result;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
983
|
// src/roles/test/codemod/inherited-automocks.ts
|
|
993
984
|
function bareModuleCalls(program, method) {
|
|
994
985
|
const found = [];
|
|
@@ -1009,7 +1000,7 @@ function bareModuleCalls(program, method) {
|
|
|
1009
1000
|
});
|
|
1010
1001
|
return found;
|
|
1011
1002
|
}
|
|
1012
|
-
function inheritedAutomocks(cwd, setupFiles,
|
|
1003
|
+
function inheritedAutomocks(cwd, setupFiles, parse6) {
|
|
1013
1004
|
const found = /* @__PURE__ */ new Set();
|
|
1014
1005
|
for (const named of setupFiles) {
|
|
1015
1006
|
const path = resolve3(cwd, named.replace("<rootDir>/", "./"));
|
|
@@ -1021,42 +1012,54 @@ function inheritedAutomocks(cwd, setupFiles, parse5) {
|
|
|
1021
1012
|
} catch {
|
|
1022
1013
|
continue;
|
|
1023
1014
|
}
|
|
1024
|
-
const program =
|
|
1015
|
+
const program = parse6(path, source);
|
|
1025
1016
|
if (program === void 0) continue;
|
|
1026
1017
|
for (const specifier of bareModuleCalls(program, "mock")) found.add(specifier);
|
|
1027
1018
|
}
|
|
1028
1019
|
return [...found].sort();
|
|
1029
1020
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
const at = last === void 0 ? 0 : last.end;
|
|
1050
|
-
const semi = /^import\s[^\n]*;\s*$/m.test(source) ? ";" : "";
|
|
1051
|
-
const block = missing.map((specifier) => `vi.mock('${specifier}')${semi}`).join("\n");
|
|
1052
|
-
const edits = [
|
|
1053
|
-
{ start: at, end: at, text: last === void 0 ? `${block}
|
|
1021
|
+
var INHERITED_MOCKS_SETUP = "vitest.setup.inherited-mocks.mts";
|
|
1022
|
+
function inheritedMocksSetup(specifiers) {
|
|
1023
|
+
const mocks = specifiers.map((specifier) => `vi.mock('${specifier}', () => automock())`);
|
|
1024
|
+
return `/**
|
|
1025
|
+
* Module mocks the ROOT jest setup made for every suite, declared where you can see them.
|
|
1026
|
+
*
|
|
1027
|
+
* The root setup mocked these for every file of every module that named it, and this
|
|
1028
|
+
* migration cuts that reach on purpose. A spec that wants the real module says
|
|
1029
|
+
* \`vi.unmock('<specifier>')\`: a file beats a setup.
|
|
1030
|
+
*
|
|
1031
|
+
* \u26A0\uFE0F \`vi.mock(specifier)\` alone is NOT what jest's automock did. Measured on \`dynamoose\`,
|
|
1032
|
+
* vitest keeps the exported FUNCTIONS and drops \`aws\`, the object the code calls, so the
|
|
1033
|
+
* provider dies on \`Cannot read properties of undefined (reading 'ddb')\`. The factory below
|
|
1034
|
+
* rebuilds the shape jest handed back: every property is a spy, a nested one builds another,
|
|
1035
|
+
* and \`new Thing()\` constructs. A property the underlying spy already owns, such as
|
|
1036
|
+
* \`mockImplementation\`, is returned untouched, so \`vi.mocked(X).mockImplementation(...)\`
|
|
1037
|
+
* keeps working.
|
|
1038
|
+
*/
|
|
1039
|
+
import { vi } from 'vitest'
|
|
1054
1040
|
|
|
1055
|
-
|
|
1041
|
+
const automock = (): Record<string | symbol, unknown> => {
|
|
1042
|
+
const anything = (): never =>
|
|
1043
|
+
new Proxy(vi.fn() as never, {
|
|
1044
|
+
get: (target: Record<string | symbol, unknown>, key: string | symbol) => {
|
|
1045
|
+
if (key === 'then') return undefined
|
|
1046
|
+
target[key] ??= anything()
|
|
1047
|
+
return target[key]
|
|
1048
|
+
},
|
|
1049
|
+
})
|
|
1056
1050
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1051
|
+
const namespace: Record<string | symbol, unknown> = {}
|
|
1052
|
+
return new Proxy(namespace, {
|
|
1053
|
+
get: (target, key) => {
|
|
1054
|
+
if (key === 'then' || key === '__esModule') return undefined
|
|
1055
|
+
target[key] ??= anything()
|
|
1056
|
+
return target[key]
|
|
1057
|
+
},
|
|
1058
|
+
})
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
${mocks.join("\n")}
|
|
1062
|
+
`;
|
|
1060
1063
|
}
|
|
1061
1064
|
|
|
1062
1065
|
// src/roles/test/codemod/inject-type-import.ts
|
|
@@ -1249,6 +1252,15 @@ ${source}`;
|
|
|
1249
1252
|
import { dirname as dirname8 } from "node:path";
|
|
1250
1253
|
import { parseSync as parseSync8 } from "oxc-parser";
|
|
1251
1254
|
|
|
1255
|
+
// src/roles/test/codemod/edits.ts
|
|
1256
|
+
function applyEdits(source, edits) {
|
|
1257
|
+
let result = source;
|
|
1258
|
+
for (const edit of [...edits].sort((left, right) => right.start - left.start)) {
|
|
1259
|
+
result = `${result.slice(0, edit.start)}${edit.text}${result.slice(edit.end)}`;
|
|
1260
|
+
}
|
|
1261
|
+
return result;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1252
1264
|
// src/roles/test/codemod/assertion-return-value.ts
|
|
1253
1265
|
function rootedAtExpect(node) {
|
|
1254
1266
|
let current = node;
|
|
@@ -4391,11 +4403,6 @@ function defaultImportedSpecifiers(cwd) {
|
|
|
4391
4403
|
walk2(cwd);
|
|
4392
4404
|
return found;
|
|
4393
4405
|
}
|
|
4394
|
-
function declaredInheritedMocks(fileName, source, inherited) {
|
|
4395
|
-
if (inherited.length === 0) return source;
|
|
4396
|
-
const program = parse4(fileName, source);
|
|
4397
|
-
return program === void 0 ? source : declareInheritedAutomocks(source, program, inherited);
|
|
4398
|
-
}
|
|
4399
4406
|
function migrateModuleTests(cwd, setupFiles = []) {
|
|
4400
4407
|
const modulesOwnMsw = ownsMswLifecycle(cwd, setupFiles);
|
|
4401
4408
|
const inherited = inheritedAutomocks(cwd, setupFiles, parse4);
|
|
@@ -4473,12 +4480,14 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
4473
4480
|
files++;
|
|
4474
4481
|
renamed += migrated.renamed;
|
|
4475
4482
|
if (migrated.hoisted.length > 0) hoisted++;
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4483
|
+
operations.push({ kind: "write", path: relative8, contents: migrated.source });
|
|
4484
|
+
}
|
|
4485
|
+
if (inherited.length > 0) {
|
|
4486
|
+
operations.push({
|
|
4487
|
+
kind: "write",
|
|
4488
|
+
path: INHERITED_MOCKS_SETUP,
|
|
4489
|
+
contents: inheritedMocksSetup(inherited)
|
|
4490
|
+
});
|
|
4482
4491
|
}
|
|
4483
4492
|
const warnings = [...new Set(collected)];
|
|
4484
4493
|
return blockers.length > 0 ? { operations: [], files, renamed, hoisted, blockers, warnings } : { operations, files, renamed, hoisted, blockers: [], warnings };
|
|
@@ -4487,6 +4496,7 @@ function migrateModuleTests(cwd, setupFiles = []) {
|
|
|
4487
4496
|
// src/roles/test/nest/generate-config.ts
|
|
4488
4497
|
import { readdirSync as readdirSync5, readFileSync as readFileSync17, statSync as statSync6 } from "node:fs";
|
|
4489
4498
|
import { join as join19, relative as relative5 } from "node:path";
|
|
4499
|
+
import { parseSync as parseSync10 } from "oxc-parser";
|
|
4490
4500
|
var NEST_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/nest";
|
|
4491
4501
|
var REACT_TEST_PRESET_SPECIFIER = "@hublo/sentinel/test/react";
|
|
4492
4502
|
function flavourOf(reading) {
|
|
@@ -4566,16 +4576,22 @@ var withoutRootDir = (value) => value.replaceAll("<rootDir>/", "./").replaceAll(
|
|
|
4566
4576
|
function ownsMswLifecycle2(cwd, reading) {
|
|
4567
4577
|
return ownsMswLifecycle(cwd, [...reading.setupFiles ?? [], ...reading.setupFilesAfterEnv ?? []]);
|
|
4568
4578
|
}
|
|
4579
|
+
function parse5(fileName, source) {
|
|
4580
|
+
const { program, errors } = parseSync10(fileName, source, { sourceType: "module" });
|
|
4581
|
+
return errors.length > 0 ? void 0 : program;
|
|
4582
|
+
}
|
|
4569
4583
|
function setupBlock(cwd, reading, msw) {
|
|
4570
4584
|
const dom = flavourOf(reading) === "react";
|
|
4571
4585
|
const declared = [...reading.setupFiles ?? [], ...reading.setupFilesAfterEnv ?? []];
|
|
4572
4586
|
const namedTheRootSetup = declared.some((file) => file.endsWith("jest.setup.after.env.js"));
|
|
4573
4587
|
const own = declared.filter((file) => !file.endsWith("jest.setup.after.env.js")).map((file) => `'${vitestSupportName(withoutRootDir(file))}'`);
|
|
4588
|
+
const inheritedMocks = namedTheRootSetup && inheritedAutomocks(cwd, declared, parse5).length > 0 ? [`'./${INHERITED_MOCKS_SETUP}'`] : [];
|
|
4574
4589
|
const sentinel = [
|
|
4575
4590
|
`'${SENTINEL_TEST_SETUP}'`,
|
|
4576
4591
|
...dom ? [`'${SENTINEL_A11Y_SETUP}'`, `'${SENTINEL_W3C_SETUP}'`] : [],
|
|
4577
4592
|
...namedTheRootSetup ? [`'${SENTINEL_WORKSPACE_SETUP}'`] : [],
|
|
4578
|
-
...msw && namedTheRootSetup && !ownsMswLifecycle2(cwd, reading) ? [`'${SENTINEL_MSW_SETUP}'`] : []
|
|
4593
|
+
...msw && namedTheRootSetup && !ownsMswLifecycle2(cwd, reading) ? [`'${SENTINEL_MSW_SETUP}'`] : [],
|
|
4594
|
+
...inheritedMocks
|
|
4579
4595
|
];
|
|
4580
4596
|
return ` setupFiles: [${[...sentinel, ...own].join(", ")}],`;
|
|
4581
4597
|
}
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
registerAdapters,
|
|
7
7
|
resolve,
|
|
8
8
|
setDefaultRunner
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OT2TWYRV.js";
|
|
10
10
|
import {
|
|
11
11
|
BaseAdapter
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-2X26HWRL.js";
|
|
13
13
|
import "./chunk-O7REVMOC.js";
|
|
14
14
|
import "./chunk-QXFCZON7.js";
|
|
15
15
|
import "./chunk-KMKQDGI6.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.4.0-alpha.
|
|
3
|
+
"version": "1.4.0-alpha.55",
|
|
4
4
|
"description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|