zoroaster
Version:
The 2020 Most Modern Testing Framework For Node.JS With Test Contexts (Reusable BeforeEach / AfterEach Via Separate Files); Masks (Inputs/Outputs In Non-Js Files) And Fork Testing; Interactive Snapshots.
1,139 lines (1,135 loc) • 32.7 kB
JavaScript
const path = require('path');
const os = require('os');
const fs = require('fs');
const stream = require('stream');
const util = require('util');
const assert = require('assert');
const readline = require('readline');
const w = os.EOL, aa = os.homedir;
const ba = /\s+at.*(?:\(|\s)(.*)\)?/, ca = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:IGNORED_MODULES)\/.*)?\w+)\.js:\d+:\d+)|native)/, x = a => {
const {pretty:b = !1, ignoredModules:c = ["pirates", "@artdeco/pirates"]} = {}, d = c.join("|"), e = new RegExp(ca.source.replace("IGNORED_MODULES", d));
return a.replace(/\\/g, "/").split("\n").filter(f => {
f = f.match(ba);
if (null === f || !f[1]) {
return !0;
}
f = f[1];
return f.includes(".app/Contents/Resources/electron.asar") || f.includes(".app/Contents/Resources/default_app.asar") ? !1 : !e.test(f);
}).filter(f => f.trim()).map(f => {
if (b) {
const g = aa().replace(/\\/g, "/");
return f.replace(/\s+at.*(?:\(|\s)(.*)\)?/, (h, k) => h.replace(k, k.replace(g, "~")));
}
return f;
}).join("\n");
};
const da = (a, b, c, d = !1, e = !1) => {
const f = c ? new RegExp(`^-(${c}|-${b})$`) : new RegExp(`^--${b}$`);
b = a.findIndex(g => f.test(g));
if (-1 == b) {
return {argv:a};
}
if (d) {
return {value:!0, index:b, length:1};
}
d = a[b + 1];
if (!d || "string" == typeof d && d.startsWith("--")) {
return {argv:a};
}
e && (d = parseInt(d, 10));
return {value:d, index:b, length:2};
}, ea = a => {
const b = [];
for (let c = 0; c < a.length; c++) {
const d = a[c];
if (d.startsWith("-")) {
break;
}
b.push(d);
}
return b;
}, fa = () => {
var a = y;
return Object.keys(a).reduce((b, c) => {
const d = a[c];
if ("string" == typeof d) {
return b[`-${d}`] = "", b;
}
c = d.command ? c : `--${c}`;
d.short && (c = `${c}, -${d.short}`);
let e = d.description;
d.default && (e = `${e}\nDefault: ${d.default}.`);
b[c] = e;
return b;
}, {});
};
const y = {tests:{description:"The location of the test suite directory or file.", command:!0, multiple:!0}, alamode:{description:"Enable import/export transpilation with \u00c0LaMode.", boolean:!0, short:"a"}, watch:{description:"Start the runner in _watch_ mode (rerun on changes).", boolean:!0, short:"w"}, timeout:{description:"Timeout for tests in ms.", number:!0, default:"2000", short:"t"}, snapshot:{description:"The location of the snapshot dir.", default:"test/snapshot", short:"s"}, snapshotRoot:{description:"The list of folders that will be roots in the snapshot dir.",
default:"test/spec,test/mask", short:"r"}, interactive:{description:"Run in interactive mode, allowing to update snapshots\nand mask results when they don't match currently expected.", boolean:!0, short:"i"}, environment:{description:"\u00c0LaMode environment for applying settings via `.alamoderc.json`.\nEquivalent to setting `ALAMODE_ENV` env variable.", short:"e"}, babel:{description:"Require `@babel/register` (needs to be installed).", boolean:!0, short:"b"}, version:{description:"Show the current version.",
boolean:!0, short:"v"}, help:{description:"Display help information.", boolean:!0, short:"h"}}, z = function(a = {}, b = process.argv) {
let [, , ...c] = b;
const d = ea(c);
c = c.slice(d.length);
a = Object.entries(a).reduce((g, [h, k]) => {
g[h] = "string" == typeof k ? {short:k} : k;
return g;
}, {});
const e = [];
a = Object.entries(a).reduce((g, [h, k]) => {
let l;
try {
const m = k.short, n = k.boolean, p = k.number, q = k.command, t = k.multiple;
if (q && t && d.length) {
l = d;
} else {
if (q && d.length) {
l = d[0];
} else {
const r = da(c, h, m, n, p);
({value:l} = r);
const u = r.index, v = r.length;
void 0 !== u && v && e.push({index:u, length:v});
}
}
} catch (m) {
return g;
}
return void 0 === l ? g : {...g, [h]:l};
}, {});
let f = c;
e.forEach(({index:g, length:h}) => {
Array.from({length:h}).forEach((k, l) => {
f[g + l] = null;
});
});
f = f.filter(g => null !== g);
Object.assign(a, {C:f});
return a;
}(y), ha = z.tests, ia = z.alamode, ja = z.watch, ka = z.timeout || 2000, la = z.snapshot || "test/snapshot", ma = z.snapshotRoot || "test/spec,test/mask", na = z.interactive, A = z.environment, oa = z.babel, pa = z.version, qa = z.help, ra = z.C;
const B = path.dirname, C = path.join, D = path.relative, E = path.resolve;
const sa = fs.createReadStream, ta = fs.createWriteStream, F = fs.lstat, ua = fs.mkdir, G = fs.readdir, va = fs.rmdir, wa = fs.unlink, xa = fs.unwatchFile, ya = fs.watchFile;
var za = stream;
const H = stream.Transform, Aa = stream.Writable;
const I = (a, b = 0, c = !1) => {
if (0 === b && !c) {
return a;
}
a = a.split("\n", c ? b + 1 : void 0);
return c ? a[a.length - 1] : a.slice(b).join("\n");
}, Ba = (a, b = !1) => I(a, 2 + (b ? 1 : 0)), Ca = a => {
({callee:{caller:a}} = a);
return a;
};
function Da(a, b, c = !1) {
return function(d) {
var e = Ca(arguments), {stack:f} = Error();
const g = I(f, 2, !0), h = (f = d instanceof Error) ? d.message : d;
e = [`Error: ${h}`, ...null !== e && a === e || c ? [b] : [g, b]].join("\n");
e = x(e);
return Object.assign(f ? d : Error(), {message:h, stack:e});
};
}
;function J(a) {
var {stack:b} = Error();
const c = Ca(arguments);
b = Ba(b, a);
return Da(c, b, a);
}
;const Ea = (a, b) => {
b.once("error", c => {
a.emit("error", c);
});
return b;
};
class K extends Aa {
constructor(a) {
const {binary:b = !1, rs:c = null, ...d} = a || {}, {G:e = J(!0), proxyError:f} = a || {}, g = (h, k) => e(k);
super(d);
this.a = [];
this.F = new Promise((h, k) => {
this.on("finish", () => {
let l;
b ? l = Buffer.concat(this.a) : l = this.a.join("");
h(l);
this.a = [];
});
this.once("error", l => {
if (-1 == l.stack.indexOf("\n")) {
g`${l}`;
} else {
const m = x(l.stack);
l.stack = m;
f && g`${l}`;
}
k(l);
});
c && Ea(this, c).pipe(this);
});
}
_write(a, b, c) {
this.a.push(a);
c();
}
get j() {
return this.F;
}
}
const Fa = async a => {
({j:a} = new K({rs:a, G:J(!0)}));
return await a;
};
/*
diff package https://github.com/kpdecker/jsdiff
BSD License
Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>
*/
function Ga(a, b, c) {
let d = a[a.length - 1];
d && d.g === b && d.l === c ? a[a.length - 1] = {count:d.count + 1, g:b, l:c} : a.push({count:1, g:b, l:c});
}
function Ha(a, b, c, d, e) {
let f = c.length, g = d.length, h = b.f;
e = h - e;
let k = 0;
for (; h + 1 < f && e + 1 < g && a.equals(c[h + 1], d[e + 1]);) {
h++, e++, k++;
}
k && b.h.push({count:k});
b.f = h;
return e;
}
function Ia(a) {
let b = [];
for (let c = 0; c < a.length; c++) {
a[c] && b.push(a[c]);
}
return b;
}
function Ja(a, b) {
var c = new Ka;
a = Ia(a.split(""));
b = Ia(b.split(""));
let d = b.length, e = a.length, f = 1, g = d + e, h = [{f:-1, h:[]}];
var k = Ha(c, h[0], b, a, 0);
if (h[0].f + 1 >= d && k + 1 >= e) {
return [{value:c.join(b), count:b.length}];
}
for (; f <= g;) {
a: {
for (k = -1 * f; k <= f; k += 2) {
var l = void 0;
l = h[k - 1];
let n = h[k + 1];
var m = (n ? n.f : 0) - k;
l && (h[k - 1] = void 0);
let p = l && l.f + 1 < d;
m = n && 0 <= m && m < e;
if (p || m) {
!p || m && l.f < n.f ? (l = {f:n.f, h:n.h.slice(0)}, Ga(l.h, void 0, !0)) : (l.f++, Ga(l.h, !0, void 0));
m = Ha(c, l, b, a, k);
if (l.f + 1 >= d && m + 1 >= e) {
k = La(c, l.h, b, a);
break a;
}
h[k] = l;
} else {
h[k] = void 0;
}
}
f++;
k = void 0;
}
if (k) {
return k;
}
}
}
class Ka {
equals(a, b) {
return a === b;
}
join(a) {
return a.join("");
}
}
function La(a, b, c, d) {
let e = 0, f = b.length, g = 0, h = 0;
for (; e < f; e++) {
var k = b[e];
if (k.l) {
k.value = a.join(d.slice(h, h + k.count)), h += k.count, e && b[e - 1].g && (k = b[e - 1], b[e - 1] = b[e], b[e] = k);
} else {
if (k.g) {
k.value = a.join(c.slice(g, g + k.count));
} else {
let l = c.slice(g, g + k.count);
l = l.map(function(m, n) {
n = d[h + n];
return n.length > m.length ? n : m;
});
k.value = a.join(l);
}
g += k.count;
k.g || (h += k.count);
}
}
c = b[f - 1];
1 < f && "string" === typeof c.value && (c.g || c.l) && a.equals("", c.value) && (b[f - 2].value += c.value, b.pop());
return b;
}
;const Ma = {black:30, red:31, green:32, yellow:33, blue:34, magenta:35, cyan:36, white:37, grey:90}, Na = {black:40, red:41, green:42, yellow:43, blue:44, magenta:45, cyan:46, white:47}, L = {reset:0, bold:1, underline:4, slow_blink:5, L:6, reverse:7, conceal:8, crossed_out:9, primary_font:10}, M = a => {
Array.isArray(a) && (a = a.join(";"));
return `\x1b[${a}m`;
};
function N(a, b) {
b = [Ma[b], ...Object.keys({}).map(d => L[d.toLowerCase()])].filter(Boolean);
if (!b.length) {
return a;
}
b = M(b);
const c = M(L.reset);
return `${b}${a}${c}`;
}
function O(a, b) {
b = [Na[b], ...Object.keys({}).map(d => L[d])].filter(Boolean);
if (!b.length) {
return a;
}
b = M(b);
const c = M(L.reset);
return `${b}${a}${c}`;
}
function Oa(a, b) {
return Ja(a, b).map(({g:c, l:d, value:e}) => {
let f;
const g = e.split(" ");
if (c || d) {
f = g.map(h => h.replace(/(\r?\n)$/mg, "\u23ce$1").replace(/(\r+)([^\n]|$)/g, (k, l, m) => "<CR>".repeat(l.length) + m));
}
c ? f = f.map(h => N(h, "green")).join(O(" ", "green")) : d ? f = f.map(h => N(h, "red")).join(O(" ", "red")) : f = N(e, "grey");
return f;
}).join("");
}
;function P(a, b) {
return a.replace(/^(?!\s*$)/mg, b);
}
function Pa({error:a, name:b}) {
if (!a) {
throw Error("cannot filter stack when a test does not have an error");
}
var c = a.stack.split(/\n/);
const d = new RegExp(`at( async)? (.+\\.)?${b}`);
b = c.findIndex(e => d.test(e)) + 1;
return (c = c.slice(0, b).join("\n")) ? c : x(a.stack);
}
const Qa = " " + N("\u2713", "green") + " ", Ra = " " + N("\u2717", "red") + " ";
function Sa() {
const a = [];
return new H({objectMode:!0, transform({type:b, name:c, ...d}, e, f) {
"test-suite-start" == b && "default" != c ? a.push(c) : "test-suite-end" == b && "default" != c && a.pop();
e = a.slice();
this.push({type:b, name:c, stack:e, ...d});
f();
}});
}
function Ta() {
return new H({objectMode:!0, transform({type:a, name:b, stack:c, result:d}, e, f) {
"test-suite-start" == a && "default" != b ? (this.push(P(b, Array.from({length:2 * c.length}).join(" "))), this.push(w)) : "test-end" == a && (this.push(P(d, Array.from({length:2 * c.length}).join(" "))), this.push(w));
f();
}});
}
function Ua() {
return new H({objectMode:!0, transform({error:a, stack:b, name:c}, d, e) {
if (!a) {
return e();
}
this.push("\u001b[31m");
this.push(b.join(" > "));
this.push(` > ${c}`);
this.push("\u001b[0m");
this.push(w);
this.push(P(Pa({error:a, name:c}), " "));
this.push(w);
this.push(w);
e();
}});
}
;async function Q(a, b, c) {
const d = J(!0);
if ("function" != typeof a) {
throw Error("Function must be passed.");
}
if (!a.length) {
throw Error(`Function${a.name ? ` ${a.name}` : ""} does not accept any arguments.`);
}
return await new Promise((e, f) => {
const g = (k, l) => k ? (k = d(k), f(k)) : e(c || l);
let h = [g];
Array.isArray(b) ? h = [...b, g] : 1 < Array.from(arguments).length && (h = [b, g]);
a(...h);
});
}
;function Va(a, b, c) {
return setTimeout(() => {
const d = Error(`${a ? a : "Promise"} has timed out after ${b}ms`);
d.stack = `Error: ${d.message}`;
c(d);
}, b);
}
function Wa(a, b) {
let c;
const d = new Promise((e, f) => {
c = Va(a, b, f);
});
return {timeout:c, j:d};
}
async function R(a, b, c) {
if (!(a instanceof Promise)) {
throw Error("Promise expected");
}
if (!b) {
throw Error("Timeout must be a number");
}
if (0 > b) {
throw Error("Timeout cannot be negative");
}
const {j:d, timeout:e} = Wa(c, b);
try {
return await Promise.race([a, d]);
} finally {
clearTimeout(e);
}
}
;async function Xa(a = []) {
a = (Array.isArray(a) ? a : [a]).map(Ya);
return await Promise.all(a);
}
const Ya = async a => {
if ("function" != (typeof a).toLowerCase()) {
return a;
}
try {
const b = {};
await a.call(b);
return b;
} catch (b) {
if (!/^Class constructor/.test(b.message)) {
throw b;
}
a = new a;
a._init && await a._init();
return new Proxy(a, {get(c, d) {
return "then" == d ? c : "function" == typeof c[d] ? c[d].bind(c) : c[d];
}});
}
}, S = async a => {
a = a.map(async b => {
if ("function" == (typeof b._destroy).toLowerCase()) {
return await b._destroy();
}
});
return await Promise.all(a);
};
const $a = async a => {
const {context:b, timeout:c = null, fn:d, persistentContext:e, onCatchment:f} = a;
a = new Date;
let g = null, h = null, k = null, l = [], m, n;
try {
b && (m = b ? Xa(b) : Promise.resolve([]), m.then(() => {
n = !0;
}), l = await (c ? R(m, c, "Evaluate context") : m));
const p = e ? [...Array.isArray(e) ? e : [e], ...l] : l, q = d(...p);
q instanceof Promise ? h = await (c ? R(q, c, "Test") : q) : h = q;
} catch (p) {
g = p;
}
if (h instanceof za) {
try {
const p = new K({rs:h});
f && f(p);
h = await p.j;
} catch (p) {
g = p;
}
}
try {
const p = S(l);
k = await (c ? R(p, c, "Destroy") : p);
} catch (p) {
g = p;
}
!n && m && Za(m);
return {started:a, finished:new Date, error:g, result:h, destroyResult:k};
}, Za = async a => {
a = await a;
await S(a);
};
const ab = async(a, b) => {
const {onlyFocused:c = !1, runTest:d, runTestSuite:e} = b, f = !c;
return await a.reduce(async(g, h) => {
const k = h.name, l = h.isFocused;
var m = h.hasFocused;
const n = !!h.fn;
if (f || l || m) {
g = g instanceof Promise ? await g : g, n ? (m = await d(h), Object.assign(h, m), g[k] = h) : (h = await e(h, m), g[k] = h);
}
return g;
}, {});
};
const bb = assert.equal;
const cb = readline.createInterface;
function db(a, b = {}) {
const {timeout:c, password:d = !1, output:e = process.stdout, input:f = process.stdin, ...g} = b, h = cb({input:f, output:e, ...g});
if (d) {
const k = h.output;
h._writeToOutput = l => {
if (["\r\n", "\n", "\r"].includes(l)) {
return k.write(l);
}
l = l.split(a);
"2" == l.length ? (k.write(a), k.write("*".repeat(l[1].length))) : k.write("*");
};
}
b = new Promise(k => {
h.question(a, k);
});
b = c ? R(b, c, `reloquent: ${a}`) : b;
h.promise = eb(b, h);
return h;
}
const eb = async(a, b) => {
try {
return await a;
} finally {
b.close();
}
};
async function fb(a, b) {
if ("object" != typeof a) {
throw Error("Please give an object with questions");
}
return await Object.keys(a).reduce(async(c, d) => {
c = await c;
var e = a[d];
switch(typeof e) {
case "object":
e = {...e};
break;
case "string":
e = {text:e};
break;
default:
throw Error("A question must be a string or an object.");
}
e.text = `${e.text}${e.text.endsWith("?") ? "" : ":"} `;
var f;
if (e.defaultValue) {
var g = e.defaultValue;
}
e.getDefault && (f = await e.getDefault());
let h = g || "";
g && f && g != f ? h = `\x1b[90m${g}\x1b[0m` : g && g == f && (h = "");
g = f || "";
({promise:g} = db(`${e.text}${h ? `[${h}] ` : ""}${g ? `[${g}] ` : ""}`, {timeout:b, password:e.password, ...e}));
f = await g || f || e.defaultValue;
"function" == typeof e.validation && e.validation(f);
"function" == typeof e.postProcess && (f = await e.postProcess(f));
return {...c, [d]:f};
}, {});
}
;async function T(a) {
const {defaultYes:b = !0, timeout:c} = {};
a = "string" == typeof a ? {text:a} : a;
const d = a.text, e = d.endsWith("?");
({question:a} = await fb({question:{defaultValue:b ? "y" : "n", ...a, text:`${e ? d.replace(/\?$/, "") : d} (y/n)${e ? "?" : ""}`}}, c));
return "y" == a;
}
;const gb = util.inspect;
async function hb(a) {
a = sa(a);
return await Fa(a);
}
;async function ib(a, b) {
if (!a) {
throw Error("No path is given.");
}
const c = J(!0), d = ta(a);
await new Promise((e, f) => {
d.on("error", g => {
g = c(g);
f(g);
}).on("close", e).end(b);
});
}
;async function jb(a) {
const b = B(a);
try {
return await U(b), a;
} catch (c) {
if (/EEXIST/.test(c.message) && -1 != c.message.indexOf(b)) {
return a;
}
throw c;
}
}
async function U(a) {
try {
await Q(ua, a);
} catch (b) {
if ("ENOENT" == b.code) {
const c = B(a);
await U(c);
await U(a);
} else {
if ("EEXIST" != b.code) {
throw b;
}
}
}
}
;const kb = (a, b) => {
a = " ".repeat(Math.max(a - b.length, 0));
return `${b}${a}`;
}, lb = a => {
a = a.split("\n");
const b = {}.width || a.reduce((c, {length:d}) => d > c ? d : c, 0);
return a.map(kb.bind(null, b)).join("\n");
};
function mb(a) {
const {padding:b = 1} = {};
var c = a.split("\n").reduce((f, {length:g}) => g > f ? g : f, 0) + 2 * b;
const d = `\u250c${"\u2500".repeat(c)}\u2510`;
c = `\u2514${"\u2500".repeat(c)}\u2518`;
const e = " ".repeat(b);
a = lb(a).split("\n").map(f => `\u2502${e}${f}${e}\u2502`).join("\n");
return `${d}\n${a}\n${c}`;
}
;async function V(a, b, c) {
a = E(a.a, b);
await jb(a);
/\.json$/.test(a) ? (c = JSON.stringify(c, null, 2), await ib(a, c)) : await ib(a, c);
}
async function nb(a, b, c, d) {
if (!c) {
throw Error("Give snapshot to save");
}
if (await a.prompt(c, d)) {
await V(a, b, c);
} else {
throw Error("Could not test missing snapshot");
}
}
async function ob(a, b, c, d, e = !1) {
if (!c) {
throw Error("Pass the actual value for snapshot.");
}
const f = J(!0), g = /\.json$/.test(b);
let h;
try {
if (h = await a.read(b), g) {
const {deepEqual:l} = require("@zoroaster/assert");
l(c, h);
} else {
bb(c, h);
}
} catch (l) {
if ("ENOENT" == l.code) {
await nb(a, b, c, d);
} else {
var k;
g || (k = Oa(h, c));
if (e && (g ? console.log(l.message) : console.log(k), await T(`Update snapshot${d ? ` for ${d}` : ""}?`))) {
await V(a, b, c);
return;
}
if (!g) {
throw !e && console.log(k), a = f("The string didn't match the snapshot."), a.erte = k, a;
}
throw f(l);
}
}
}
class pb {
constructor() {
this.a = "test/snapshot";
}
async prompt(a, b) {
if ("string" == typeof a) {
let c = a.split(/\r?\n/).reduce((d, e) => {
if (e.length > d) {
return e.length;
}
}, 0);
process.stdout.isTTY && process.stdout.columns - 4 >= c ? console.log(mb(a)) : console.log(a);
} else {
console.log(gb(a, {colors:!0}));
}
return await T(`Save snapshot${b ? ` for ${b}` : ""}?`);
}
async read(a) {
a = E(this.a, a);
return /\.json$/.test(a) ? (a = await hb(a), JSON.parse(a)) : await hb(a);
}
}
;const W = async a => {
try {
return await Q(F, a);
} catch (b) {
return null;
}
};
async function qb(a, b) {
b = b.map(async c => {
const d = C(a, c);
return {lstat:await Q(F, d), path:d, relativePath:c};
});
return await Promise.all(b);
}
const rb = a => a.lstat.isDirectory(), sb = a => !a.lstat.isDirectory();
async function tb(a) {
if (!a) {
throw Error("Please specify a path to the directory");
}
const {ignore:b = []} = {};
if (!(await Q(F, a)).isDirectory()) {
var c = Error("Path is not a directory");
c.code = "ENOTDIR";
throw c;
}
c = await Q(G, a);
var d = await qb(a, c);
c = d.filter(rb);
d = d.filter(sb).reduce((e, f) => {
var g = f.lstat.isDirectory() ? "Directory" : f.lstat.isFile() ? "File" : f.lstat.isSymbolicLink() ? "SymbolicLink" : void 0;
return {...e, [f.relativePath]:{type:g}};
}, {});
c = await c.reduce(async(e, {path:f, relativePath:g}) => {
const h = D(a, f);
if (b.includes(h)) {
return e;
}
e = await e;
f = await tb(f);
return {...e, [g]:f};
}, {});
return {content:{...d, ...c}, type:"Directory"};
}
;const ub = async a => {
await Q(wa, a);
}, vb = async a => {
const {content:b} = await tb(a);
var c = Object.keys(b).filter(e => {
({type:e} = b[e]);
if ("File" == e || "SymbolicLink" == e) {
return !0;
}
}), d = Object.keys(b).filter(e => {
({type:e} = b[e]);
if ("Directory" == e) {
return !0;
}
});
c = c.map(e => C(a, e));
await Promise.all(c.map(ub));
d = d.map(e => C(a, e));
await Promise.all(d.map(vb));
await Q(va, a);
}, wb = async a => {
(await Q(F, a)).isDirectory() ? await vb(a) : await ub(a);
};
const xb = a => a.replace(/^!/, ""), yb = async(a, b, c, d = "", e = [], f = !1, g = "txt") => {
var h = b.replace(/^!/, "");
const k = h.replace(/ /g, "-");
b = "string" == typeof a;
const l = `${k}.${b ? g : "json"}`;
let m = C(...c.map(xb));
(c = e.find(n => {
n = C(...n.split("/"));
return m.startsWith(n);
})) && (m = m.slice(c.length));
e = C(d, m);
d = C(e, l);
if (a) {
if (c = new pb, c.a = e, g = C(e, `${k}.${b ? "json" : g}`), await W(g)) {
h = `Snapshot of another type exists: ${N(g, "red")}`, f || X(h), console.log("%s.\nNew data:", h), console.log(b ? a : gb(a, {colors:!0})), await T(`Update snapshot ${N(g, "yellow")} to a new type?`) || X(h), await V(c, l, a), await wb(g);
} else {
try {
await ob(c, l, a, N(h, "yellow"), f);
} catch (n) {
"The string didn't match the snapshot." == n.message && (n.message = `The string didn't match the snapshot ${N(d, "yellow")}`), X(n);
}
}
} else {
a = await W(d), a || (d = d.replace(/json$/, g), a = await W(d)), a && X(`Snapshot ${d} exists, but the test did not return anything.`);
}
}, X = a => {
a = Error(a);
a.stack = a.message;
throw a;
};
const Y = require("../");
async function zb(a, b, {name:c, context:d, fn:e, timeout:f, persistentContext:g}, h = {}, k = null) {
a && a({name:c, type:"test-start"});
let l, m, n;
d = Array.isArray(d) ? d : [d];
d.forEach(r => {
r.prototype instanceof Y && (l = r.snapshotExtension, n = r.serialise);
});
d = (e.name ? d.slice(0, e.length) : d).map(r => {
try {
return r === Y || r.prototype instanceof Y ? {["snapshotExtension"](u) {
l = u;
}, ["snapshotSource"](u, v) {
m = u;
v && (l = v);
}} : r;
} catch (u) {
return r;
}
});
let p, q;
const t = r => {
if (p) {
return p.emit("error", r);
}
k = r;
};
if (!k) {
process.once("uncaughtException", t);
process.once("unhandledRejection", t);
try {
q = await $a({context:d, persistentContext:g, fn:e, timeout:f, onCatchment(v) {
p = v;
}});
let {result:r, error:u} = q;
k || (k = u);
if (!k) {
try {
void 0 !== r && n && (r = n(r)), await yb(r, m || c, b, h.m, h.o, h.i, l);
} catch (v) {
k = v;
}
}
if (h.i && u && u.handleUpdate) {
try {
await u.handleUpdate() && (k = null);
} catch (v) {
k = v;
}
}
} finally {
process.removeListener("uncaughtException", t), process.removeListener("unhandledRejection", t);
}
}
a && a({name:c, error:k, type:"test-end", result:Ab({error:k, name:c})});
return q;
}
function Ab({error:a, name:b}) {
return null === a ? `${Qa} ${b}` : `${Ra} ${b}` + w + P(Pa({error:a, name:b}), " | ");
}
async function Bb(a, b, {name:c, tests:d, persistentContext:e}, f, g, h) {
a && a({type:"test-suite-start", name:c});
let k, l;
if (e && !h) {
try {
k = await Cb(e), Db(d, k);
} catch (m) {
m.message = `Persistent context failed to evaluate: ${m.message}`, m.stack = m.stack.split("\n", 2).join("\n"), h = m;
}
}
try {
const m = [...b, c.replace(/\.jsx?$/, "")];
l = await Eb(a, m, d, f, g, h);
a && a({type:"test-suite-end", name:c});
} finally {
if (k) {
try {
await Fb(k);
} catch (m) {
m.stack = m.stack.split("\n", 2).join("\n"), console.log(N(m.stack, "red"));
}
}
}
return l;
}
const Db = (a, b) => {
a.forEach(c => {
c.persistentContext = b;
});
}, Gb = async a => {
const b = Ya(a);
return await R(b, a.u || 5000, `Evaluate persistent context ${a.name ? a.name : ""}`);
}, Cb = async a => {
a = Array.isArray(a) ? a : [a];
return await Promise.all(a.map(b => Gb(b)));
}, Hb = async a => {
const b = S([a]);
return await R(b, a.u || 5000, `Destroy persistent context ${a.name ? a.name : ""}`);
}, Fb = async a => await Promise.all(a.map(b => Hb(b)));
async function Eb(a, b, c, d, e, f) {
return await ab(c, {onlyFocused:d, runTest(g) {
return zb(a, b, g, e, f);
}, runTestSuite(g, h) {
return Bb(a, b, g, d ? h : !1, e, f);
}});
}
;class Ib {
constructor(a, b, c = 2000, d = []) {
this.timeout = c;
this.name = a;
this.fn = b;
this.context = d;
this.error = this.persistentContext = null;
}
get isFocused() {
return this.name.startsWith("!");
}
}
;function Jb({v:a}) {
return a instanceof Z;
}
const Kb = a => a.some(b => b.startsWith("!") || b.startsWith("$")), Lb = a => a.reduce((b, c) => c instanceof Z ? [...b, c.name, ...c.I] : [...b, c.name], []);
function Mb(a, b) {
if (Array.isArray(b) || "function" == (typeof b).toLowerCase()) {
return a.a = b, !0;
}
if ("object" == (typeof b).toLowerCase()) {
return a.a = Object.freeze({...a.a || {}, ...b}), !0;
}
}
class Z {
constructor(a, b, c, d, e) {
if (!a) {
throw Error("Test suite name must be given.");
}
this.J = a;
this.K = c;
this.u = e || (Jb(this) ? this.v.timeout : void 0);
this.a = this.A = void 0;
!Mb(this, d) && Jb(this) && (this.a = c.context);
if ("object" != typeof b) {
throw Error("You must provide tests in an object.");
}
this.B = !1;
this.s = [];
this.w = [];
{
const {context:f, persistentContext:g, ...h} = b;
void 0 !== f && Mb(this, f);
void 0 !== g && (a = g, Array.isArray(a) ? this.A = a : "function" == (typeof a).toLowerCase() && (this.A = a));
this.s = Nb(h, this);
this.w = Lb(this.s);
this.B = Kb(this.w);
}
}
get name() {
return this.J;
}
get v() {
return this.K;
}
get tests() {
return this.s;
}
get context() {
return this.a;
}
get timeout() {
return this.u;
}
get hasFocused() {
return this.B;
}
get I() {
return this.w;
}
get isFocused() {
return this.name.startsWith("!") || this.name.startsWith("$");
}
dump() {
const a = this.name + w + this.tests.map(b => b.dump()).join("\n");
return this.v ? P(a, " ") : a;
}
get persistentContext() {
return this.A;
}
}
const Ob = ({name:a}, {name:b}) => "default" == a ? -1 : "default" == b ? 1 : 0;
function Pb(a) {
const b = [], c = [];
a.forEach(d => {
d instanceof Ib ? c.push(d) : b.push(d);
});
a = b.sort(Ob);
return [...c, ...a];
}
function Nb(a, b) {
const c = Object.keys(a).map(d => {
const e = a[d];
if (e instanceof Z) {
return e;
}
switch(typeof e) {
case "function":
return new Ib(d, e, b.timeout, b.context);
case "object":
return new Z(d, e, b);
}
}).filter(d => d);
return Pb(c);
}
;function Qb() {
Object.keys(require.cache).forEach(a => {
D("", a).startsWith("node_modules") || a == require.resolve("../") || delete require.cache[a];
});
}
const Sb = async(a, b) => {
a = await a.reduce(async(c, d) => {
c = await c;
const e = await Rb(d);
return e ? {...c, [d]:e} : c;
}, {});
return new Z("Zoroaster Root Test Suite", a, null, void 0, b);
};
async function Tb(a) {
return (await Q(G, a)).reduce(async(b, c) => {
b = await b;
const d = C(a, c), e = await Q(F, d);
let f;
if (e.isFile()) {
var g = E(d);
g = require(g);
f = c.replace(/\.jsx?$/, "");
} else {
e.isDirectory() && (g = await Tb(d), f = c);
}
return b[f] ? (console.warn("Merging %s with %s in %s", f, c, a), b[f] = Ub(b[f], g), b) : {...b, [f]:g};
}, {});
}
const Ub = (a, b) => {
Object.keys(b).forEach(c => {
if (a[c]) {
throw Error(`Duplicate key ${c}`);
}
});
return {...a, ...b};
};
async function Rb(a) {
try {
const b = await Q(F, a);
if (b.isFile()) {
const c = E(a);
return require(c);
}
if (b.isDirectory()) {
return await Tb(a);
}
} catch (b) {
throw a = N("Could not require ", "red") + O(N(a, "white"), "red"), b.message += `${w}${a}`, b;
}
}
;function Vb(a, b) {
a.forEach(c => {
ya(c, (...d) => {
b(c, ...d);
});
});
}
function Wb(a) {
a.forEach(b => {
xa(b);
});
}
async function Xb({paths:a, watch:b, timeout:c, m:d, o:e, i:f}, {D:g = [], H:h} = {}) {
Wb(g);
h && process.removeListener("beforeExit", h);
g = await Sb(a, c);
const k = Sa();
h = Ua();
const l = Ta();
k.pipe(l).pipe(process.stdout);
k.pipe(h);
({j:h} = new K({rs:h}));
var m = 0, n = 0;
await Eb(q => {
"object" == typeof q && (k.write(q), "test-end" == q.type && (m++, q.error && n++));
}, [], g.tests, g.hasFocused, {m:d, o:e, i:f});
k.end();
g = await h;
process.stdout.write(w);
process.stdout.write(g);
process.stdout.write(`\ud83e\udd85 Executed ${m} test${1 == m ? "" : "s"}`);
n && process.stdout.write(`: ${n} error${1 < n ? "s" : ""}`);
process.stdout.write(`.${w}`);
const p = () => {
process.exit(n);
};
process.once("beforeExit", p);
if (b) {
const q = Object.keys(require.cache).filter(t => !t.startsWith(`${process.cwd()}/node_modules/`));
Vb(q, async(t, r) => {
const u = a.filter(v => E(v) != t || r.mtime.getTime() ? !0 : (console.warn("Test suite file %s was deleted.", N(v, "yellow")), !1));
Qb();
await Xb({paths:u, watch:b, timeout:c, m:d, o:e, i:f}, {D:q, H:p});
});
}
}
;function Yb(a = {usage:{}}) {
const {usage:b = {}, description:c, line:d, example:e} = a;
a = Object.keys(b);
const f = Object.values(b), [g] = a.reduce(([l = 0, m = 0], n) => {
const p = b[n].split("\n").reduce((q, t) => t.length > q ? t.length : q, 0);
p > m && (m = p);
n.length > l && (l = n.length);
return [l, m];
}, []), h = (l, m) => {
m = " ".repeat(m - l.length);
return `${l}${m}`;
};
a = a.reduce((l, m, n) => {
n = f[n].split("\n");
m = h(m, g);
const [p, ...q] = n;
m = `${m}\t${p}`;
const t = h("", g);
n = q.map(r => `${t}\t${r}`);
return [...l, m, ...n];
}, []).map(l => `\t${l}`);
const k = [c, ` ${d || ""}`].filter(l => l ? l.trim() : l).join("\n\n");
a = `${k ? `${k}\n` : ""}
${a.join("\n")}
`;
return e ? `${a}
Example:
${e}
` : a;
}
;if (pa) {
console.log(require("../../package.json").version), process.exit();
} else {
if (qa) {
var Zb;
{
const a = fa();
Zb = Yb({usage:a, description:"A context-testing framework with support for mask and fork-testing.\nAutomatically transpiles import/export and JSX with \u00c0LaMode.\nhttps://www.contexttesting.com", line:"zoroaster path [pathN] [-w] [-a [-e env]] [-sr] [-vh]", example:"zoroaster test/spec test/mask -a"});
}
console.log(Zb);
process.exit();
}
}
if (oa) {
try {
require("@babel/register");
} catch (a) {
const b = E(process.cwd(), "node_modules/@babel/register");
require(b);
}
}
ia && (A && (process.env.ALAMODE_ENV = A), require("alamode")());
(async() => {
try {
await Xb({paths:[...ha || [], ...ra], watch:ja, timeout:ka, m:la, o:ma.split(","), i:na});
} catch (a) {
console.log(x(a.stack)), process.exit(1);
}
})();