@isentinel/jest-roblox 0.3.8 → 0.3.9

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 CHANGED
@@ -352,7 +352,7 @@ Create a file named drillbit.toml in your project's directory.
352
352
 
353
353
  ```toml
354
354
  [plugins.jest_roblox]
355
- github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.3.8/JestRobloxRunner.rbxm"
355
+ github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.2.7/JestRobloxRunner.rbxm"
356
356
  ```
357
357
 
358
358
  Then run `drillbit` and it will download the plugin and install it in Studio for
@@ -10,10 +10,7 @@ const sourceEntry = resolve(dirname(fileURLToPath(import.meta.url)), "../src/cli
10
10
 
11
11
  registerHooks({ load, resolve: resolveLuau });
12
12
 
13
- if (existsSync(sourceEntry)) {
14
- const { main } = await import("../src/cli.ts");
15
- await main();
16
- } else {
17
- const { main } = await import("../dist/cli.mjs");
18
- await main();
19
- }
13
+ const { main } = existsSync(sourceEntry)
14
+ ? await import("../src/cli.ts")
15
+ : await import("../dist/cli.mjs");
16
+ await main();
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as outputSingleResult, I as parseGameOutput, W as formatBanner, Z as LuauScriptError, ct as VALID_BACKENDS, dt as isValidBackend, et as mergeCliWithConfig, ft as ConfigError, h as walkErrorChain, k as outputMultiResult, m as formatMissingScopes, n as runJestRoblox, pt as version, tt as loadConfig } from "./run-Cirdb_CB.mjs";
1
+ import { B as parseGameOutput, J as formatBanner, N as outputMultiResult, P as outputSingleResult, bt as version, ct as loadConfig, ht as VALID_BACKENDS, n as runJestRoblox, st as mergeCliWithConfig, tt as LuauScriptError, v as formatMissingScopes, vt as isValidBackend, y as walkErrorChain, yt as ConfigError } from "./run-BM5sqclu.mjs";
2
2
  import { OpenCloudError } from "@bedrock-rbx/ocale";
3
3
  import process from "node:process";
4
4
  import { parseArgs as parseArgs$1 } from "node:util";
@@ -215,6 +215,7 @@ async function main() {
215
215
  process.exitCode = await run(process.argv.slice(2));
216
216
  }
217
217
  const PARALLEL_FLAG = "--parallel";
