@isentinel/jest-roblox 0.2.3 → 0.2.5
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 +6 -1
- package/dist/cli.mjs +2 -2
- package/dist/sea/jest-roblox +0 -0
- package/dist/sea-entry.cjs +7 -5
- package/package.json +3 -3
- package/plugin/JestRobloxRunner.rbxm +0 -0
- package/plugin/src/test-in-run-mode.server.luau +37 -11
package/README.md
CHANGED
|
@@ -227,6 +227,11 @@ Connects to Roblox Studio over WebSocket. Faster than Open Cloud (no upload
|
|
|
227
227
|
step), but Studio must be open with the plugin running. Studio doesn't expose which place is open, so
|
|
228
228
|
multiple concurrent projects aren't supported yet.
|
|
229
229
|
|
|
230
|
+
> [!NOTE]
|
|
231
|
+
> For `--coverage`, prefer `--backend open-cloud` since the coverage output is
|
|
232
|
+
> built to a separate output under `.jest-roblox-coverage/` that is likely not
|
|
233
|
+
> the studio place being served.
|
|
234
|
+
|
|
230
235
|
Install the plugin with [Drillbit](https://github.com/jacktabscode/drillbit):
|
|
231
236
|
|
|
232
237
|
#### Configuration file
|
|
@@ -235,7 +240,7 @@ Create a file named drillbit.toml in your project's directory.
|
|
|
235
240
|
|
|
236
241
|
```toml
|
|
237
242
|
[plugins.jest_roblox]
|
|
238
|
-
github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.2.
|
|
243
|
+
github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.2.5/JestRobloxRunner.rbxm"
|
|
239
244
|
```
|
|
240
245
|
|
|
241
246
|
Then run `drillbit` and it will download the plugin and install it in Studio for you.
|
package/dist/cli.mjs
CHANGED
|
@@ -23,7 +23,7 @@ import istanbulCoverage from "istanbul-lib-coverage";
|
|
|
23
23
|
import istanbulReport from "istanbul-lib-report";
|
|
24
24
|
import istanbulReports from "istanbul-reports";
|
|
25
25
|
//#region package.json
|
|
26
|
-
var version = "0.2.
|
|
26
|
+
var version = "0.2.5";
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/backends/auto.ts
|
|
29
29
|
var StudioWithFallback = class {
|
|
@@ -160,7 +160,7 @@ function evalTable(entries) {
|
|
|
160
160
|
}
|
|
161
161
|
//#endregion
|
|
162
162
|
//#region src/luau/parse-ast.luau
|
|
163
|
-
var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.
|
|
163
|
+
var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readFileToString(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listDirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\n-- Optional 3rd arg: path to skip list JSON file.\n-- Skipped files are still included in the file list but not parsed.\nlocal skipListPath = userArgs[3]\nlocal skipSet: { [string]: boolean } = {}\nif skipListPath then\n local skipJson = fs.readFileToString(skipListPath)\n local skipList = json.deserialize(skipJson) :: { string }\n for _, entry in skipList do\n skipSet[entry] = true\n end\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n if skipSet[relativePath] then\n continue\n end\n\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readFileToString(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createDirectory(dir, { makeParents = true })\n end\n\n fs.writeStringToFile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.Array))\n";
|
|
164
164
|
//#endregion
|
|
165
165
|
//#region src/config/luau-config-loader.ts
|
|
166
166
|
let cachedTemporaryDirectory$1;
|
package/dist/sea/jest-roblox
CHANGED
|
Binary file
|
package/dist/sea-entry.cjs
CHANGED
|
@@ -7633,7 +7633,7 @@ function C$5({ force: e } = {}) {
|
|
|
7633
7633
|
var y$4 = C$5();
|
|
7634
7634
|
//#endregion
|
|
7635
7635
|
//#region package.json
|
|
7636
|
-
var version = "0.2.
|
|
7636
|
+
var version = "0.2.5";
|
|
7637
7637
|
//#endregion
|
|
7638
7638
|
//#region node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/constants.js
|
|
7639
7639
|
var require_constants$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -31896,7 +31896,7 @@ function evalTable(entries) {
|
|
|
31896
31896
|
}
|
|
31897
31897
|
//#endregion
|
|
31898
31898
|
//#region src/luau/parse-ast.luau
|
|
31899
|
-
var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.
|
|
31899
|
+
var parse_ast_default = "local fs = require(\"@std/fs\")\nlocal json = require(\"@std/json\")\nlocal process = require(\"@std/process\")\nlocal syntax = require(\"@std/syntax\")\n\nlocal rawArgs = process.args\nlocal userArgs: { string } = {}\nlocal pastSeparator = false\n\nfor _, arg in rawArgs do\n if pastSeparator then\n table.insert(userArgs, arg)\n elseif arg == \"--\" then\n pastSeparator = true\n end\nend\n\nlocal luauRoot = userArgs[1]\nif not luauRoot then\n error(\"Usage: lute run parse-ast.luau -- <file.luau | luau-root> [output-dir]\")\nend\n\nluauRoot = string.gsub(luauRoot, \"\\\\\", \"/\")\n\n-- Fields to keep per AST tag (beyond tag/kind/location which are always kept).\n-- Tags shared by stat/expr variants are merged — nil fields are harmless.\nlocal KEEP: { [string]: { string } } = {\n assign = { \"values\", \"variables\" },\n binary = { \"lhsOperand\", \"rhsOperand\" },\n block = { \"statements\" },\n boolean = { \"value\" },\n call = { \"arguments\", \"func\" },\n cast = { \"operand\" },\n compoundassign = { \"value\", \"variable\" },\n conditional = { \"condition\", \"thenBlock\", \"elseifs\", \"elseBlock\", \"thenExpr\", \"elseExpr\" },\n [\"do\"] = { \"body\" },\n expression = { \"expression\" },\n [\"for\"] = { \"body\", \"from\", \"to\", \"step\" },\n forin = { \"body\", \"values\" },\n [\"function\"] = { \"body\", \"name\", \"func\" },\n global = { \"name\" },\n group = { \"expression\" },\n index = { \"expression\", \"index\" },\n indexname = { \"expression\", \"accessor\", \"index\" },\n instantiate = { \"expr\" },\n interpolatedstring = { \"expressions\" },\n [\"local\"] = { \"values\", \"variables\" },\n localfunction = { \"name\", \"func\" },\n number = { \"value\" },\n [\"repeat\"] = { \"body\", \"condition\" },\n [\"return\"] = { \"expressions\" },\n string = { \"text\" },\n table = { \"entries\" },\n unary = { \"operand\" },\n [\"while\"] = { \"body\", \"condition\" },\n}\n\nlocal function strip(value: any): any\n if type(value) ~= \"table\" then\n return value\n end\n\n -- LuauSpan — has beginLine, no tag\n if value.beginLine ~= nil then\n return value\n end\n\n -- Token — has text but no tag, reduce to {text}\n if value.text ~= nil and value.tag == nil then\n return { text = value.text }\n end\n\n -- AST node — has tag, keep only allowlisted fields\n if value.tag ~= nil then\n local result = { tag = value.tag, kind = value.kind, location = value.location }\n local fields = KEEP[value.tag :: string]\n if fields then\n for _, field in fields do\n if value[field] ~= nil then\n result[field] = strip(value[field])\n end\n end\n end\n\n return result\n end\n\n -- Other tables (arrays, Pairs, ElseIf structs) — recurse all fields\n local result: any = {}\n for k, v in value do\n result[k] = strip(v)\n end\n\n return result\nend\n\n-- Single-file mode: parse one file, print stripped AST to stdout\nif string.sub(luauRoot, -5) == \".luau\" or string.sub(luauRoot, -4) == \".lua\" then\n local source = fs.readFileToString(luauRoot)\n local parseResult = syntax.parse(source)\n print(json.serialize(strip(parseResult.root)))\n return\nend\n\nlocal outputDir = userArgs[2]\nif not outputDir then\n error(\"Usage: lute run parse-ast.luau -- <luau-root> <output-dir>\")\nend\n\noutputDir = string.gsub(outputDir, \"\\\\\", \"/\")\n\n-- Discover .luau files recursively, skipping node_modules, dot dirs, spec/test files\nlocal function discoverFiles(directory: string, relativeTo: string, results: { string })\n local entries = fs.listDirectory(directory)\n for _, entry in entries do\n local fullPath = directory .. \"/\" .. entry.name\n if entry.type == \"dir\" then\n if entry.name == \"node_modules\" or entry.name == \".jest-roblox-coverage\" then\n continue\n end\n\n if string.sub(entry.name, 1, 1) == \".\" then\n continue\n end\n\n discoverFiles(fullPath, relativeTo, results)\n elseif\n entry.type == \"file\"\n and (string.sub(entry.name, -5) == \".luau\" or string.sub(entry.name, -4) == \".lua\")\n then\n if\n string.sub(entry.name, -10) == \".spec.luau\"\n or string.sub(entry.name, -10) == \".test.luau\"\n or string.sub(entry.name, -9) == \".spec.lua\"\n or string.sub(entry.name, -9) == \".test.lua\"\n or string.sub(entry.name, -10) == \".snap.luau\"\n or string.sub(entry.name, -9) == \".snap.lua\"\n then\n continue\n end\n\n -- Compute relative path\n local relative = string.sub(fullPath, #relativeTo + 2)\n table.insert(results, relative)\n end\n end\nend\n\nlocal function dirname(filepath: string): string\n local pos = string.find(filepath, \"/[^/]*$\")\n if pos then\n return string.sub(filepath, 1, pos - 1)\n end\n\n return \"\"\nend\n\n-- Optional 3rd arg: path to skip list JSON file.\n-- Skipped files are still included in the file list but not parsed.\nlocal skipListPath = userArgs[3]\nlocal skipSet: { [string]: boolean } = {}\nif skipListPath then\n local skipJson = fs.readFileToString(skipListPath)\n local skipList = json.deserialize(skipJson) :: { string }\n for _, entry in skipList do\n skipSet[entry] = true\n end\nend\n\nlocal files: { string } = {}\ndiscoverFiles(luauRoot, luauRoot, files)\n\n-- Parse, strip, and write per-file AST JSON\nfor _, relativePath in files do\n if skipSet[relativePath] then\n continue\n end\n\n local fullPath = luauRoot .. \"/\" .. relativePath\n local source = fs.readFileToString(fullPath)\n local parseResult = syntax.parse(source)\n local stripped = strip(parseResult.root)\n\n local outPath = outputDir .. \"/\" .. relativePath .. \".json\"\n local dir = dirname(outPath)\n if dir ~= \"\" then\n fs.createDirectory(dir, { makeParents = true })\n end\n\n fs.writeStringToFile(outPath, json.serialize(stripped))\nend\n\n-- Print file list to stdout (tiny — just paths)\nprint(json.serialize(files :: json.Array))\n";
|
|
31900
31900
|
//#endregion
|
|
31901
31901
|
//#region src/config/luau-config-loader.ts
|
|
31902
31902
|
let cachedTemporaryDirectory$1;
|
|
@@ -39567,11 +39567,13 @@ var require_ensure = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
39567
39567
|
};
|
|
39568
39568
|
}));
|
|
39569
39569
|
//#endregion
|
|
39570
|
-
//#region node_modules/.pnpm/jsonfile@6.2.
|
|
39570
|
+
//#region node_modules/.pnpm/jsonfile@6.2.1/node_modules/jsonfile/utils.js
|
|
39571
39571
|
var require_utils$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
39572
39572
|
function stringify(obj, { EOL = "\n", finalEOL = true, replacer = null, spaces } = {}) {
|
|
39573
39573
|
const EOF = finalEOL ? EOL : "";
|
|
39574
|
-
|
|
39574
|
+
const str = JSON.stringify(obj, replacer, spaces);
|
|
39575
|
+
if (str === void 0) throw new TypeError(`Converting ${typeof obj} value to JSON is not supported`);
|
|
39576
|
+
return str.replace(/\n/g, EOL) + EOF;
|
|
39575
39577
|
}
|
|
39576
39578
|
function stripBom(content) {
|
|
39577
39579
|
if (Buffer.isBuffer(content)) content = content.toString("utf8");
|
|
@@ -39583,7 +39585,7 @@ var require_utils$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
39583
39585
|
};
|
|
39584
39586
|
}));
|
|
39585
39587
|
//#endregion
|
|
39586
|
-
//#region node_modules/.pnpm/jsonfile@6.2.
|
|
39588
|
+
//#region node_modules/.pnpm/jsonfile@6.2.1/node_modules/jsonfile/index.js
|
|
39587
39589
|
var require_jsonfile$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
39588
39590
|
let _fs;
|
|
39589
39591
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isentinel/jest-roblox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Jest-compatible CLI for running roblox-ts tests via Roblox Open Cloud",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jest",
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
"type-fest": "5.5.0",
|
|
87
87
|
"typescript": "5.9.3",
|
|
88
88
|
"vitest": "4.1.2",
|
|
89
|
-
"@isentinel/luau-ast": "0.1.0",
|
|
90
89
|
"@isentinel/roblox-runner": "0.1.0",
|
|
91
|
-
"@isentinel/rojo-utils": "0.1.0"
|
|
90
|
+
"@isentinel/rojo-utils": "0.1.0",
|
|
91
|
+
"@isentinel/luau-ast": "0.1.0"
|
|
92
92
|
},
|
|
93
93
|
"engines": {
|
|
94
94
|
"node": ">=24.10.0"
|
|
Binary file
|
|
@@ -7,6 +7,18 @@ if not RunService:IsRunning() then
|
|
|
7
7
|
return
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
local function endWithError(err: string): ()
|
|
11
|
+
local ok, endErr = pcall(function()
|
|
12
|
+
StudioTestService:EndTest({
|
|
13
|
+
jestOutput = HttpService:JSONEncode({ success = false, err = err }),
|
|
14
|
+
gameOutput = "[]",
|
|
15
|
+
})
|
|
16
|
+
end)
|
|
17
|
+
if not ok then
|
|
18
|
+
warn("[jest-roblox] EndTest failed: " .. tostring(endErr))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
10
22
|
local testArgs = StudioTestService:GetTestArgs()
|
|
11
23
|
if testArgs == nil then
|
|
12
24
|
for _ = 1, 50 do
|
|
@@ -18,29 +30,43 @@ if testArgs == nil then
|
|
|
18
30
|
end
|
|
19
31
|
end
|
|
20
32
|
|
|
21
|
-
if testArgs == nil
|
|
33
|
+
if testArgs == nil then
|
|
34
|
+
endWithError("StudioTestService:GetTestArgs() returned nil after 50 polls (5s)")
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if testArgs.config == nil or testArgs.config.configs == nil then
|
|
39
|
+
local keysOk, keys = pcall(HttpService.JSONEncode, HttpService, testArgs)
|
|
40
|
+
endWithError(
|
|
41
|
+
"testArgs.config.configs is nil. Keys: " .. (if keysOk then keys else "<unencodable>")
|
|
42
|
+
)
|
|
22
43
|
return
|
|
23
44
|
end
|
|
24
45
|
|
|
46
|
+
local configs = testArgs.config.configs
|
|
47
|
+
|
|
25
48
|
local loadStringEnabled = pcall(function()
|
|
26
49
|
loadstring("return true")
|
|
27
50
|
end)
|
|
28
51
|
|
|
29
52
|
if not loadStringEnabled then
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
endWithError("LoadString must be enabled in ServerScriptService to run tests")
|
|
54
|
+
return
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
local requireOk, Runner = pcall(require, script.Parent.shared.runner)
|
|
58
|
+
if not requireOk then
|
|
59
|
+
endWithError("Failed to require shared.runner: " .. tostring(Runner))
|
|
37
60
|
return
|
|
38
61
|
end
|
|
39
62
|
|
|
40
|
-
local
|
|
41
|
-
|
|
63
|
+
local runOk, entriesOrErr = pcall(Runner.runProjects, script, configs)
|
|
64
|
+
if not runOk then
|
|
65
|
+
endWithError("Runner.runProjects threw: " .. tostring(entriesOrErr))
|
|
66
|
+
return
|
|
67
|
+
end
|
|
42
68
|
|
|
43
69
|
StudioTestService:EndTest({
|
|
44
|
-
jestOutput = HttpService:JSONEncode({ entries =
|
|
70
|
+
jestOutput = HttpService:JSONEncode({ entries = entriesOrErr }),
|
|
45
71
|
gameOutput = "[]",
|
|
46
72
|
})
|