@rpcbase/test 0.307.0 → 0.309.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.
Files changed (83) hide show
  1. package/README.md +2 -2
  2. package/dist/clearDatabase.d.ts +2 -0
  3. package/dist/clearDatabase.d.ts.map +1 -0
  4. package/dist/clearDatabase.js +12 -0
  5. package/dist/clearDatabase.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +785 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/coverage/collect.d.ts +5 -0
  11. package/dist/coverage/collect.d.ts.map +1 -0
  12. package/dist/coverage/collect.js +113 -0
  13. package/dist/coverage/collect.js.map +1 -0
  14. package/dist/coverage/config-loader.d.ts +11 -0
  15. package/dist/coverage/config-loader.d.ts.map +1 -0
  16. package/dist/coverage/config-loader.js +292 -0
  17. package/dist/coverage/config-loader.js.map +1 -0
  18. package/dist/coverage/config.d.ts +3 -0
  19. package/dist/coverage/config.d.ts.map +1 -0
  20. package/dist/coverage/config.js +110 -0
  21. package/dist/coverage/config.js.map +1 -0
  22. package/dist/coverage/files.d.ts +4 -0
  23. package/dist/coverage/files.d.ts.map +1 -0
  24. package/dist/coverage/files.js +52 -0
  25. package/dist/coverage/files.js.map +1 -0
  26. package/dist/coverage/fixtures.d.ts +5 -0
  27. package/dist/coverage/fixtures.d.ts.map +1 -0
  28. package/dist/coverage/fixtures.js +42 -0
  29. package/dist/coverage/fixtures.js.map +1 -0
  30. package/dist/coverage/global-setup.d.ts +3 -0
  31. package/dist/coverage/global-setup.d.ts.map +1 -0
  32. package/dist/coverage/global-setup.js +18 -0
  33. package/dist/coverage/global-setup.js.map +1 -0
  34. package/dist/coverage/index.d.ts +10 -0
  35. package/dist/coverage/index.d.ts.map +1 -0
  36. package/dist/coverage/index.js +62 -0
  37. package/dist/coverage/index.js.map +1 -0
  38. package/dist/coverage/report.d.ts +7 -0
  39. package/dist/coverage/report.d.ts.map +1 -0
  40. package/dist/coverage/report.js +524 -0
  41. package/dist/coverage/report.js.map +1 -0
  42. package/dist/coverage/reporter.d.ts +16 -0
  43. package/dist/coverage/reporter.d.ts.map +1 -0
  44. package/dist/coverage/reporter.js +57 -0
  45. package/dist/coverage/reporter.js.map +1 -0
  46. package/dist/coverage/types.d.ts +47 -0
  47. package/dist/coverage/types.d.ts.map +1 -0
  48. package/dist/coverage/v8-tracker.d.ts +6 -0
  49. package/dist/coverage/v8-tracker.d.ts.map +1 -0
  50. package/dist/coverage/v8-tracker.js +166 -0
  51. package/dist/coverage/v8-tracker.js.map +1 -0
  52. package/dist/defineConfig.d.ts +3 -0
  53. package/dist/defineConfig.d.ts.map +1 -0
  54. package/dist/index.d.ts +11 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +61 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/serverCoverage.d.ts +8 -0
  59. package/dist/serverCoverage.d.ts.map +1 -0
  60. package/dist/serverCoverage.js +42 -0
  61. package/dist/serverCoverage.js.map +1 -0
  62. package/dist/vitest.config.d.ts +3 -0
  63. package/dist/vitest.config.d.ts.map +1 -0
  64. package/dist/vitest.config.js +83 -0
  65. package/dist/vitest.config.js.map +1 -0
  66. package/package.json +25 -14
  67. package/index.d.ts +0 -64
  68. package/src/clearDatabase.js +0 -19
  69. package/src/cli.js +0 -501
  70. package/src/coverage/collect.js +0 -134
  71. package/src/coverage/config-loader.js +0 -206
  72. package/src/coverage/config.js +0 -134
  73. package/src/coverage/files.js +0 -55
  74. package/src/coverage/fixtures.js +0 -37
  75. package/src/coverage/global-setup.js +0 -19
  76. package/src/coverage/index.js +0 -30
  77. package/src/coverage/report.js +0 -600
  78. package/src/coverage/reporter.js +0 -65
  79. package/src/coverage/v8-tracker.js +0 -205
  80. package/src/defineConfig.js +0 -129
  81. package/src/index.js +0 -49
  82. package/src/vitest.config.mjs +0 -107
  83. /package/{src → dist}/register-tty.cjs +0 -0
