@rezless/vitest 0.1.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 (63) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +32 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +140 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/coverage-aggregate.d.ts +22 -0
  8. package/dist/coverage-aggregate.d.ts.map +1 -0
  9. package/dist/coverage-aggregate.js +65 -0
  10. package/dist/coverage-aggregate.js.map +1 -0
  11. package/dist/coverage-config.d.ts +10 -0
  12. package/dist/coverage-config.d.ts.map +1 -0
  13. package/dist/coverage-config.js +12 -0
  14. package/dist/coverage-config.js.map +1 -0
  15. package/dist/coverage-registry.d.ts +13 -0
  16. package/dist/coverage-registry.d.ts.map +1 -0
  17. package/dist/coverage-registry.js +111 -0
  18. package/dist/coverage-registry.js.map +1 -0
  19. package/dist/coverage-setup.d.ts +25 -0
  20. package/dist/coverage-setup.d.ts.map +1 -0
  21. package/dist/coverage-setup.js +42 -0
  22. package/dist/coverage-setup.js.map +1 -0
  23. package/dist/format/console.d.ts +7 -0
  24. package/dist/format/console.d.ts.map +1 -0
  25. package/dist/format/console.js +93 -0
  26. package/dist/format/console.js.map +1 -0
  27. package/dist/format/html.d.ts +11 -0
  28. package/dist/format/html.d.ts.map +1 -0
  29. package/dist/format/html.js +291 -0
  30. package/dist/format/html.js.map +1 -0
  31. package/dist/format/istanbul.d.ts +47 -0
  32. package/dist/format/istanbul.d.ts.map +1 -0
  33. package/dist/format/istanbul.js +50 -0
  34. package/dist/format/istanbul.js.map +1 -0
  35. package/dist/format/lcov.d.ts +19 -0
  36. package/dist/format/lcov.d.ts.map +1 -0
  37. package/dist/format/lcov.js +74 -0
  38. package/dist/format/lcov.js.map +1 -0
  39. package/dist/format/summary.d.ts +25 -0
  40. package/dist/format/summary.d.ts.map +1 -0
  41. package/dist/format/summary.js +48 -0
  42. package/dist/format/summary.js.map +1 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +10 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/loadLinkset.d.ts +38 -0
  48. package/dist/loadLinkset.d.ts.map +1 -0
  49. package/dist/loadLinkset.js +77 -0
  50. package/dist/loadLinkset.js.map +1 -0
  51. package/dist/loadScript.d.ts +24 -0
  52. package/dist/loadScript.d.ts.map +1 -0
  53. package/dist/loadScript.js +45 -0
  54. package/dist/loadScript.js.map +1 -0
  55. package/dist/matchers.d.ts +34 -0
  56. package/dist/matchers.d.ts.map +1 -0
  57. package/dist/matchers.js +120 -0
  58. package/dist/matchers.js.map +1 -0
  59. package/dist/reporter.d.ts +82 -0
  60. package/dist/reporter.d.ts.map +1 -0
  61. package/dist/reporter.js +166 -0
  62. package/dist/reporter.js.map +1 -0
  63. package/package.json +69 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Render an LCOV `lcov.info` file body for one or more coverage reports.