218
+ const IntegerLikePattern = /^-?\d+$/;
218
219
  function normalizeParallelFlag(args) {
219
220
  const out = [];
220
221
  for (let index = 0; index < args.length; index++) {
@@ -224,7 +225,7 @@ function normalizeParallelFlag(args) {
224
225
  continue;
225
226
  }
226
227
  const next = args[index + 1];
227
- if (next !== void 0 && !next.startsWith("-") && (next === "auto" || /^-?\d+$/.test(next))) {
228
+ if (next !== void 0 && !next.startsWith("-") && (next === "auto" || IntegerLikePattern.test(next))) {
228
229
  out.push(PARALLEL_FLAG, next);
229
230
  index += 1;
230
231
  } else out.push(PARALLEL_FLAG, "auto");
package/dist/index.d.mts CHANGED
@@ -106,6 +106,44 @@ interface CoverageArtifacts {
106
106
  }
107
107
  declare function readBuildManifest(filePath: string, options?: ReadBuildManifestOptions): ReadBuildManifestResult;
108
108
  //#endregion
109
+ //#region src/artifacts/build-coverage-place.d.ts
110
+ /**
111
+ * Everything a caller (a Node-only "Machine A") needs after producing the
112
+ * coverage-instrumented place offline, without executing any suite: the built
113
+ * place (`coveragePlace.path` + content hash) and the paths of the sibling
114
+ * manifests it shares a `buildId` with. The place is left on disk for the caller
115
+ * to copy to the run machine — it is never cleaned.
116
+ */
117
+ interface CoveragePlaceBundle {
118
+ buildId: string;
119
+ /** The always-on build record's path (`build-manifest.json`). */
120
+ buildManifestPath: string;
121
+ /** The coverage-data sibling manifest's path (`coverage-manifest.json`). */
122
+ coverageManifestPath: string;
123
+ /** The instrumented place: cwd-relative path + SHA-256 of its bytes. */
124
+ coveragePlace: BuildManifestArtifact;
125
+ /** Per-project DataModel paths baked into the place. */
126
+ projects: Array<BuildManifestProject>;
127
+ /** `false` on the incremental no-change reuse path (place was not rebuilt). */
128
+ rebuilt: boolean;
129
+ }
130
+ /**
131
+ * Build the coverage-instrumented place **without running it** — the offline
132
+ * half of the split producer. Instruments (incrementally) and rojo-builds the
133
+ * place, bakes each project's `jest.config` stub into it so any runner that
134
+ * opens the place can discover and run the suite unaided, publishes the sibling
135
+ * Build + Coverage manifests, and hands back the place. No backend is resolved,
136
+ * no suite executes, nothing hits the network. Coverage collection is forced on
137
+ * regardless of the input config.
138
+ *
139
+ * The counterpart to `prepareArtifacts`, minus the run and the Clean Place —
140
+ * the entry point for a machine that cannot execute Roblox at all. It shares the
141
+ * `prepareBakedCoverage` seam with the run path but always bakes stubs (the run
142
+ * path skips baking for studio-cli, which injects configs at runtime), because a
143
+ * place handed to a foreign runner must be self-contained.
144
+ */
145
+ declare function buildCoveragePlace(config: ResolvedConfig): Promise<CoveragePlaceBundle>;
146
+ //#endregion
109
147
  //#region src/coverage-pipeline/types.d.ts
110
148
  /**
111
149
  * Raw hit counts for a single file, keyed by statement/function index.
@@ -761,6 +799,40 @@ type ReadManifestResult = ParsedManifest<CoverageManifest>;
761
799
  declare const manifestSchema: type<CoverageManifest>;
762
800
  declare function readManifest(filePath: string): ReadManifestResult;
763
801
  //#endregion
802
+ //#region src/coverage-pipeline/merge-raw-coverage.d.ts
803
+ /**
804
+ * Additively merge two raw coverage datasets. Overlapping files have their
805
+ * hit counts summed (matching istanbul-lib-coverage's semantics).
806
+ */
807
+ declare function mergeRawCoverage(target: RawCoverageData | undefined, source: RawCoverageData | undefined): RawCoverageData | undefined;
808
+ //#endregion
809
+ //#region src/coverage-pipeline/raw-coverage.d.ts
810
+ /**
811
+ * Normalize a raw coverage table into typed {@link RawCoverageData}. The input
812
+ * is the per-file hit table the coverage probes accumulate at runtime — the
813
+ * `_G.__jest_roblox_cov` global, or the `_coverage` field of a run envelope —
814
+ * keyed by the stable per-file join key (`fileKey`). Luau serializes the
815
+ * `s`/`f` counters as 1-based arrays and `b` as an array of arrays; this
816
+ * canonicalizes them to string-keyed records while leaving the fileKey verbatim
817
+ * (it is the byte-identical join key the static maps are also keyed to). Returns
818
+ * `undefined` when the input is not an object or carries no file with a
819
+ * statement map.
820
+ */
821
+ declare function normalizeRawCoverage(coverage: unknown): RawCoverageData | undefined;
822
+ /**
823
+ * Extract raw coverage from a completed run's result envelope — the companion
824
+ * seam for a run this CLI did not launch. Accepts the plugin's `jestOutput`
825
+ * (a JSON string or an already-parsed object), or the bare `_G.__jest_roblox_cov`
826
+ * table read straight off the run. When an object carries a `_coverage` field it
827
+ * is used; otherwise the object is treated as the hit table itself. Returns
828
+ * `undefined` for malformed JSON or an envelope with no coverage.
829
+ *
830
+ * A multi-project result (`{ entries: [{ jestOutput }, …] }`) carries one
831
+ * envelope per project; parse each `entries[i].jestOutput` and combine with
832
+ * `mergeRawCoverage`.
833
+ */
834
+ declare function parseCoverageEnvelope(output: unknown): RawCoverageData | undefined;
835
+ //#endregion
764
836
  //#region src/coverage-pipeline/attribution.d.ts
765
837
  interface AttributionResult {
766
838
  /** Per Luau file: statement id → ids of the tests that covered it. */
@@ -1608,4 +1680,4 @@ declare function visitExpression(expression: AstExpr, visitor: LuauVisitor): voi
1608
1680
  declare function visitStatement(statement: AstStat, visitor: LuauVisitor): void;
1609
1681
  declare function visitBlock(block: AstStatBlock, visitor: LuauVisitor): void; //#endregion
1610
1682
  //#endregion
1611
- export { type ArtifactBundle, type AstExpr, type AstExprBinary, type AstExprCall, type AstExprFunction, type AstStat, type AstStatBlock, BUILD_MANIFEST_VERSION, type Backend, type BackendOptions, type BuildManifest, type BuildManifestArtifact, type BuildManifestFileRecord, type BuildManifestProject, type CliOptions, type Config, type ConfigInput, type CoverageManifest, DEFAULT_CONFIG, type DisplayName, type ExecuteResult, type FormatOutputOptions, type FormatterEntry, GLOBAL_TEST_KEYS, type GameOutputEntry, type GitHubActionsFormatterOptions, type GlobalTestConfig, type InlineProjectConfig, type InstrumentedFileRecord, JEST_ARGV_EXCLUDED_KEYS, type JestArgv, type JestResult, type LuauSpan, type LuauVisitor, MANIFEST_VERSION, type MultiProjectMerged, type MultiRunResult, type NonInstrumentedFileRecord, OpenCloudBackend, type ProjectEntry, type ProjectInput, type ProjectResult, type ProjectTestConfig, ROOT_CLI_KEYS, type ReadBuildManifestOptions, type ReadBuildManifestResult, type ReadManifestResult as ReadCoverageManifestResult, type ResolvedConfig, type ResolvedProjectConfig, type RunMode, type RunOptions, type RunProjectsOptions, type RunProjectsResult, type RunResult, SHARED_TEST_KEYS, type SharedTestConfig, type SingleRunResult, StudioBackend, StudioCliBackend, type TestCaseResult, type TestDefinition, type TestFileResult, type TestRecord, type TestStatus, type TscErrorInfo, type TypecheckOptions, type WorkspaceConfig, type WorkspaceRunResult, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
1683
+ export { type ArtifactBundle, type AstExpr, type AstExprBinary, type AstExprCall, type AstExprFunction, type AstStat, type AstStatBlock, BUILD_MANIFEST_VERSION, type Backend, type BackendOptions, type BuildManifest, type BuildManifestArtifact, type BuildManifestFileRecord, type BuildManifestProject, type CliOptions, type Config, type ConfigInput, type CoverageManifest, type CoveragePlaceBundle, DEFAULT_CONFIG, type DisplayName, type ExecuteResult, type FormatOutputOptions, type FormatterEntry, GLOBAL_TEST_KEYS, type GameOutputEntry, type GitHubActionsFormatterOptions, type GlobalTestConfig, type InlineProjectConfig, type InstrumentedFileRecord, JEST_ARGV_EXCLUDED_KEYS, type JestArgv, type JestResult, type LuauSpan, type LuauVisitor, MANIFEST_VERSION, type MultiProjectMerged, type MultiRunResult, type NonInstrumentedFileRecord, OpenCloudBackend, type ProjectEntry, type ProjectInput, type ProjectResult, type ProjectTestConfig, ROOT_CLI_KEYS, type RawCoverageData, type RawFileCoverage, type ReadBuildManifestOptions, type ReadBuildManifestResult, type ReadManifestResult as ReadCoverageManifestResult, type ResolvedConfig, type ResolvedProjectConfig, type RunMode, type RunOptions, type RunProjectsOptions, type RunProjectsResult, type RunResult, SHARED_TEST_KEYS, type SharedTestConfig, type SingleRunResult, StudioBackend, StudioCliBackend, type TestCaseResult, type TestDefinition, type TestFileResult, type TestRecord, type TestStatus, type TscErrorInfo, type TypecheckOptions, type WorkspaceConfig, type WorkspaceRunResult, buildCoveragePlace, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, mergeRawCoverage, normalizeRawCoverage, parseCoverageEnvelope, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
package/dist/index.mjs CHANGED
@@ -1,5 +1,55 @@
1
- import { $ as parseJestOutput, B as writeJsonFile, C as visitStatement, D as emitBuildManifest, E as buildManifestSchema, F as formatGameOutputNotice, G as hashFile, H as formatResult, I as parseGameOutput, J as readManifest, K as MANIFEST_VERSION, L as writeGameOutput, M as formatJobSummary, N as formatExecuteOutput, O as readBuildManifest, P as runProjects, Q as extractJsonFromOutput, R as createTimingCollector, S as visitExpression, T as BUILD_MANIFEST_VERSION, U as formatTestSummary, V as formatFailure, X as applyAttribution, Y as writeManifest, _ as generateTestScript, a as loadRojoTree, at as JEST_ARGV_EXCLUDED_KEYS, b as findRojoProject, c as StudioBackend, d as createStudioCliBackend, et as mergeCliWithConfig, f as OpenCloudBackend, g as buildJestArgv, i as collectStubMounts, it as GLOBAL_TEST_KEYS, j as formatAnnotations, l as createStudioBackend, lt as defineConfig, n as runJestRoblox, nt as resolveConfig, o as runTypecheck, ot as ROOT_CLI_KEYS, p as createOpenCloudBackend, q as manifestSchema, r as runSingleOrMulti, rt as DEFAULT_CONFIG, s as resolveAllProjects, st as SHARED_TEST_KEYS, t as getRawProjects, tt as loadConfig, u as StudioCliBackend, ut as defineProject, v as COVERAGE_BUILD_MANIFEST_PATH, w as buildPlace, x as visitBlock, y as COVERAGE_MANIFEST_PATH, z as formatJson } from "./run-Cirdb_CB.mjs";
1
+ import { $ as writeManifest, A as buildManifestSchema, B as parseGameOutput, C as COVERAGE_MANIFEST_PATH, D as visitStatement, E as visitExpression, F as formatAnnotations, G as formatFailure, H as createTimingCollector, I as formatJobSummary, K as formatResult, L as formatExecuteOutput, M as readBuildManifest, O as buildPlace, Q as readManifest, R as runProjects, S as COVERAGE_BUILD_MANIFEST_PATH, T as visitBlock, U as formatJson, V as writeGameOutput, W as writeJsonFile, X as MANIFEST_VERSION, Y as hashFile, Z as manifestSchema, _ as createOpenCloudBackend, _t as defineProject, a as collectStubMounts, at as parseCoverageEnvelope, b as buildJestArgv, c as runTypecheck, ct as loadConfig, d as resolveAllProjects, dt as GLOBAL_TEST_KEYS, et as applyAttribution, f as StudioBackend, ft as JEST_ARGV_EXCLUDED_KEYS, g as OpenCloudBackend, gt as defineConfig, h as createStudioCliBackend, i as buildImplicitProject, it as normalizeRawCoverage, j as emitBuildManifest, k as BUILD_MANIFEST_VERSION, l as cleanLeftoverStubs, lt as resolveConfig, m as StudioCliBackend, mt as SHARED_TEST_KEYS, n as runJestRoblox, nt as extractJsonFromOutput, o as loadRojoTree, ot as mergeRawCoverage, p as createStudioBackend, pt as ROOT_CLI_KEYS, q as formatTestSummary, r as runSingleOrMulti, rt as parseJestOutput, s as prepareBakedCoverage, st as mergeCliWithConfig, t as getRawProjects, u as generateProjectStubs, ut as DEFAULT_CONFIG, w as findRojoProject, x as generateTestScript, z as formatGameOutputNotice } from "./run-BM5sqclu.mjs";
2
2
  import * as path$1 from "node:path";
3
+ //#region src/artifacts/build-coverage-place.ts
4
+ const CACHE_DIR$1 = path$1.join(".jest-roblox", "cache");
5
+ /**
6
+ * Build the coverage-instrumented place **without running it** — the offline
7
+ * half of the split producer. Instruments (incrementally) and rojo-builds the
8
+ * place, bakes each project's `jest.config` stub into it so any runner that
9
+ * opens the place can discover and run the suite unaided, publishes the sibling
10
+ * Build + Coverage manifests, and hands back the place. No backend is resolved,
11
+ * no suite executes, nothing hits the network. Coverage collection is forced on
12
+ * regardless of the input config.
13
+ *
14
+ * The counterpart to `prepareArtifacts`, minus the run and the Clean Place —
15
+ * the entry point for a machine that cannot execute Roblox at all. It shares the
16
+ * `prepareBakedCoverage` seam with the run path but always bakes stubs (the run
17
+ * path skips baking for studio-cli, which injects configs at runtime), because a
18
+ * place handed to a foreign runner must be self-contained.
19
+ */
20
+ async function buildCoveragePlace(config) {
21
+ const merged = mergeCliWithConfig({}, {
22
+ ...config,
23
+ collectCoverage: true
24
+ });
25
+ const projects = await resolveProjects(merged);
26
+ const cacheRoot = path$1.resolve(merged.rootDir, CACHE_DIR$1);
27
+ cleanLeftoverStubs(projects, merged.rootDir);
28
+ generateProjectStubs(projects, merged.rootDir, cacheRoot);
29
+ const { artifacts } = prepareBakedCoverage(merged, projects, cacheRoot, true);
30
+ if (artifacts.rebuilt) emitBuildManifest(COVERAGE_BUILD_MANIFEST_PATH, artifacts);
31
+ return {
32
+ buildId: artifacts.buildId,
33
+ buildManifestPath: COVERAGE_BUILD_MANIFEST_PATH,
34
+ coverageManifestPath: COVERAGE_MANIFEST_PATH,
35
+ coveragePlace: artifacts.coveragePlace,
36
+ projects: artifacts.projects,
37
+ rebuilt: artifacts.rebuilt
38
+ };
39
+ }
40
+ /**
41
+ * Resolve the project set the place is built from, mirroring `runSingleOrMulti`
42
+ * dispatch: an explicit `projects:` config resolves through `resolveAllProjects`;
43
+ * a bare config collapses to the single implicit project derived from its luau
44
+ * roots. Type-only configs are irrelevant here — a build always instruments.
45
+ */
46
+ async function resolveProjects(config) {
47
+ const rojoTree = loadRojoTree(config);
48
+ const rawProjects = getRawProjects(config);
49
+ if (rawProjects !== void 0 && rawProjects.length > 0) return resolveAllProjects(rawProjects, config, rojoTree, config.rootDir);
50
+ return [buildImplicitProject(config, rojoTree)];
51
+ }
52
+ //#endregion
3
53
  //#region src/artifacts/prepare-artifacts.ts
4
54
  const COVERAGE_DIR = path$1.dirname(COVERAGE_BUILD_MANIFEST_PATH);
5
55
  const CLEAN_PLACE_FILE = path$1.join(COVERAGE_DIR, "clean.rbxl");
@@ -81,4 +131,4 @@ async function buildCleanPlace(config) {
81
131
  });
82
132
  }
83
133
  //#endregion
84
- export { BUILD_MANIFEST_VERSION, DEFAULT_CONFIG, GLOBAL_TEST_KEYS, JEST_ARGV_EXCLUDED_KEYS, MANIFEST_VERSION, OpenCloudBackend, ROOT_CLI_KEYS, SHARED_TEST_KEYS, StudioBackend, StudioCliBackend, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };
134
+ export { BUILD_MANIFEST_VERSION, DEFAULT_CONFIG, GLOBAL_TEST_KEYS, JEST_ARGV_EXCLUDED_KEYS, MANIFEST_VERSION, OpenCloudBackend, ROOT_CLI_KEYS, SHARED_TEST_KEYS, StudioBackend, StudioCliBackend, buildCoveragePlace, buildJestArgv, buildManifestSchema, manifestSchema as coverageManifestSchema, createOpenCloudBackend, createStudioBackend, createStudioCliBackend, defineConfig, defineProject, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, hashFile, loadConfig, mergeRawCoverage, normalizeRawCoverage, parseCoverageEnvelope, parseGameOutput, parseJestOutput, prepareArtifacts, readBuildManifest, readManifest as readCoverageManifest, resolveConfig, runJestRoblox, runProjects, runTypecheck, visitBlock, visitExpression, visitStatement, writeGameOutput, writeJsonFile };