@isentinel/jest-roblox 0.1.2 → 0.1.4

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.
@@ -825,6 +825,7 @@ interface Config extends Except<Argv, "projects" | "rootDir" | "setupFiles" | "s
825
825
  gameOutput?: string;
826
826
  jestPath?: string;
827
827
  luauRoots?: Array<string>;
828
+ passWithNoTests?: boolean;
828
829
  placeFile?: string;
829
830
  pollInterval?: number;
830
831
  port?: number;
@@ -852,6 +853,7 @@ interface ResolvedConfig extends Except<Config, "projects"> {
852
853
  coverageDirectory: string;
853
854
  coveragePathIgnorePatterns: Array<string>;
854
855
  coverageReporters: Array<CoverageReporter>;
856
+ passWithNoTests: boolean;
855
857
  placeFile: string;
856
858
  pollInterval: number;
857
859
  port: number;
@@ -875,6 +877,7 @@ interface CliOptions {
875
877
  backend?: Backend$1;
876
878
  cache?: boolean;
877
879
  collectCoverage?: boolean;
880
+ collectCoverageFrom?: Array<string>;
878
881
  color?: boolean;
879
882
  config?: string;
880
883
  coverageDirectory?: string;
@@ -884,6 +887,7 @@ interface CliOptions {
884
887
  gameOutput?: string;
885
888
  help?: boolean;
886
889
  outputFile?: string;
890
+ passWithNoTests?: boolean;
887
891
  pollInterval?: number;
888
892
  port?: number;
889
893
  project?: Array<string>;
@@ -4,7 +4,7 @@ import assert from "node:assert";
4
4
  import * as fs$1 from "node:fs";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  import * as path$1 from "node:path";
7
- import path from "node:path";
7
+ import path, { dirname, join, relative } from "node:path";
8
8
  import process from "node:process";
9
9
  import color from "tinyrainbow";
10
10
  import { WebSocketServer } from "ws";
@@ -14,9 +14,9 @@ import * as crypto from "node:crypto";
14
14
  import { randomUUID } from "node:crypto";
15
15
  import buffer from "node:buffer";
16
16
  import { defuFn } from "defu";
17
+ import { execFileSync } from "node:child_process";
17
18
  import { TraceMap, originalPositionFor, sourceContentFor } from "@jridgewell/trace-mapping";
18
19
  import { getTsconfig } from "get-tsconfig";
19
- import { execFileSync } from "node:child_process";
20
20
  import hljs from "highlight.js/lib/core";
21
21
  import typescript from "highlight.js/lib/languages/typescript";
22
22
  import { parseJSONC } from "confbox";
@@ -243,6 +243,7 @@ const DEFAULT_CONFIG = {
243
243
  "**/rbxts_include/**"
244
244
  ],
245
245
  coverageReporters: ["text", "lcov"],
246
+ passWithNoTests: false,
246
247
  placeFile: "./game.rbxl",
247
248
  pollInterval: 500,
248
249
  port: 3001,
@@ -361,6 +362,7 @@ const configSchema = type({
361
362
  "maxWorkers?": type("number").or(type("string")),
362
363
  "noStackTrace?": "boolean",
363
364
  "outputFile?": "string",
365
+ "passWithNoTests?": "boolean",
364
366
  "placeFile?": "string",
365
367
  "pollInterval?": "number",
366
368
  "port?": "number",
@@ -822,6 +824,52 @@ function resolveFunctionValues(config) {
822
824
  return resolved;
823
825
  }
824
826
  //#endregion
827
+ //#region src/utils/rojo-tree.ts
828
+ function resolveNestedProjects(tree, rootDirectory) {
829
+ return resolveTree(tree, rootDirectory, rootDirectory, /* @__PURE__ */ new Set());
830
+ }
831
+ function collectPaths(node, result) {
832
+ for (const [key, value] of Object.entries(node)) if (key === "$path" && typeof value === "string") result.push(value.replaceAll("\\", "/"));
833
+ else if (typeof value === "object" && !Array.isArray(value) && !key.startsWith("$")) collectPaths(value, result);
834
+ }
835
+ function inlineNestedProject(projectPath, currentDirectory, originalRoot, visited) {
836
+ const chain = new Set(visited);
837
+ chain.add(projectPath);
838
+ let content;
839
+ try {
840
+ content = readFileSync(projectPath, "utf-8");
841
+ } catch (err) {
842
+ const relativePath = relative(currentDirectory, projectPath);
843
+ throw new Error(`Could not read nested Rojo project: ${relativePath}`, { cause: err });
844
+ }
845
+ return resolveTree(JSON.parse(content).tree, dirname(projectPath), originalRoot, chain);
846
+ }
847
+ function resolveRootRelativePath(currentDirectory, value, originalRoot) {
848
+ return relative(originalRoot, join(currentDirectory, value)).replaceAll("\\", "/");
849
+ }
850
+ function resolveTree(node, currentDirectory, originalRoot, visited) {
851
+ const resolved = {};
852
+ for (const [key, value] of Object.entries(node)) {
853
+ if (key === "$path" && typeof value === "string" && value.endsWith(".project.json")) {
854
+ const projectPath = join(currentDirectory, value);
855
+ if (visited.has(projectPath)) throw new Error(`Circular project reference: ${value}`);
856
+ const innerTree = inlineNestedProject(projectPath, currentDirectory, originalRoot, visited);
857
+ for (const [innerKey, innerValue] of Object.entries(innerTree)) resolved[innerKey] = innerValue;
858
+ continue;
859
+ }
860
+ if (key === "$path" && typeof value === "string") {
861
+ resolved[key] = resolveRootRelativePath(currentDirectory, value, originalRoot);
862
+ continue;
863
+ }
864
+ if (key.startsWith("$") || typeof value !== "object" || Array.isArray(value)) {
865
+ resolved[key] = value;
866
+ continue;
867
+ }
868
+ resolved[key] = resolveTree(value, currentDirectory, originalRoot, visited);
869
+ }
870
+ return resolved;
871
+ }
872
+ //#endregion
825
873
  //#region src/types/rojo.ts
826
874
  const rojoProjectSchema = type({
827
875
  "name": "string",
@@ -1991,8 +2039,8 @@ function formatSnapshotLine(snapshot, styles) {
1991
2039
  return `${styles.dim(" Snapshots")} ${styles.summary.failed(`${snapshot.unmatched} failed`)}`;
1992
2040
  }
1993
2041
  //#endregion
1994
- //#region src/formatters/compact.ts
1995
- function formatCompact(result, options) {
2042
+ //#region src/formatters/agent.ts
2043
+ function formatAgent(result, options) {
1996
2044
  const lines = [];
1997
2045
  const execErrors = result.testResults.filter(hasExecError);
1998
2046
  if (result.numFailedTests > 0 || execErrors.length > 0) {
@@ -2004,15 +2052,15 @@ function formatCompact(result, options) {
2004
2052
  lines.push(...failureLines);
2005
2053
  }
2006
2054
  for (const file of execErrors) lines.push(...formatExecError(file, options));
2007
- const hints = formatCompactLogHints(options);
2055
+ const hints = formatAgentLogHints(options);
2008
2056
  if (hints !== "") lines.push(hints);
2009
2057
  }
2010
2058
  lines.push(...formatSummarySection(result, options));
2011
2059
  return lines.join("\n");
2012
2060
  }
2013
- function formatCompactMultiProject(projects, options) {
2061
+ function formatAgentMultiProject(projects, options) {
2014
2062
  const lines = [];
2015
- for (const { displayName, result } of projects) lines.push(...formatCompactProjectHeader(displayName, result, options));
2063
+ for (const { displayName, result } of projects) lines.push(...formatAgentProjectHeader(displayName, result, options));
2016
2064
  const stats = collectMultiProjectStats(projects);
2017
2065
  if (stats.totalFailed + stats.allExecErrors.length > 0) lines.push(...formatMultiProjectFailures(projects, stats, options));
2018
2066
  lines.push(...formatMultiProjectSummary(stats, options));
@@ -2091,7 +2139,7 @@ function formatSize(bytes) {
2091
2139
  if (bytes < 1024) return `${bytes}b`;
2092
2140
  return `${Math.round(bytes / 1024)}kb`;
2093
2141
  }
2094
- function formatCompactLogHints(options) {
2142
+ function formatAgentLogHints(options) {
2095
2143
  const lines = [];
2096
2144
  if (options.outputFile !== void 0) {
2097
2145
  const size = options.outputFileSize !== void 0 ? ` (${formatSize(options.outputFileSize)})` : "";
@@ -2201,7 +2249,7 @@ function getFailureSnippets(mappedLocations, location, snippetLevel, rootDirecto
2201
2249
  if (location !== void 0) return getFallbackSnippet(location);
2202
2250
  return [];
2203
2251
  }
2204
- function formatCompactFailure(test, filePath, options, snippetLevel) {
2252
+ function formatAgentFailure(test, filePath, options, snippetLevel) {
2205
2253
  const lines = [];
2206
2254
  for (const originalMessage of test.failureMessages) {
2207
2255
  let mappedLocations = [];
@@ -2230,11 +2278,11 @@ function formatFailures(result, totalFailures, options) {
2230
2278
  lines.push(`... ${result.numFailedTests - index} more failures omitted`, "");
2231
2279
  break;
2232
2280
  }
2233
- lines.push(formatCompactFailure(test, filePath, options, snippetLevel));
2281
+ lines.push(formatAgentFailure(test, filePath, options, snippetLevel));
2234
2282
  }
2235
2283
  return lines;
2236
2284
  }
2237
- function formatCompactProjectHeader(displayName, result, options) {
2285
+ function formatAgentProjectHeader(displayName, result, options) {
2238
2286
  const execErrors = result.testResults.filter(hasExecError);
2239
2287
  const hasFailures = result.numFailedTests > 0 || execErrors.length > 0;
2240
2288
  const failedFiles = result.testResults.filter((file) => file.numFailingTests > 0 || hasExecError(file)).length;
@@ -2282,7 +2330,7 @@ function formatMultiProjectFailures(projects, stats, options) {
2282
2330
  ];
2283
2331
  for (const { result } of projects) if (result.numFailedTests > 0) lines.push(...formatFailures(result, totalFailures, options));
2284
2332
  for (const file of stats.allExecErrors) lines.push(...formatExecError(file, options));
2285
- const hints = formatCompactLogHints(options);
2333
+ const hints = formatAgentLogHints(options);
2286
2334
  if (hints !== "") lines.push(hints);
2287
2335
  return lines;
2288
2336
  }
@@ -2394,7 +2442,7 @@ function formatExecuteOutput(options) {
2394
2442
  const resolvedOutputFile = config.outputFile !== void 0 ? path$1.resolve(config.outputFile) : void 0;
2395
2443
  const resolvedGameOutput = config.gameOutput !== void 0 ? path$1.resolve(config.gameOutput) : void 0;
2396
2444
  const agentOptions = findFormatterOptions(config.formatters ?? [], "agent");
2397
- if (agentOptions !== void 0 && !config.verbose) return formatCompact(result, {
2445
+ if (agentOptions !== void 0 && !config.verbose) return formatAgent(result, {
2398
2446
  gameOutput: resolvedGameOutput,
2399
2447
  maxFailures: agentOptions.maxFailures ?? 10,
2400
2448
  outputFile: resolvedOutputFile,
@@ -2487,9 +2535,13 @@ function buildSourceMapper(config, tsconfigMappings) {
2487
2535
  try {
2488
2536
  const rojoResult = rojoProjectSchema(JSON.parse(fs$1.readFileSync(rojoProjectPath, "utf-8")));
2489
2537
  if (rojoResult instanceof type.errors) return;
2538
+ const resolvedTree = resolveNestedProjects(rojoResult.tree, path$1.dirname(rojoProjectPath));
2490
2539
  return createSourceMapper({
2491
2540
  mappings: tsconfigMappings,
2492
- rojoProject: rojoResult
2541
+ rojoProject: {
2542
+ ...rojoResult,
2543
+ tree: resolvedTree
2544
+ }
2493
2545
  });
2494
2546
  } catch {
2495
2547
  return;
@@ -2567,9 +2619,13 @@ function writeSnapshots(snapshotWrites, config, tsconfigMappings) {
2567
2619
  process.stderr.write("Warning: Cannot write snapshots - invalid rojo project\n");
2568
2620
  return;
2569
2621
  }
2622
+ const resolvedTree = resolveNestedProjects(rojoResult.tree, path$1.dirname(rojoProjectPath));
2570
2623
  const resolver = createSnapshotPathResolver({
2571
2624
  mappings: tsconfigMappings,
2572
- rojoProject: rojoResult
2625
+ rojoProject: {
2626
+ ...rojoResult,
2627
+ tree: resolvedTree
2628
+ }
2573
2629
  });
2574
2630
  let written = 0;
2575
2631
  for (const [virtualPath, content] of Object.entries(snapshotWrites)) {
@@ -3027,4 +3083,4 @@ function writeGameOutput(filePath, entries) {
3027
3083
  fs$1.writeFileSync(absolutePath, JSON.stringify(entries, null, 2));
3028
3084
  }
3029
3085
  //#endregion
3030
- export { generateTestScript as A, resolveConfig as C, createOpenCloudBackend as D, OpenCloudBackend as E, defineProject as F, isValidBackend as I, LuauScriptError as L, ROOT_ONLY_KEYS as M, VALID_BACKENDS as N, hashBuffer as O, defineConfig as P, extractJsonFromOutput as R, loadConfig$1 as S, createStudioBackend as T, formatResult as _, formatAnnotations as a, formatBanner as b, execute as c, findFormatterOptions as d, formatJson as f, formatMultiProjectResult as g, formatFailure as h, runTypecheck as i, DEFAULT_CONFIG as j, buildJestArgv as k, formatExecuteOutput as l, formatCompactMultiProject as m, parseGameOutput as n, formatJobSummary as o, writeJsonFile as p, writeGameOutput as r, resolveGitHubActionsOptions as s, formatGameOutputNotice as t, loadCoverageManifest as u, formatTestSummary as v, StudioBackend as w, rojoProjectSchema as x, formatTypecheckSummary as y, parseJestOutput as z };
3086
+ export { hashBuffer as A, extractJsonFromOutput as B, resolveNestedProjects as C, createStudioBackend as D, StudioBackend as E, VALID_BACKENDS as F, defineConfig as I, defineProject as L, generateTestScript as M, DEFAULT_CONFIG as N, OpenCloudBackend as O, ROOT_ONLY_KEYS as P, isValidBackend as R, collectPaths as S, resolveConfig as T, parseJestOutput as V, formatResult as _, formatAnnotations as a, formatBanner as b, execute as c, findFormatterOptions as d, formatJson as f, formatMultiProjectResult as g, formatFailure as h, runTypecheck as i, buildJestArgv as j, createOpenCloudBackend as k, formatExecuteOutput as l, formatAgentMultiProject as m, parseGameOutput as n, formatJobSummary as o, writeJsonFile as p, writeGameOutput as r, resolveGitHubActionsOptions as s, formatGameOutputNotice as t, loadCoverageManifest as u, formatTestSummary as v, loadConfig$1 as w, rojoProjectSchema as x, formatTypecheckSummary as y, LuauScriptError as z };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as defineConfig, C as FormatterEntry, D as ROOT_ONLY_KEYS, E as ProjectTestConfig, M as Argv, O as ResolvedConfig, S as DisplayName, T as ProjectEntry, _ as ResolvedProjectConfig, a as formatExecuteOutput, b as ConfigInput, c as Backend, d as extractJsonFromOutput, f as parseJestOutput, g as TestStatus, h as TestFileResult, i as execute, j as defineProject, k as SnapshotFormatOptions, l as BackendOptions, m as TestCaseResult, n as ExecuteResult, o as TimingResult, p as JestResult, r as FormatOutputOptions, s as SourceMapper, t as ExecuteOptions, u as BackendResult, v as CliOptions, w as InlineProjectConfig, x as DEFAULT_CONFIG, y as Config } from "./executor-DqZE3wME.mjs";
1
+ import { A as defineConfig, C as FormatterEntry, D as ROOT_ONLY_KEYS, E as ProjectTestConfig, M as Argv, O as ResolvedConfig, S as DisplayName, T as ProjectEntry, _ as ResolvedProjectConfig, a as formatExecuteOutput, b as ConfigInput, c as Backend, d as extractJsonFromOutput, f as parseJestOutput, g as TestStatus, h as TestFileResult, i as execute, j as defineProject, k as SnapshotFormatOptions, l as BackendOptions, m as TestCaseResult, n as ExecuteResult, o as TimingResult, p as JestResult, r as FormatOutputOptions, s as SourceMapper, t as ExecuteOptions, u as BackendResult, v as CliOptions, w as InlineProjectConfig, x as DEFAULT_CONFIG, y as Config } from "./executor-CNz6_04-.mjs";
2
2
  import { WebSocket, WebSocketServer } from "ws";
3
3
  import buffer from "node:buffer";
4
4
 
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { A as generateTestScript, C as resolveConfig, D as createOpenCloudBackend, E as OpenCloudBackend, F as defineProject, M as ROOT_ONLY_KEYS, P as defineConfig, R as extractJsonFromOutput, S as loadConfig, T as createStudioBackend, _ as formatResult, a as formatAnnotations, c as execute, f as formatJson, h as formatFailure, i as runTypecheck, j as DEFAULT_CONFIG, k as buildJestArgv, l as formatExecuteOutput, n as parseGameOutput, o as formatJobSummary, p as writeJsonFile, r as writeGameOutput, t as formatGameOutputNotice, v as formatTestSummary, w as StudioBackend, z as parseJestOutput } from "./game-output-BMGxhjkE.mjs";
1
+ import { B as extractJsonFromOutput, D as createStudioBackend, E as StudioBackend, I as defineConfig, L as defineProject, M as generateTestScript, N as DEFAULT_CONFIG, O as OpenCloudBackend, P as ROOT_ONLY_KEYS, T as resolveConfig, V as parseJestOutput, _ as formatResult, a as formatAnnotations, c as execute, f as formatJson, h as formatFailure, i as runTypecheck, j as buildJestArgv, k as createOpenCloudBackend, l as formatExecuteOutput, n as parseGameOutput, o as formatJobSummary, p as writeJsonFile, r as writeGameOutput, t as formatGameOutputNotice, v as formatTestSummary, w as loadConfig } from "./game-output-BL7u7qMT.mjs";
2
2
  export { DEFAULT_CONFIG, OpenCloudBackend, ROOT_ONLY_KEYS, StudioBackend, buildJestArgv, createOpenCloudBackend, createStudioBackend, defineConfig, defineProject, execute, extractJsonFromOutput, formatAnnotations, formatExecuteOutput, formatFailure, formatGameOutputNotice, formatJobSummary, formatJson, formatResult, formatTestSummary, generateTestScript, loadConfig, parseGameOutput, parseJestOutput, resolveConfig, runTypecheck, writeGameOutput, writeJsonFile };
Binary file