3
+ *
4
+ * LCOV record reference: https://manpages.debian.org/unstable/lcov/geninfo.1.en.html
5
+ *
6
+ * Per file we emit:
7
+ * SF:<path>
8
+ * FN:<line>,<name> — one per function/event
9
+ * FNDA:<hits>,<name>
10
+ * FNF:<total> FNH:<hit>
11
+ * DA:<line>,<count> — one per source line that has at least one statement
12
+ * BRDA:<line>,<block>,<branch>,<taken> — one per (if/loop) outcome
13
+ * BRF:<total> BRH:<hit>
14
+ * LF:<lines> LH:<lines hit>
15
+ * end_of_record
16
+ */
17
+ export function renderLcov(reports) {
18
+ const out = [];
19
+ for (const r of reports) {
20
+ out.push(`SF:${r.filename}`);
21
+ let fnTotal = 0;
22
+ let fnHit = 0;
23
+ for (const fn of r.functions) {
24
+ const label = fn.kind === 'event' ? `${fn.state ?? ''}::${fn.name}` : fn.name;
25
+ out.push(`FN:${fn.line},${label}`);
26
+ fnTotal++;
27
+ if (fn.hits > 0)
28
+ fnHit++;
29
+ }
30
+ for (const fn of r.functions) {
31
+ const label = fn.kind === 'event' ? `${fn.state ?? ''}::${fn.name}` : fn.name;
32
+ out.push(`FNDA:${fn.hits},${label}`);
33
+ }
34
+ out.push(`FNF:${fnTotal}`);
35
+ out.push(`FNH:${fnHit}`);
36
+ // Aggregate statement hits per line: a line is "hit" if any statement on
37
+ // it was hit; the count is the max hit count on the line (preserves
38
+ // tool semantics of "executed at least once"). Lines that only ever
39
+ // see hits=0 are still recorded so they appear as `DA:<line>,0`.
40
+ const lineHits = new Map();
41
+ for (const s of r.statements) {
42
+ const prev = lineHits.get(s.line) ?? 0;
43
+ lineHits.set(s.line, Math.max(prev, s.hits));
44
+ }
45
+ let lf = 0;
46
+ let lh = 0;
47
+ const lines = [...lineHits.entries()].sort((a, b) => a[0] - b[0]);
48
+ for (const [line, hits] of lines) {
49
+ out.push(`DA:${line},${hits}`);
50
+ lf++;
51
+ if (hits > 0)
52
+ lh++;
53
+ }
54
+ let brTotal = 0;
55
+ let brHit = 0;
56
+ for (const b of r.branches) {
57
+ const [t, f] = b.hits;
58
+ out.push(`BRDA:${b.line},${b.id},0,${t}`);
59
+ out.push(`BRDA:${b.line},${b.id},1,${f}`);
60
+ brTotal += 2;
61
+ if (t > 0)
62
+ brHit++;
63
+ if (f > 0)
64
+ brHit++;
65
+ }
66
+ out.push(`BRF:${brTotal}`);
67
+ out.push(`BRH:${brHit}`);
68
+ out.push(`LF:${lf}`);
69
+ out.push(`LH:${lh}`);
70
+ out.push('end_of_record');
71
+ }
72
+ return out.join('\n') + '\n';
73
+ }
74
+ //# sourceMappingURL=lcov.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lcov.js","sourceRoot":"","sources":["../../src/format/lcov.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { CoverageReport } from '@rezless/vm';
2
+ export interface MetricSummary {
3
+ readonly total: number;
4
+ readonly covered: number;
5
+ readonly skipped: 0;
6
+ readonly pct: number;
7
+ }
8
+ export interface FileSummary {
9
+ readonly statements: MetricSummary;
10
+ readonly branches: MetricSummary;
11
+ readonly functions: MetricSummary;
12
+ readonly states: MetricSummary;
13
+ }
14
+ export interface CoverageSummary {
15
+ readonly total: FileSummary;
16
+ readonly [filename: string]: FileSummary;
17
+ }
18
+ /**
19
+ * Render an Istanbul-style coverage-summary.json for LSL coverage. The
20
+ * shape mirrors `@vitest/coverage-v8`'s summary so CI tooling can read
21
+ * either with the same parser, with `states` added as the LSL-specific
22
+ * fourth metric.
23
+ */
24
+ export declare function renderSummary(reports: ReadonlyArray<CoverageReport>): CoverageSummary;
25
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/format/summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAA;CACzC;AAyBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,eAAe,CAmCrF"}
@@ -0,0 +1,48 @@
1
+ function metric(covered, total) {
2
+ const pct = total === 0 ? 100 : (covered / total) * 100;
3
+ return { total, covered, skipped: 0, pct: Number(pct.toFixed(2)) };
4
+ }
5
+ function summarize(r) {
6
+ return {
7
+ statements: metric(r.statements.filter((s) => s.hits > 0).length, r.statements.length),
8
+ branches: metric(r.branches.reduce((a, b) => a + (b.hits[0] > 0 ? 1 : 0) + (b.hits[1] > 0 ? 1 : 0), 0), r.branches.length * 2),
9
+ functions: metric(r.functions.filter((f) => f.hits > 0).length, r.functions.length),
10
+ states: metric(r.states.filter((s) => s.hits > 0).length, r.states.length),
11
+ };
12
+ }
13
+ /**
14
+ * Render an Istanbul-style coverage-summary.json for LSL coverage. The
15
+ * shape mirrors `@vitest/coverage-v8`'s summary so CI tooling can read
16
+ * either with the same parser, with `states` added as the LSL-specific
17
+ * fourth metric.
18
+ */
19
+ export function renderSummary(reports) {
20
+ const out = {};
21
+ let stmtT = 0, stmtC = 0, brT = 0, brC = 0, fnT = 0, fnC = 0, stT = 0, stC = 0;
22
+ for (const r of reports) {
23
+ const s = summarize(r);
24
+ out[r.filename] = s;
25
+ stmtT += s.statements.total;
26
+ stmtC += s.statements.covered;
27
+ brT += s.branches.total;
28
+ brC += s.branches.covered;
29
+ fnT += s.functions.total;
30
+ fnC += s.functions.covered;
31
+ stT += s.states.total;
32
+ stC += s.states.covered;
33
+ }
34
+ // `total` is spread after `out` so a per-file entry whose filename
35
+ // happens to be "total" (e.g. an inline fixture loaded with that name)
36
+ // can't shadow the aggregate. Mirrors istanbul-lib-coverage's own
37
+ // ordering — last-writer-wins puts the aggregate on top.
38
+ return {
39
+ ...out,
40
+ total: {
41
+ statements: metric(stmtC, stmtT),
42
+ branches: metric(brC, brT),
43
+ functions: metric(fnC, fnT),
44
+ states: metric(stC, stT),
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/format/summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import './matchers.js';
2
+ export * from '@rezless/vm';
3
+ export { loadScript } from './loadScript.js';
4
+ export type { LoadScriptInput, InlineScriptInput } from './loadScript.js';
5
+ export { loadLinkset } from './loadLinkset.js';
6
+ export type { LinksetInput, PrimInput, ScriptInput, ScriptSource, InlineSource, LoadedLinkset, } from './loadLinkset.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,YAAY,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,kBAAkB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import './matchers.js';
2
+ export * from '@rezless/vm';
3
+ export { loadScript } from './loadScript.js';
4
+ export { loadLinkset } from './loadLinkset.js';
5
+ // LslCoverageReporter is intentionally NOT re-exported here — importing it
6
+ // pulls in every format module (lcov / istanbul / html / summary / console),
7
+ // `node:fs`, and `node:path`. Test files don't need any of that. Import it
8
+ // from the dedicated subpath in vitest.config.ts only:
9
+ // import { LslCoverageReporter } from '@rezless/vitest/reporter'
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAEtB,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAU9C,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,uDAAuD;AACvD,mEAAmE"}
@@ -0,0 +1,38 @@
1
+ import { Script, Linkset, Prim, type ScriptOptions, type LinksetOptions, type PrimOptions, type InventoryItem } from '@rezless/vm';
2
+ export interface InlineSource {
3
+ /** LSL source code as a string. */
4
+ readonly source: string;
5
+ /** Optional virtual filename for diagnostics; defaults to "<inline>". */
6
+ readonly filename?: string;
7
+ }
8
+ export type ScriptSource = string | InlineSource;
9
+ export interface ScriptInput extends Omit<ScriptOptions, 'source'> {
10
+ /** Path or inline source. */
11
+ readonly source: ScriptSource;
12
+ /** Inventory name override (defaults to scriptName / filename basename). */
13
+ readonly name?: string;
14
+ }
15
+ export interface PrimInput extends PrimOptions {
16
+ /** Scripts hosted on this prim. */
17
+ readonly scripts?: ReadonlyArray<ScriptInput>;
18
+ /** Non-script inventory items (notecards, textures, …). */
19
+ readonly inventory?: ReadonlyArray<InventoryItem>;
20
+ }
21
+ export interface LinksetInput extends LinksetOptions {
22
+ readonly prims: ReadonlyArray<PrimInput>;
23
+ }
24
+ export interface LoadedLinkset {
25
+ readonly linkset: Linkset;
26
+ readonly prims: ReadonlyArray<Prim>;
27
+ /** Flat name → Script lookup across all prims. */
28
+ readonly scripts: Readonly<Record<string, Script>>;
29
+ }
30
+ /**
31
+ * Build a multi-prim, multi-script Linkset for tests. Each prim hosts one or
32
+ * more scripts; the returned `scripts` map keys by inventory name.
33
+ *
34
+ * Existing single-script tests continue to use `loadScript`; this is the
35
+ * additive multi-script path.
36
+ */
37
+ export declare function loadLinkset(input: LinksetInput): Promise<LoadedLinkset>;
38
+ //# sourceMappingURL=loadLinkset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadLinkset.d.ts","sourceRoot":"","sources":["../src/loadLinkset.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,OAAO,EACP,IAAI,EACJ,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAA;AAIpB,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,CAAA;AAEhD,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC;IAChE,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,mCAAmC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IAC7C,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,CAAA;IACnC,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACnD;AASD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAmD7E"}
@@ -0,0 +1,77 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { parse, LslParseError } from '@rezless/parser';
3
+ import { Script, Linkset, Prim, } from '@rezless/vm';
4
+ import { isCoverageEnabled } from './coverage-config.js';
5
+ import { registerScript } from './coverage-registry.js';
6
+ async function readScriptSource(src) {
7
+ if (typeof src === 'string') {
8
+ return { source: await readFile(src, 'utf8'), filename: src };
9
+ }
10
+ return { source: src.source, filename: src.filename ?? '<inline>' };
11
+ }
12
+ /**
13
+ * Build a multi-prim, multi-script Linkset for tests. Each prim hosts one or
14
+ * more scripts; the returned `scripts` map keys by inventory name.
15
+ *
16
+ * Existing single-script tests continue to use `loadScript`; this is the
17
+ * additive multi-script path.
18
+ */
19
+ export async function loadLinkset(input) {
20
+ const linksetOpts = {};
21
+ if (input.owner !== undefined)
22
+ linksetOpts.owner = input.owner;
23
+ const linkset = new Linkset(linksetOpts);
24
+ // Object.create(null) avoids prototype keys ('toString', 'constructor', …)
25
+ // false-positive-tripping the duplicate-name check below.
26
+ const scripts = Object.create(null);
27
+ const prims = [];
28
+ for (const primInput of input.prims) {
29
+ const primOpts = {};
30
+ if (primInput.key !== undefined)
31
+ primOpts.key = primInput.key;
32
+ if (primInput.name !== undefined)
33
+ primOpts.name = primInput.name;
34
+ if (primInput.description !== undefined)
35
+ primOpts.description = primInput.description;
36
+ const prim = new Prim(primOpts);
37
+ linkset.addPrim(prim);
38
+ prims.push(prim);
39
+ for (const item of primInput.inventory ?? []) {
40
+ prim.addInventory(item);
41
+ }
42
+ for (const sInput of primInput.scripts ?? []) {
43
+ const { source, filename } = await readScriptSource(sInput.source);
44
+ const { script: ast, diagnostics } = parse(source, filename);
45
+ const errors = diagnostics.filter((d) => d.severity === 'error');
46
+ if (errors.length > 0)
47
+ throw new LslParseError(errors);
48
+ // Build options without the loadLinkset-only fields. The inventory
49
+ // `name` is also surfaced as `scriptName` so llGetScriptName /
50
+ // llSetScriptState / llResetOtherScript all agree on the script's
51
+ // identity.
52
+ const { source: _src, name: invName, ...rest } = sInput;
53
+ const coverage = rest.coverage ?? isCoverageEnabled();
54
+ const opts = { ...rest, filename, host: prim, source, coverage };
55
+ const inventoryName = invName ?? rest.scriptName;
56
+ if (inventoryName !== undefined) {
57
+ ;
58
+ opts.scriptName =
59
+ inventoryName;
60
+ }
61
+ const s = new Script(ast, opts);
62
+ if (coverage)
63
+ registerScript(s);
64
+ const finalName = inventoryName ?? s.scriptName;
65
+ const item = prim.inventory.find((it) => it.script === s);
66
+ if (item)
67
+ item.name = finalName;
68
+ if (finalName in scripts) {
69
+ throw new Error(`loadLinkset: duplicate script name '${finalName}' across prims; ` +
70
+ `give each script a unique inventory name to avoid silent overwrites`);
71
+ }
72
+ scripts[finalName] = s;
73
+ }
74
+ }
75
+ return { linkset, prims, scripts };
76
+ }
77
+ //# sourceMappingURL=loadLinkset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadLinkset.js","sourceRoot":"","sources":["../src/loadLinkset.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { Script } from '@rezless/vm';
2
+ import type { ScriptOptions } from '@rezless/vm';
3
+ export interface InlineScriptInput extends ScriptOptions {
4
+ /** LSL source code as a string. */
5
+ readonly source: string;
6
+ /** Optional virtual filename for diagnostics; defaults to "<inline>". */
7
+ readonly filename?: string;
8
+ }
9
+ export type LoadScriptInput = string | InlineScriptInput;
10
+ /**
11
+ * Parse and instantiate an LSL script ready for testing.
12
+ *
13
+ * Pass a file path to load from disk, or `{ source, ...options }` for an
14
+ * inline string. Options propagate to the Script (random seed, owner key,
15
+ * object/script name).
16
+ *
17
+ * Coverage activates when any of: `coverage: true` in options, the Vitest
18
+ * coverage reporter has been installed, or `LSL_COVERAGE=1` in the env.
19
+ *
20
+ * Parse errors throw `LslParseError`, which Vitest renders with the
21
+ * offending `file:line:col`.
22
+ */
23
+ export declare function loadScript(input: LoadScriptInput): Promise<Script>;
24
+ //# sourceMappingURL=loadScript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadScript.d.ts","sourceRoot":"","sources":["../src/loadScript.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,iBAAiB,CAAA;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBxE"}
@@ -0,0 +1,45 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { parse, LslParseError } from '@rezless/parser';
3
+ import { Script } from '@rezless/vm';
4
+ import { isCoverageEnabled } from './coverage-config.js';
5
+ import { registerScript } from './coverage-registry.js';
6
+ /**
7
+ * Parse and instantiate an LSL script ready for testing.
8
+ *
9
+ * Pass a file path to load from disk, or `{ source, ...options }` for an
10
+ * inline string. Options propagate to the Script (random seed, owner key,
11
+ * object/script name).
12
+ *
13
+ * Coverage activates when any of: `coverage: true` in options, the Vitest
14
+ * coverage reporter has been installed, or `LSL_COVERAGE=1` in the env.
15
+ *
16
+ * Parse errors throw `LslParseError`, which Vitest renders with the
17
+ * offending `file:line:col`.
18
+ */
19
+ export async function loadScript(input) {
20
+ let source;
21
+ let filename;
22
+ let baseOptions;
23
+ if (typeof input === 'string') {
24
+ source = await readFile(input, 'utf8');
25
+ filename = input;
26
+ baseOptions = { filename };
27
+ }
28
+ else {
29
+ source = input.source;
30
+ filename = input.filename ?? '<inline>';
31
+ baseOptions = { ...input, filename };
32
+ }
33
+ const { script: ast, diagnostics } = parse(source, filename);
34
+ const errors = diagnostics.filter((d) => d.severity === 'error');
35
+ if (errors.length > 0) {
36
+ throw new LslParseError(errors);
37
+ }
38
+ const coverage = baseOptions.coverage ?? isCoverageEnabled();
39
+ const options = { ...baseOptions, source, coverage };
40
+ const script = new Script(ast, options);
41
+ if (coverage)
42
+ registerScript(script);
43
+ return script;
44
+ }
45
+ //# sourceMappingURL=loadScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadScript.js","sourceRoot":"","sources":["../src/loadScript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAWvD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,IAAI,MAAc,CAAA;IAClB,IAAI,QAAgB,CAAA;IACpB,IAAI,WAA0B,CAAA;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QACtC,QAAQ,GAAG,KAAK,CAAA;QAChB,WAAW,GAAG,EAAE,QAAQ,EAAE,CAAA;IAC5B,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;QACrB,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,UAAU,CAAA;QACvC,WAAW,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAA;IACtC,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAC5D,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAA;IAChE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;IACD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,IAAI,iBAAiB,EAAE,CAAA;IAC5D,MAAM,OAAO,GAAkB,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;IACnE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACvC,IAAI,QAAQ;QAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IACpC,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,34 @@
1
+ declare module 'vitest' {
2
+ interface Assertion<T = any> {
3
+ toHaveSaid(channel: number, text: string): T;
4
+ toBeInState(name: string): T;
5
+ toHaveCalledFunction(name: string, ...args: unknown[]): T;
6
+ toHaveSentHTTP(expected: {
7
+ url?: string;
8
+ method?: string;
9
+ body?: string;
10
+ }): T;
11
+ toHaveListened(channel: number, filter?: {
12
+ name?: string;
13
+ key?: string;
14
+ message?: string;
15
+ }): T;
16
+ }
17
+ interface AsymmetricMatchersContaining {
18
+ toHaveSaid(channel: number, text: string): unknown;
19
+ toBeInState(name: string): unknown;
20
+ toHaveCalledFunction(name: string, ...args: unknown[]): unknown;
21
+ toHaveSentHTTP(expected: {
22
+ url?: string;
23
+ method?: string;
24
+ body?: string;
25
+ }): unknown;
26
+ toHaveListened(channel: number, filter?: {
27
+ name?: string;
28
+ key?: string;
29
+ message?: string;
30
+ }): unknown;
31
+ }
32
+ }
33
+ export {};
34
+ //# sourceMappingURL=matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"AAqKA,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,SAAS,CAAC,CAAC,GAAG,GAAG;QACzB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAAA;QAC5C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAA;QAC5B,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QACzD,cAAc,CAAC,QAAQ,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,CAAC,CAAA;QAC7E,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,CAAC,CAAA;KAC/F;IACD,UAAU,4BAA4B;QACpC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;QAClD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;QAClC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;QAC/D,cAAc,CAAC,QAAQ,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAA;QACnF,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAA;KACrG;CACF"}
@@ -0,0 +1,120 @@
1
+ import { expect } from 'vitest';
2
+ function isScript(value) {
3
+ return (typeof value === 'object' &&
4
+ value !== null &&
5
+ 'chat' in value &&
6
+ 'currentState' in value &&
7
+ 'callsOf' in value);
8
+ }
9
+ expect.extend({
10
+ toHaveSaid(received, channel, text) {
11
+ if (!isScript(received)) {
12
+ return {
13
+ pass: false,
14
+ message: () => `expected a Script, received ${typeof received}`,
15
+ };
16
+ }
17
+ const matched = received.chat.some((c) => c.channel === channel && c.text === text);
18
+ return {
19
+ pass: matched,
20
+ message: () => matched
21
+ ? `expected script not to have said ${JSON.stringify(text)} on channel ${channel}`
22
+ : `expected script to have said ${JSON.stringify(text)} on channel ${channel}\n actual chat: ${JSON.stringify(received.chat, null, 2)}`,
23
+ actual: received.chat,
24
+ expected: { channel, text },
25
+ };
26
+ },
27
+ toBeInState(received, name) {
28
+ if (!isScript(received)) {
29
+ return {
30
+ pass: false,
31
+ message: () => `expected a Script, received ${typeof received}`,
32
+ };
33
+ }
34
+ const pass = received.currentState === name;
35
+ return {
36
+ pass,
37
+ message: () => pass
38
+ ? `expected script not to be in state '${name}'`
39
+ : `expected script to be in state '${name}', actual: '${received.currentState}'`,
40
+ actual: received.currentState,
41
+ expected: name,
42
+ };
43
+ },
44
+ toHaveCalledFunction(received, name, ...args) {
45
+ if (!isScript(received)) {
46
+ return {
47
+ pass: false,
48
+ message: () => `expected a Script, received ${typeof received}`,
49
+ };
50
+ }
51
+ const calls = received.callsOf(name);
52
+ if (calls.length === 0) {
53
+ return {
54
+ pass: false,
55
+ message: () => `expected script to have called ${name}, but it was never called`,
56
+ };
57
+ }
58
+ if (args.length === 0) {
59
+ return {
60
+ pass: true,
61
+ message: () => `expected script not to have called ${name}`,
62
+ };
63
+ }
64
+ const matched = calls.some((c) => c.args.length === args.length &&
65
+ c.args.every((a, i) => Object.is(a, args[i]) || JSON.stringify(a) === JSON.stringify(args[i])));
66
+ return {
67
+ pass: matched,
68
+ message: () => matched
69
+ ? `expected script not to have called ${name}(${args.map((a) => JSON.stringify(a)).join(', ')})`
70
+ : `expected script to have called ${name}(${args.map((a) => JSON.stringify(a)).join(', ')})\n actual calls: ${JSON.stringify(calls, null, 2)}`,
71
+ actual: calls,
72
+ expected: { name, args },
73
+ };
74
+ },
75
+ toHaveSentHTTP(received, expected) {
76
+ if (!isScript(received)) {
77
+ return {
78
+ pass: false,
79
+ message: () => `expected a Script, received ${typeof received}`,
80
+ };
81
+ }
82
+ const reqs = received.httpRequests;
83
+ const matched = reqs.some((r) => (expected.url === undefined || r.url === expected.url) &&
84
+ (expected.method === undefined || r.method === expected.method) &&
85
+ (expected.body === undefined || r.body === expected.body));
86
+ return {
87
+ pass: matched,
88
+ message: () => matched
89
+ ? `expected script not to have sent HTTP ${JSON.stringify(expected)}`
90
+ : `expected script to have sent HTTP ${JSON.stringify(expected)}\n actual requests: ${JSON.stringify(reqs, null, 2)}`,
91
+ actual: reqs,
92
+ expected,
93
+ };
94
+ },
95
+ toHaveListened(received, channel, filter) {
96
+ if (!isScript(received)) {
97
+ return {
98
+ pass: false,
99
+ message: () => `expected a Script, received ${typeof received}`,
100
+ };
101
+ }
102
+ const NULL_KEY = '00000000-0000-0000-0000-000000000000';
103
+ const matched = received.listens.some((l) => l.active &&
104
+ l.channel === channel &&
105
+ (filter?.name === undefined || l.name === filter.name) &&
106
+ (filter?.key === undefined ||
107
+ l.key === filter.key ||
108
+ (filter.key === '' && (l.key === '' || l.key === NULL_KEY))) &&
109
+ (filter?.message === undefined || l.message === filter.message));
110
+ return {
111
+ pass: matched,
112
+ message: () => matched
113
+ ? `expected script not to have listened on channel ${channel}`
114
+ : `expected script to have listened on channel ${channel}${filter ? ` with filter ${JSON.stringify(filter)}` : ''}\n actual listens: ${JSON.stringify(received.listens, null, 2)}`,
115
+ actual: received.listens,
116
+ expected: { channel, filter },
117
+ };
118
+ },
119
+ });
120
+ //# sourceMappingURL=matchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.js","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"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"}