@@ -0,0 +1,47 @@
1
+ export type CoverageThresholds = {
2
+ branches: number;
3
+ functions: number;
4
+ lines: number;
5
+ statements: number;
6
+ };
7
+ export type CoverageThresholdMap = {
8
+ global?: Partial<CoverageThresholds>;
9
+ [pattern: string]: Partial<CoverageThresholds> | number | undefined;
10
+ };
11
+ export type CoverageThresholdOption = Partial<CoverageThresholds> | CoverageThresholdMap;
12
+ export type CoverageThresholdTarget = {
13
+ id: string;
14
+ pattern: string;
15
+ thresholds: CoverageThresholds;
16
+ };
17
+ export type CoverageHarnessOptions = {
18
+ rootDir: string;
19
+ collectCoverageFrom: string[];
20
+ testResultsDir?: string;
21
+ coverageReportSubdir?: string;
22
+ coverageFileName?: string;
23
+ includeAllFiles?: boolean;
24
+ thresholds?: CoverageThresholdOption;
25
+ disabledEnvVar?: string;
26
+ };
27
+ export type CoverageConfig = {
28
+ rootDir: string;
29
+ collectCoverageFrom: string[];
30
+ testResultsRoot: string;
31
+ coverageReportDir: string;
32
+ coverageFileName: string;
33
+ includeAllFiles: boolean;
34
+ thresholds: CoverageThresholds;
35
+ thresholdTargets: CoverageThresholdTarget[];
36
+ coverageEnabled: boolean;
37
+ disabledEnvVar: string;
38
+ };
39
+ export type CoverageHarness = {
40
+ config: CoverageConfig;
41
+ globalSetup: () => Promise<void>;
42
+ extendTest<T extends {
43
+ extend: (fixtures: any) => unknown;
44
+ }>(baseTest: T): T;
45
+ reporterEntry(): [string, Record<string, unknown>?];
46
+ };
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coverage/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,MAAM,GAAG,SAAS,CAAA;CACpE,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,oBAAoB,CAAA;AAExF,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,kBAAkB,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,uBAAuB,CAAA;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,gBAAgB,EAAE,uBAAuB,EAAE,CAAA;IAC3C,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,UAAU,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAA;KAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;IAC5E,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CACpD,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { Page, TestInfo } from '@playwright/test';
2
+ import { CoverageConfig } from './types';
3
+ export declare function createCoverageTracker(page: Page, config: CoverageConfig): Promise<{
4
+ stop: (testInfo: TestInfo) => Promise<void>;
5
+ }>;
6
+ //# sourceMappingURL=v8-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v8-tracker.d.ts","sourceRoot":"","sources":["../../src/coverage/v8-tracker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAe7C,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC;IAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA2C1D"}
@@ -0,0 +1,166 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolveCollectCoverageRoots, isInsideAnyRoot } from "./collect.js";
4
+ const VITE_FS_PREFIX = "/@fs/";
5
+ function sanitizePathSegment(input) {
6
+ const value = String(input ?? "").trim();
7
+ return value.replace(/[^a-zA-Z0-9._-]+/g, "_") || "unknown";
8
+ }
9
+ function urlPathLooksLikeFile(pathname) {
10
+ const base = path.posix.basename(String(pathname ?? ""));
11
+ return base.length > 0 && base.includes(".");
12
+ }
13
+ async function createCoverageTracker(page, config) {
14
+ const session = await page.context().newCDPSession(page);
15
+ const scriptMeta = /* @__PURE__ */ new Map();
16
+ const sourceCache = /* @__PURE__ */ new Map();
17
+ const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir);
18
+ await session.send("Debugger.enable");
19
+ session.on("Debugger.scriptParsed", (event) => {
20
+ if (!event.url) {
21
+ return;
22
+ }
23
+ const normalized = normalizeScriptUrl(event.url, config);
24
+ const trackable = normalized && !isNodeModulesPath(normalized.absolutePath) && isInsideAnyRoot(normalized.absolutePath, scriptRoots);
25
+ scriptMeta.set(event.scriptId, {
26
+ normalized: trackable ? normalized : null,
27
+ url: event.url
28
+ });
29
+ });
30
+ await session.send("Profiler.enable");
31
+ await session.send("Profiler.startPreciseCoverage", { callCount: false, detailed: true });
32
+ return {
33
+ async stop(testInfo) {
34
+ try {
35
+ const payload = await collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config);
36
+ if (payload.scripts.length === 0) {
37
+ return;
38
+ }
39
+ const outputFile = resolveCoverageOutputFile(config, testInfo);
40
+ await fs.mkdir(path.dirname(outputFile), { recursive: true });
41
+ await fs.writeFile(outputFile, JSON.stringify(payload, null, 2), "utf8");
42
+ } finally {
43
+ await shutdownSession(session);
44
+ }
45
+ }
46
+ };
47
+ }
48
+ function resolveCoverageOutputFile(config, testInfo) {
49
+ const projectName = sanitizePathSegment(testInfo.project?.name);
50
+ const testId = sanitizePathSegment(testInfo.testId);
51
+ const outputDir = path.join(config.testResultsRoot, "playwright", projectName, testId);
52
+ return path.join(outputDir, config.coverageFileName);
53
+ }
54
+ async function collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config) {
55
+ const { result } = await session.send("Profiler.takePreciseCoverage");
56
+ await session.send("Profiler.stopPreciseCoverage");
57
+ const scripts = [];
58
+ for (const script of result) {
59
+ const meta = scriptMeta.get(script.scriptId);
60
+ if (!meta || !meta.normalized) {
61
+ continue;
62
+ }
63
+ const source = await resolveScriptSource(session, sourceCache, script.scriptId);
64
+ scripts.push({
65
+ absolutePath: meta.normalized.absolutePath,
66
+ relativePath: meta.normalized.relativePath,
67
+ source,
68
+ functions: script.functions,
69
+ url: meta.url
70
+ });
71
+ }
72
+ return {
73
+ testId: testInfo.titlePath.join(" › "),
74
+ scripts
75
+ };
76
+ }
77
+ async function resolveScriptSource(session, cache, scriptId) {
78
+ const cached = cache.get(scriptId);
79
+ if (cached) {
80
+ return cached;
81
+ }
82
+ const promise = fetchScriptSource(session, scriptId);
83
+ cache.set(scriptId, promise);
84
+ return promise;
85
+ }
86
+ async function fetchScriptSource(session, scriptId) {
87
+ try {
88
+ const sourceResponse = await session.send("Debugger.getScriptSource", { scriptId });
89
+ return sourceResponse?.scriptSource ?? "";
90
+ } catch (error) {
91
+ const message = String(error?.message ?? error);
92
+ if (message.includes("Debugger agent is not enabled")) {
93
+ try {
94
+ await session.send("Debugger.enable");
95
+ const sourceResponse = await session.send("Debugger.getScriptSource", { scriptId });
96
+ return sourceResponse?.scriptSource ?? "";
97
+ } catch {
98
+ return "";
99
+ }
100
+ }
101
+ return "";
102
+ }
103
+ }
104
+ async function shutdownSession(session) {
105
+ await Promise.allSettled([
106
+ session.send("Profiler.stopPreciseCoverage").catch(() => void 0),
107
+ session.send("Profiler.disable").catch(() => void 0),
108
+ session.send("Debugger.disable").catch(() => void 0)
109
+ ]);
110
+ await session.detach().catch(() => void 0);
111
+ }
112
+ function normalizeScriptUrl(rawUrl, config) {
113
+ if (!rawUrl || rawUrl.startsWith("node:")) {
114
+ return null;
115
+ }
116
+ const cleaned = stripQuery(rawUrl);
117
+ let pathname = cleaned;
118
+ try {
119
+ const parsed = new URL(cleaned);
120
+ pathname = parsed.pathname;
121
+ } catch {
122
+ }
123
+ if (!pathname) {
124
+ return null;
125
+ }
126
+ let absolutePath;
127
+ const decoded = decodeURIComponent(pathname);
128
+ if (decoded.startsWith(VITE_FS_PREFIX)) {
129
+ absolutePath = path.normalize(decoded.slice(VITE_FS_PREFIX.length));
130
+ } else if (decoded.startsWith("/")) {
131
+ if (!urlPathLooksLikeFile(decoded)) {
132
+ return null;
133
+ }
134
+ absolutePath = path.resolve(process.cwd(), `.${decoded}`);
135
+ } else {
136
+ return null;
137
+ }
138
+ return createNormalizedPath(absolutePath, config.rootDir);
139
+ }
140
+ function createNormalizedPath(absolutePath, rootDir) {
141
+ const normalizedAbsolute = path.normalize(absolutePath);
142
+ const relativePath = path.relative(rootDir, normalizedAbsolute);
143
+ return {
144
+ absolutePath: normalizedAbsolute,
145
+ relativePath
146
+ };
147
+ }
148
+ function stripQuery(url) {
149
+ const queryIndex = url.indexOf("?");
150
+ const hashIndex = url.indexOf("#");
151
+ const endIndex = Math.min(
152
+ queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex,
153
+ hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex
154
+ );
155
+ if (!Number.isFinite(endIndex)) {
156
+ return url;
157
+ }
158
+ return url.slice(0, endIndex);
159
+ }
160
+ function isNodeModulesPath(filePath) {
161
+ return path.normalize(String(filePath ?? "")).split(path.sep).includes("node_modules");
162
+ }
163
+ export {
164
+ createCoverageTracker
165
+ };
166
+ //# sourceMappingURL=v8-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v8-tracker.js","sources":["../../src/coverage/v8-tracker.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { Page, TestInfo } from \"@playwright/test\"\n\nimport { isInsideAnyRoot, resolveCollectCoverageRoots } from \"./collect\"\nimport type { CoverageConfig } from \"./types\"\n\n\nconst VITE_FS_PREFIX = \"/@fs/\"\n\nfunction sanitizePathSegment(input: unknown): string {\n const value = String(input ?? \"\").trim()\n return value.replace(/[^a-zA-Z0-9._-]+/g, \"_\") || \"unknown\"\n}\n\nfunction urlPathLooksLikeFile(pathname: unknown): boolean {\n const base = path.posix.basename(String(pathname ?? \"\"))\n return base.length > 0 && base.includes(\".\")\n}\n\nexport async function createCoverageTracker(\n page: Page,\n config: CoverageConfig,\n): Promise<{ stop: (testInfo: TestInfo) => Promise<void> }> {\n const session = await page.context().newCDPSession(page)\n const scriptMeta = new Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>()\n const sourceCache = new Map<string, Promise<string>>()\n const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir)\n\n await session.send(\"Debugger.enable\")\n session.on(\"Debugger.scriptParsed\", (event: any) => {\n if (!event.url) {\n return\n }\n\n const normalized = normalizeScriptUrl(event.url, config)\n const trackable = normalized\n && !isNodeModulesPath(normalized.absolutePath)\n && isInsideAnyRoot(normalized.absolutePath, scriptRoots)\n\n scriptMeta.set(event.scriptId, {\n normalized: trackable ? normalized : null,\n url: event.url,\n })\n })\n\n await session.send(\"Profiler.enable\")\n await session.send(\"Profiler.startPreciseCoverage\", { callCount: false, detailed: true })\n\n return {\n async stop(testInfo: TestInfo) {\n try {\n const payload = await collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config)\n\n if (payload.scripts.length === 0) {\n return\n }\n\n const outputFile = resolveCoverageOutputFile(config, testInfo)\n await fs.mkdir(path.dirname(outputFile), { recursive: true })\n await fs.writeFile(outputFile, JSON.stringify(payload, null, 2), \"utf8\")\n } finally {\n await shutdownSession(session)\n }\n },\n }\n}\n\nfunction resolveCoverageOutputFile(config: CoverageConfig, testInfo: TestInfo): string {\n const projectName = sanitizePathSegment(testInfo.project?.name)\n const testId = sanitizePathSegment(testInfo.testId)\n const outputDir = path.join(config.testResultsRoot, \"playwright\", projectName, testId)\n return path.join(outputDir, config.coverageFileName)\n}\n\nasync function collectCoveragePayload(\n session: any,\n scriptMeta: Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>,\n sourceCache: Map<string, Promise<string>>,\n testInfo: TestInfo,\n config: CoverageConfig,\n): Promise<{ testId: string; scripts: any[] }> {\n const { result } = await session.send(\"Profiler.takePreciseCoverage\")\n await session.send(\"Profiler.stopPreciseCoverage\")\n\n const scripts = []\n\n for (const script of result) {\n const meta = scriptMeta.get(script.scriptId)\n if (!meta || !meta.normalized) {\n continue\n }\n\n const source = await resolveScriptSource(session, sourceCache, script.scriptId)\n scripts.push({\n absolutePath: meta.normalized.absolutePath,\n relativePath: meta.normalized.relativePath,\n source,\n functions: script.functions,\n url: meta.url,\n })\n }\n\n return {\n testId: testInfo.titlePath.join(\" › \"),\n scripts,\n }\n}\n\nasync function resolveScriptSource(session: any, cache: Map<string, Promise<string>>, scriptId: string): Promise<string> {\n const cached = cache.get(scriptId)\n if (cached) {\n return cached\n }\n\n const promise = fetchScriptSource(session, scriptId)\n cache.set(scriptId, promise)\n return promise\n}\n\nasync function fetchScriptSource(session: any, scriptId: string): Promise<string> {\n try {\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch (error: any) {\n const message = String(error?.message ?? error)\n if (message.includes(\"Debugger agent is not enabled\")) {\n try {\n await session.send(\"Debugger.enable\")\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch {\n return \"\"\n }\n }\n\n return \"\"\n }\n}\n\nasync function shutdownSession(session: any): Promise<void> {\n await Promise.allSettled([\n session.send(\"Profiler.stopPreciseCoverage\").catch(() => undefined),\n session.send(\"Profiler.disable\").catch(() => undefined),\n session.send(\"Debugger.disable\").catch(() => undefined),\n ])\n await session.detach().catch(() => undefined)\n}\n\nfunction normalizeScriptUrl(rawUrl: string, config: CoverageConfig): { absolutePath: string; relativePath: string } | null {\n if (!rawUrl || rawUrl.startsWith(\"node:\")) {\n return null\n }\n\n const cleaned = stripQuery(rawUrl)\n let pathname = cleaned\n\n try {\n const parsed = new URL(cleaned)\n pathname = parsed.pathname\n } catch {\n // keep as-is for relative paths\n }\n\n if (!pathname) {\n return null\n }\n\n let absolutePath\n\n const decoded = decodeURIComponent(pathname)\n if (decoded.startsWith(VITE_FS_PREFIX)) {\n absolutePath = path.normalize(decoded.slice(VITE_FS_PREFIX.length))\n } else if (decoded.startsWith(\"/\")) {\n if (!urlPathLooksLikeFile(decoded)) {\n return null\n }\n absolutePath = path.resolve(process.cwd(), `.${decoded}`)\n } else {\n return null\n }\n\n return createNormalizedPath(absolutePath, config.rootDir)\n}\n\nfunction createNormalizedPath(absolutePath: string, rootDir: string): { absolutePath: string; relativePath: string } {\n const normalizedAbsolute = path.normalize(absolutePath)\n const relativePath = path.relative(rootDir, normalizedAbsolute)\n return {\n absolutePath: normalizedAbsolute,\n relativePath,\n }\n}\n\nfunction stripQuery(url: string): string {\n const queryIndex = url.indexOf(\"?\")\n const hashIndex = url.indexOf(\"#\")\n\n const endIndex = Math.min(\n queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex,\n hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex,\n )\n\n if (!Number.isFinite(endIndex)) {\n return url\n }\n\n return url.slice(0, endIndex)\n}\n\nfunction isNodeModulesPath(filePath: string): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { defineConfig as playwrightDefineConfig } from '@playwright/test';
2
+ export default function (config: Parameters<typeof playwrightDefineConfig>[0]): import('@playwright/test').PlaywrightTestConfig<{}, {}>;
3
+ //# sourceMappingURL=defineConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defineConfig.d.ts","sourceRoot":"","sources":["../src/defineConfig.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,IAAI,sBAAsB,EAAW,MAAM,kBAAkB,CAAA;AA6ElF,MAAM,CAAC,OAAO,WAAU,MAAM,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,2DA6C3E"}
@@ -0,0 +1,11 @@
1
+ import { defineConfig as playwrightDefineConfig, devices } from '@playwright/test';
2
+ export * from '@playwright/test';
3
+ export { clearDatabase } from './clearDatabase';
4
+ export * from './coverage';
5
+ export * from './serverCoverage';
6
+ export declare const test: any;
7
+ export declare const expect: import('@playwright/test').Expect<{}>;
8
+ export { devices };
9
+ type PlaywrightConfig = Parameters<typeof playwrightDefineConfig>[0];
10
+ export declare function defineConfig(userConfig?: PlaywrightConfig): import('@playwright/test').PlaywrightTestConfig<{}, {}>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,YAAY,IAAI,sBAAsB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAM1H,cAAc,kBAAkB,CAAA;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAIhC,eAAO,MAAM,IAAI,KAA2E,CAAA;AAC5F,eAAO,MAAM,MAAM,uCAAa,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,CAAA;AAElB,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;AAGpE,wBAAgB,YAAY,CAAC,UAAU,GAAE,gBAAqB,2DAc7D"}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ import { test as test$2, expect as expect$1, defineConfig as defineConfig$1 } from "@playwright/test";
2
+ export * from "@playwright/test";
3
+ import { devices } from "@playwright/test";
4
+ import { loadCoverageOptionsSync } from "./coverage/config-loader.js";
5
+ import { createCoverageHarness } from "./coverage/index.js";
6
+ import { clearDatabase } from "./clearDatabase.js";
7
+ import { setupServerCoverage } from "./serverCoverage.js";
8
+ import { CoverageReporter } from "./coverage/reporter.js";
9
+ import { createCoverageConfig } from "./coverage/config.js";
10
+ import { generateCoverageReport } from "./coverage/report.js";
11
+ import { createCoverageFixtures } from "./coverage/fixtures.js";
12
+ import { createCoverageGlobalSetup } from "./coverage/global-setup.js";
13
+ import { findCoverageFiles, removeCoverageFiles } from "./coverage/files.js";
14
+ const coverageOptions = loadCoverageOptionsSync({ optional: true });
15
+ const coverageHarness = coverageOptions ? createCoverageHarness(coverageOptions) : null;
16
+ const test = coverageHarness ? coverageHarness.extendTest(test$2) : test$2;
17
+ const expect = expect$1;
18
+ function defineConfig(userConfig = {}) {
19
+ const normalized = { ...userConfig };
20
+ const reporters = ensureReporterArray(normalized.reporter);
21
+ if (coverageHarness?.config.coverageEnabled && process.env.RB_TEST_COMBINED_COVERAGE !== "1") {
22
+ const coverageReporter = coverageHarness.reporterEntry();
23
+ if (!reporters.some(([name]) => name === coverageReporter[0])) {
24
+ reporters.push(coverageReporter);
25
+ }
26
+ }
27
+ normalized.reporter = reporters;
28
+ return defineConfig$1(normalized);
29
+ }
30
+ function ensureReporterArray(reporter) {
31
+ if (!reporter) {
32
+ return [["list"]];
33
+ }
34
+ if (!Array.isArray(reporter)) {
35
+ return [normalizeReporterEntry(reporter)];
36
+ }
37
+ return reporter.map((entry) => normalizeReporterEntry(entry));
38
+ }
39
+ function normalizeReporterEntry(entry) {
40
+ if (Array.isArray(entry)) {
41
+ return entry;
42
+ }
43
+ return [entry];
44
+ }
45
+ export {
46
+ CoverageReporter,
47
+ clearDatabase,
48
+ createCoverageConfig,
49
+ createCoverageFixtures,
50
+ createCoverageGlobalSetup,
51
+ createCoverageHarness,
52
+ defineConfig,
53
+ devices,
54
+ expect,
55
+ findCoverageFiles,
56
+ generateCoverageReport,
57
+ removeCoverageFiles,
58
+ setupServerCoverage,
59
+ test
60
+ };
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { test as baseTest, expect as baseExpect, defineConfig as playwrightDefineConfig, devices } from \"@playwright/test\"\n\nimport { loadCoverageOptionsSync } from \"./coverage/config-loader\"\nimport { createCoverageHarness } from \"./coverage\"\n\n\nexport * from \"@playwright/test\"\n\nexport { clearDatabase } from \"./clearDatabase\"\nexport * from \"./coverage\"\nexport * from \"./serverCoverage\"\n\nconst coverageOptions = loadCoverageOptionsSync({ optional: true })\nconst coverageHarness = coverageOptions ? createCoverageHarness(coverageOptions) : null\nexport const test = coverageHarness ? coverageHarness.extendTest(baseTest as any) : baseTest\nexport const expect = baseExpect\nexport { devices }\n\ntype PlaywrightConfig = Parameters<typeof playwrightDefineConfig>[0]\ntype ReporterEntry = [string, Record<string, unknown>?]\n\nexport function defineConfig(userConfig: PlaywrightConfig = {}) {\n const normalized: any = { ...userConfig }\n const reporters = ensureReporterArray(normalized.reporter)\n\n if (coverageHarness?.config.coverageEnabled && process.env.RB_TEST_COMBINED_COVERAGE !== \"1\") {\n const coverageReporter = coverageHarness.reporterEntry()\n if (!reporters.some(([name]) => name === coverageReporter[0])) {\n reporters.push(coverageReporter)\n }\n }\n\n normalized.reporter = reporters\n\n return playwrightDefineConfig(normalized)\n}\n\nfunction ensureReporterArray(reporter: any): ReporterEntry[] {\n if (!reporter) {\n return [[\"list\"]]\n }\n\n if (!Array.isArray(reporter)) {\n return [normalizeReporterEntry(reporter)]\n }\n\n return reporter.map((entry: any) => normalizeReporterEntry(entry))\n}\n\nfunction normalizeReporterEntry(entry: any): ReporterEntry {\n if (Array.isArray(entry)) {\n return entry as ReporterEntry\n }\n return [entry] as ReporterEntry\n}\n"],"names":["baseTest","baseExpect","playwrightDefineConfig"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,kBAAkB,wBAAwB,EAAE,UAAU,MAAM;AAClE,MAAM,kBAAkB,kBAAkB,sBAAsB,eAAe,IAAI;AAC5E,MAAM,OAAO,kBAAkB,gBAAgB,WAAWA,MAAe,IAAIA;AAC7E,MAAM,SAASC;AAMf,SAAS,aAAa,aAA+B,IAAI;AAC9D,QAAM,aAAkB,EAAE,GAAG,WAAA;AAC7B,QAAM,YAAY,oBAAoB,WAAW,QAAQ;AAEzD,MAAI,iBAAiB,OAAO,mBAAmB,QAAQ,IAAI,8BAA8B,KAAK;AAC5F,UAAM,mBAAmB,gBAAgB,cAAA;AACzC,QAAI,CAAC,UAAU,KAAK,CAAC,CAAC,IAAI,MAAM,SAAS,iBAAiB,CAAC,CAAC,GAAG;AAC7D,gBAAU,KAAK,gBAAgB;AAAA,IACjC;AAAA,EACF;AAEA,aAAW,WAAW;AAEtB,SAAOC,eAAuB,UAAU;AAC1C;AAEA,SAAS,oBAAoB,UAAgC;AAC3D,MAAI,CAAC,UAAU;AACb,WAAO,CAAC,CAAC,MAAM,CAAC;AAAA,EAClB;AAEA,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,WAAO,CAAC,uBAAuB,QAAQ,CAAC;AAAA,EAC1C;AAEA,SAAO,SAAS,IAAI,CAAC,UAAe,uBAAuB,KAAK,CAAC;AACnE;AAEA,SAAS,uBAAuB,OAA2B;AACzD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO;AAAA,EACT;AACA,SAAO,CAAC,KAAK;AACf;"}
@@ -0,0 +1,8 @@
1
+ import { FullConfig } from '@playwright/test';
2
+ type SetupServerCoverageOptions = {
3
+ baseURL?: string;
4
+ strict?: boolean;
5
+ };
6
+ export declare function setupServerCoverage(config: FullConfig, options?: SetupServerCoverageOptions): Promise<() => Promise<void>>;
7
+ export {};
8
+ //# sourceMappingURL=serverCoverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverCoverage.d.ts","sourceRoot":"","sources":["../src/serverCoverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAGlD,KAAK,0BAA0B,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA2B9B"}
@@ -0,0 +1,42 @@
1
+ async function setupServerCoverage(config, options = {}) {
2
+ if (process.env.RB_DISABLE_COVERAGE === "1") {
3
+ return async () => {
4
+ };
5
+ }
6
+ const strict = options.strict ?? true;
7
+ const baseURL = resolveBaseURL(config, options, strict);
8
+ if (!baseURL) {
9
+ return async () => {
10
+ };
11
+ }
12
+ const startResponse = await fetch(`${baseURL}/api/dev/coverage/start`, { method: "POST" });
13
+ if (!startResponse.ok) {
14
+ const body = await startResponse.text().catch(() => "");
15
+ if (!strict) {
16
+ return async () => {
17
+ };
18
+ }
19
+ throw new Error(`Failed to start server coverage: ${startResponse.status} ${body}`);
20
+ }
21
+ return async function stopCoverage() {
22
+ const stopResponse = await fetch(`${baseURL}/api/dev/coverage/stop`, { method: "POST" });
23
+ if (!stopResponse.ok) {
24
+ const body = await stopResponse.text().catch(() => "");
25
+ throw new Error(`Failed to stop server coverage: ${stopResponse.status} ${body}`);
26
+ }
27
+ };
28
+ }
29
+ function resolveBaseURL(config, options, strict) {
30
+ const raw = options.baseURL ?? config.projects?.[0]?.use?.baseURL ?? (process.env.PORT ? `http://localhost:${process.env.PORT}` : null);
31
+ if (typeof raw !== "string" || !raw.trim()) {
32
+ if (!strict) {
33
+ return null;
34
+ }
35
+ throw new Error("Cannot resolve Playwright baseURL (missing config.projects[0].use.baseURL and PORT)");
36
+ }
37
+ return raw.replace(/\/$/, "");
38
+ }
39
+ export {
40
+ setupServerCoverage
41
+ };
42
+ //# sourceMappingURL=serverCoverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverCoverage.js","sources":["../src/serverCoverage.ts"],"sourcesContent":["import type { FullConfig } from \"@playwright/test\"\n\n\ntype SetupServerCoverageOptions = {\n baseURL?: string\n strict?: boolean\n}\n\nexport async function setupServerCoverage(\n config: FullConfig,\n options: SetupServerCoverageOptions = {},\n): Promise<() => Promise<void>> {\n if (process.env.RB_DISABLE_COVERAGE === \"1\") {\n return async () => {}\n }\n\n const strict = options.strict ?? true\n const baseURL = resolveBaseURL(config, options, strict)\n if (!baseURL) {\n return async () => {}\n }\n\n const startResponse = await fetch(`${baseURL}/api/dev/coverage/start`, { method: \"POST\" })\n if (!startResponse.ok) {\n const body = await startResponse.text().catch(() => \"\")\n if (!strict) {\n return async () => {}\n }\n throw new Error(`Failed to start server coverage: ${startResponse.status} ${body}`)\n }\n\n return async function stopCoverage(): Promise<void> {\n const stopResponse = await fetch(`${baseURL}/api/dev/coverage/stop`, { method: \"POST\" })\n if (!stopResponse.ok) {\n const body = await stopResponse.text().catch(() => \"\")\n throw new Error(`Failed to stop server coverage: ${stopResponse.status} ${body}`)\n }\n }\n}\n\nfunction resolveBaseURL(config: FullConfig, options: SetupServerCoverageOptions, strict: boolean): string | null {\n const raw = options.baseURL ?? (config.projects?.[0]?.use as any)?.baseURL\n ?? (process.env.PORT ? `http://localhost:${process.env.PORT}` : null)\n\n if (typeof raw !== \"string\" || !raw.trim()) {\n if (!strict) {\n return null\n }\n throw new Error(\"Cannot resolve Playwright baseURL (missing config.projects[0].use.baseURL and PORT)\")\n }\n\n return raw.replace(/\\/$/, \"\")\n}\n"],"names":[],"mappings":"AAQA,eAAsB,oBACpB,QACA,UAAsC,IACR;AAC9B,MAAI,QAAQ,IAAI,wBAAwB,KAAK;AAC3C,WAAO,YAAY;AAAA,IAAC;AAAA,EACtB;AAEA,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,UAAU,eAAe,QAAQ,SAAS,MAAM;AACtD,MAAI,CAAC,SAAS;AACZ,WAAO,YAAY;AAAA,IAAC;AAAA,EACtB;AAEA,QAAM,gBAAgB,MAAM,MAAM,GAAG,OAAO,2BAA2B,EAAE,QAAQ,QAAQ;AACzF,MAAI,CAAC,cAAc,IAAI;AACrB,UAAM,OAAO,MAAM,cAAc,OAAO,MAAM,MAAM,EAAE;AACtD,QAAI,CAAC,QAAQ;AACX,aAAO,YAAY;AAAA,MAAC;AAAA,IACtB;AACA,UAAM,IAAI,MAAM,oCAAoC,cAAc,MAAM,IAAI,IAAI,EAAE;AAAA,EACpF;AAEA,SAAO,eAAe,eAA8B;AAClD,UAAM,eAAe,MAAM,MAAM,GAAG,OAAO,0BAA0B,EAAE,QAAQ,QAAQ;AACvF,QAAI,CAAC,aAAa,IAAI;AACpB,YAAM,OAAO,MAAM,aAAa,OAAO,MAAM,MAAM,EAAE;AACrD,YAAM,IAAI,MAAM,mCAAmC,aAAa,MAAM,IAAI,IAAI,EAAE;AAAA,IAClF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,QAAoB,SAAqC,QAAgC;AAC/G,QAAM,MAAM,QAAQ,WAAY,OAAO,WAAW,CAAC,GAAG,KAAa,YAC7D,QAAQ,IAAI,OAAO,oBAAoB,QAAQ,IAAI,IAAI,KAAK;AAElE,MAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,QAAQ;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AACA,UAAM,IAAI,MAAM,qFAAqF;AAAA,EACvG;AAEA,SAAO,IAAI,QAAQ,OAAO,EAAE;AAC9B;"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import('vite').UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../src/vitest.config.ts"],"names":[],"mappings":";AAyGA,wBAKE"}
@@ -0,0 +1,83 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { defineConfig } from "vitest/config";
5
+ const require$1 = createRequire(import.meta.url);
6
+ function escapeRegex(str) {
7
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8
+ }
9
+ function loadTsconfig() {
10
+ let ts;
11
+ try {
12
+ ts = require$1("typescript");
13
+ } catch (_err) {
14
+ throw new Error(
15
+ "@rpcbase/test: TypeScript is required to resolve path aliases. Please add it as a devDependency."
16
+ );
17
+ }
18
+ const cwd = process.cwd();
19
+ const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.json") || ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.base.json");
20
+ if (!configPath) {
21
+ throw new Error("@rpcbase/test: no tsconfig found for alias resolution");
22
+ }
23
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
24
+ if (configFile.error) {
25
+ throw new Error(`@rpcbase/test: unable to read tsconfig at ${configPath}`);
26
+ }
27
+ const parsed = ts.parseJsonConfigFileContent(
28
+ configFile.config,
29
+ ts.sys,
30
+ path.dirname(configPath)
31
+ );
32
+ return {
33
+ path: configPath,
34
+ baseUrl: parsed.options?.baseUrl ? path.resolve(path.dirname(configPath), parsed.options.baseUrl) : path.dirname(configPath),
35
+ paths: parsed.options?.paths
36
+ };
37
+ }
38
+ function pathsToAlias(tsconfig2) {
39
+ const paths = tsconfig2?.paths;
40
+ if (!paths) return [];
41
+ const baseUrl = tsconfig2.baseUrl || path.dirname(tsconfig2.path);
42
+ const alias2 = [];
43
+ for (const [key, targets] of Object.entries(paths)) {
44
+ if (!Array.isArray(targets)) continue;
45
+ for (const target of targets) {
46
+ if (key.includes("*") && target.includes("*")) {
47
+ const wildcardPattern = target.endsWith("*") ? "(.+)" : "([^/]+)";
48
+ const find2 = new RegExp(
49
+ `^${escapeRegex(key).split("\\*").join(wildcardPattern)}$`
50
+ );
51
+ let groupIndex = 0;
52
+ const replacedTarget = target.replace(/\*/g, () => `$${++groupIndex}`);
53
+ const replacement2 = path.resolve(baseUrl, replacedTarget);
54
+ const checkPath = replacement2.replace(/\$\\d+/g, "");
55
+ if (checkPath.includes(`${path.sep}node_modules${path.sep}`) && !fs.existsSync(checkPath)) {
56
+ continue;
57
+ }
58
+ alias2.push({ find: find2, replacement: replacement2 });
59
+ continue;
60
+ }
61
+ const find = key.replace(/\*$/, "");
62
+ const cleanTarget = target.replace(/\*$/, "");
63
+ const replacement = path.resolve(baseUrl, cleanTarget);
64
+ if (replacement.includes(`${path.sep}node_modules${path.sep}`) && !fs.existsSync(replacement)) {
65
+ continue;
66
+ }
67
+ alias2.push({ find, replacement });
68
+ }
69
+ }
70
+ return alias2;
71
+ }
72
+ const tsconfig = loadTsconfig();
73
+ const alias = pathsToAlias(tsconfig);
74
+ const vitest_config = defineConfig({
75
+ test: {
76
+ include: ["{src,lib}/**/*.test.{js,ts,tsx}"]
77
+ },
78
+ resolve: alias.length > 0 ? { alias } : void 0
79
+ });
80
+ export {
81
+ vitest_config as default
82
+ };
83
+ //# sourceMappingURL=vitest.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.js","sources":["../src/vitest.config.ts"],"sourcesContent":["import path from \"node:path\"\nimport fs from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nimport { defineConfig } from \"vitest/config\"\n\n\nconst require = createRequire(import.meta.url)\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\ntype TsconfigPaths = Record<string, string[]>\n\nfunction loadTsconfig(): { path: string; baseUrl: string; paths?: TsconfigPaths } {\n let ts\n try {\n ts = require(\"typescript\")\n } catch (_err) {\n throw new Error(\n \"@rpcbase/test: TypeScript is required to resolve path aliases. Please add it as a devDependency.\",\n )\n }\n\n const cwd = process.cwd()\n const configPath =\n ts.findConfigFile(cwd, ts.sys.fileExists, \"tsconfig.json\") ||\n ts.findConfigFile(cwd, ts.sys.fileExists, \"tsconfig.base.json\")\n\n if (!configPath) {\n throw new Error(\"@rpcbase/test: no tsconfig found for alias resolution\")\n }\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (configFile.error) {\n throw new Error(`@rpcbase/test: unable to read tsconfig at ${configPath}`)\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path.dirname(configPath),\n )\n\n return {\n path: configPath,\n baseUrl: parsed.options?.baseUrl\n ? path.resolve(path.dirname(configPath), parsed.options.baseUrl)\n : path.dirname(configPath),\n paths: parsed.options?.paths,\n }\n}\n\ntype ViteAliasEntry = { find: string | RegExp; replacement: string }\n\nfunction pathsToAlias(tsconfig: { path: string; baseUrl: string; paths?: TsconfigPaths }): ViteAliasEntry[] {\n const paths = tsconfig?.paths\n if (!paths) return []\n\n const baseUrl = tsconfig.baseUrl || path.dirname(tsconfig.path)\n const alias: ViteAliasEntry[] = []\n\n for (const [key, targets] of Object.entries(paths)) {\n if (!Array.isArray(targets)) continue\n\n for (const target of targets) {\n if (key.includes(\"*\") && target.includes(\"*\")) {\n const wildcardPattern = target.endsWith(\"*\") ? \"(.+)\" : \"([^/]+)\"\n const find = new RegExp(\n `^${escapeRegex(key).split(\"\\\\*\").join(wildcardPattern)}$`,\n )\n let groupIndex = 0\n const replacedTarget = target.replace(/\\*/g, () => `$${++groupIndex}`)\n const replacement = path.resolve(baseUrl, replacedTarget)\n const checkPath = replacement.replace(/\\$\\\\d+/g, \"\")\n if (\n checkPath.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(checkPath)\n ) {\n continue\n }\n alias.push({ find, replacement })\n continue\n }\n\n const find = key.replace(/\\*$/, \"\")\n const cleanTarget = target.replace(/\\*$/, \"\")\n const replacement = path.resolve(baseUrl, cleanTarget)\n if (\n replacement.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(replacement)\n ) {\n continue\n }\n alias.push({ find, replacement })\n }\n }\n\n return alias\n}\n\nconst tsconfig = loadTsconfig()\nconst alias = pathsToAlias(tsconfig)\n\nexport default defineConfig({\n test: {\n include: [\"{src,lib}/**/*.test.{js,ts,tsx}\"],\n },\n resolve: alias.length > 0 ? { alias } : undefined,\n})\n"],"names":["require","tsconfig","alias","find","replacement"],"mappings":";;;;AAOA,MAAMA,YAAU,cAAc,YAAY,GAAG;AAE7C,SAAS,YAAY,KAAqB;AACxC,SAAO,IAAI,QAAQ,uBAAuB,MAAM;AAClD;AAIA,SAAS,eAAyE;AAChF,MAAI;AACJ,MAAI;AACF,SAAKA,UAAQ,YAAY;AAAA,EAC3B,SAAS,MAAM;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,MAAM,QAAQ,IAAA;AACpB,QAAM,aACJ,GAAG,eAAe,KAAK,GAAG,IAAI,YAAY,eAAe,KACzD,GAAG,eAAe,KAAK,GAAG,IAAI,YAAY,oBAAoB;AAEhE,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,QAAM,aAAa,GAAG,eAAe,YAAY,GAAG,IAAI,QAAQ;AAChE,MAAI,WAAW,OAAO;AACpB,UAAM,IAAI,MAAM,6CAA6C,UAAU,EAAE;AAAA,EAC3E;AAEA,QAAM,SAAS,GAAG;AAAA,IAChB,WAAW;AAAA,IACX,GAAG;AAAA,IACH,KAAK,QAAQ,UAAU;AAAA,EAAA;AAGzB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,OAAO,SAAS,UACrB,KAAK,QAAQ,KAAK,QAAQ,UAAU,GAAG,OAAO,QAAQ,OAAO,IAC7D,KAAK,QAAQ,UAAU;AAAA,IAC3B,OAAO,OAAO,SAAS;AAAA,EAAA;AAE3B;AAIA,SAAS,aAAaC,WAAsF;AAC1G,QAAM,QAAQA,WAAU;AACxB,MAAI,CAAC,MAAO,QAAO,CAAA;AAEnB,QAAM,UAAUA,UAAS,WAAW,KAAK,QAAQA,UAAS,IAAI;AAC9D,QAAMC,SAA0B,CAAA;AAEhC,aAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClD,QAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAE7B,eAAW,UAAU,SAAS;AAC5B,UAAI,IAAI,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,GAAG;AAC7C,cAAM,kBAAkB,OAAO,SAAS,GAAG,IAAI,SAAS;AACxD,cAAMC,QAAO,IAAI;AAAA,UACf,IAAI,YAAY,GAAG,EAAE,MAAM,KAAK,EAAE,KAAK,eAAe,CAAC;AAAA,QAAA;AAEzD,YAAI,aAAa;AACjB,cAAM,iBAAiB,OAAO,QAAQ,OAAO,MAAM,IAAI,EAAE,UAAU,EAAE;AACrE,cAAMC,eAAc,KAAK,QAAQ,SAAS,cAAc;AACxD,cAAM,YAAYA,aAAY,QAAQ,WAAW,EAAE;AACnD,YACE,UAAU,SAAS,GAAG,KAAK,GAAG,eAAe,KAAK,GAAG,EAAE,KACvD,CAAC,GAAG,WAAW,SAAS,GACxB;AACA;AAAA,QACF;AACAF,eAAM,KAAK,EAAE,MAAAC,OAAM,aAAAC,cAAa;AAChC;AAAA,MACF;AAEA,YAAM,OAAO,IAAI,QAAQ,OAAO,EAAE;AAClC,YAAM,cAAc,OAAO,QAAQ,OAAO,EAAE;AAC5C,YAAM,cAAc,KAAK,QAAQ,SAAS,WAAW;AACrD,UACE,YAAY,SAAS,GAAG,KAAK,GAAG,eAAe,KAAK,GAAG,EAAE,KACzD,CAAC,GAAG,WAAW,WAAW,GAC1B;AACA;AAAA,MACF;AACAF,aAAM,KAAK,EAAE,MAAM,aAAa;AAAA,IAClC;AAAA,EACF;AAEA,SAAOA;AACT;AAEA,MAAM,WAAW,aAAA;AACjB,MAAM,QAAQ,aAAa,QAAQ;AAEnC,MAAA,gBAAe,aAAa;AAAA,EAC1B,MAAM;AAAA,IACJ,SAAS,CAAC,iCAAiC;AAAA,EAAA;AAAA,EAE7C,SAAS,MAAM,SAAS,IAAI,EAAE,UAAU;AAC1C,CAAC;"}
package/package.json CHANGED
@@ -1,34 +1,45 @@
1
1
  {
2
2
  "name": "@rpcbase/test",
3
- "version": "0.307.0",
3
+ "version": "0.309.0",
4
4
  "type": "module",
5
5
  "files": [
6
- "src",
7
- "index.d.ts"
6
+ "dist"
8
7
  ],
9
- "types": "./index.d.ts",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
- "types": "./index.d.ts",
13
- "import": "./src/index.js",
14
- "default": "./src/index.js"
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
15
  }
