« get me outta code hell

test: move lib functions into one (short!) file - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/test/test-lib.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2026-03-31 19:53:51 -0300
committer(quasar) nebula <qznebula@protonmail.com>2026-03-31 19:53:51 -0300
commit90b0f3ebb163e05aa47aec66bf16ddaa03739546 (patch)
tree7f271020b791d7ef432d97bbddfba4a736d85291 /test/test-lib.js
parent727e1f0b4f6361a38a12489675b8f8c892040d65 (diff)
test: move lib functions into one (short!) file
Diffstat (limited to 'test/test-lib.js')
-rw-r--r--test/test-lib.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/test/test-lib.js b/test/test-lib.js
new file mode 100644
index 00000000..a12974cd
--- /dev/null
+++ b/test/test-lib.js
@@ -0,0 +1,86 @@
+import {compositeFrom} from '#composite';
+
+Error.stackTraceLimit = Infinity;
+
+export function quickCheckCompositeOutputs(t, dependencies) {
+  return (step, outputDict) => {
+    t.same(
+      Object.keys(step.toDescription().outputs),
+      Object.keys(outputDict));
+
+    const composite = compositeFrom({
+      compose: false,
+      steps: [
+        step,
+
+        {
+          dependencies: Object.keys(outputDict),
+
+          // Access all dependencies by their expected keys -
+          // the composition runner actually provides a proxy
+          // and is checking that *we* access the dependencies
+          // we've specified.
+          compute: dependencies =>
+            Object.fromEntries(
+              Object.keys(outputDict)
+                .map(key => [key, dependencies[key]])),
+        },
+      ],
+    });
+
+    t.same(
+      composite.expose.compute(dependencies),
+      outputDict);
+  };
+}
+
+export function strictlyThrows(t, fn, pattern) {
+  const error = catchErrorOrNull(fn);
+
+  t.currentAssert = strictlyThrows;
+
+  if (error === null) {
+    t.fail(`expected to throw`);
+    return;
+  }
+
+  const nameAndMessage = `${pattern.constructor.name} ${pattern.message}`;
+  t.match(
+    prepareErrorForMatch(error),
+    prepareErrorForMatch(pattern),
+    (pattern instanceof AggregateError
+      ? `expected to throw: ${nameAndMessage} (${pattern.errors.length} error(s))`
+      : `expected to throw: ${nameAndMessage}`));
+}
+
+function prepareErrorForMatch(error) {
+  if (error instanceof RegExp) {
+    return {
+      message: error,
+    };
+  }
+
+  if (!(error instanceof Error)) {
+    return error;
+  }
+
+  const matchable = {
+    name: error.constructor.name,
+    message: error.message,
+  };
+
+  if (error instanceof AggregateError) {
+    matchable.errors = error.errors.map(prepareErrorForMatch);
+  }
+
+  return matchable;
+}
+
+function catchErrorOrNull(fn) {
+  try {
+    fn();
+    return null;
+  } catch (error) {
+    return error;
+  }
+}