16
16
  },
17
17
  "bin": {
18
- "rb-test": "./src/cli.js"
18
+ "rb-test": "./dist/cli.js"
19
19
  },
20
- "main": "./src/index.js",
21
20
  "scripts": {
22
21
  "build": "wireit",
23
22
  "release": "wireit"
24
23
  },
25
24
  "wireit": {
26
25
  "build": {
27
- "command": "echo 'build ok' > build-output.txt",
28
- "output": [
29
- "build-output.txt"
26
+ "command": "../../node_modules/.bin/vite build",
27
+ "files": [
28
+ "package.json",
29
+ "src/**/*",
30
+ "../../tsconfig.json",
31
+ "../../scripts/tsconfig.pkg.json",
32
+ "./tsconfig.json",
33
+ "./vite.config.js",
34
+ "../../scripts/vite.config-pkg.js"
30
35
  ],
31
- "dependencies": []
36
+ "output": [
37
+ "dist/"
38
+ ]
39
+ },
40
+ "build-watch": {
41
+ "command": "../../node_modules/.bin/vite build --watch",
42
+ "service": true
32
43
  },
33
44
  "release": {
34
45
  "command": "../../scripts/publish.js",
@@ -38,7 +49,7 @@
38
49
  "files": [
39
50
  "../../scripts/publish.js",
40
51
  "package.json",
41
- "src/**/*"
52
+ "dist/**/*"
42
53
  ],
43
54
  "output": [
44
55
  "publish-output.txt"
package/index.d.ts DELETED
@@ -1,64 +0,0 @@
1
- export * from "playwright/test"
2
-
3
- interface CoverageThresholds {
4
- branches: number
5
- functions: number
6
- lines: number
7
- statements: number
8
- }
9
-
10
- type CoverageThresholdMap = {
11
- global?: Partial<CoverageThresholds>
12
- [pattern: string]: Partial<CoverageThresholds> | number | undefined
13
- }
14
-
15
- type CoverageThresholdOption = Partial<CoverageThresholds> | CoverageThresholdMap
16
-
17
- interface CoverageThresholdTarget {
18
- id: string
19
- pattern: string
20
- thresholds: CoverageThresholds
21
- }
22
-
23
- interface CoverageHarnessOptions {
24
- rootDir: string
25
- collectCoverageFrom: string[]
26
- testResultsDir?: string
27
- coverageReportSubdir?: string
28
- coverageFileName?: string
29
- includeAllFiles?: boolean
30
- envPrefix?: string
31
- thresholds?: CoverageThresholdOption
32
- disabledEnvVar?: string
33
- }
34
-
35
- interface CoverageConfig extends CoverageHarnessOptions {
36
- testResultsRoot: string
37
- coverageReportDir: string
38
- coverageFileName: string
39
- includeAllFiles: boolean
40
- thresholds: CoverageThresholds
41
- thresholdTargets: CoverageThresholdTarget[]
42
- coverageEnabled: boolean
43
- disabledEnvVar: string
44
- }
45
-
46
- interface CoverageHarness {
47
- config: CoverageConfig
48
- globalSetup(...args: any[]): Promise<void>
49
- extendTest<T>(baseTest: T): T
50
- reporterEntry(): [string, Record<string, unknown>?]
51
- }
52
-
53
- export function clearDatabase(dbName: string): Promise<void>
54
- export function createCoverageHarness(options: CoverageHarnessOptions): CoverageHarness
55
- export function createCoverageConfig(options: CoverageHarnessOptions): CoverageConfig
56
-
57
- export type {
58
- CoverageHarness,
59
- CoverageHarnessOptions,
60
- CoverageConfig,
61
- CoverageThresholds,
62
- CoverageThresholdOption,
63
- CoverageThresholdTarget,
64
- }