« get me outta code hell

data steps: basic custom mocking function support - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-03-27 12:47:04 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-03-27 12:47:04 -0300
commitc6f1011722dc6fe50afb3a63ee414c70dbfd6abf (patch)
treed13235a4b37e8264a1fbccdfad12009f7a3a4f6d /src
parentcb13d591c6965dc52d89ec4d1e10558e6b22456b (diff)
data steps: basic custom mocking function support
I checked out a few libraries but none really behaved
the way I needed, and coding it myself means much lower-
level access, which makes certain options a lot easier
(e.g. excluding one argument of a mocked function from
assertion while matching the rest against a pattern).
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/index.js67
1 files changed, 49 insertions, 18 deletions
diff --git a/src/content/dependencies/index.js b/src/content/dependencies/index.js
index 7f86abb1..767828ad 100644
--- a/src/content/dependencies/index.js
+++ b/src/content/dependencies/index.js
@@ -8,6 +8,7 @@ import {color, logWarn} from '../../util/cli.js';
 import {annotateFunction} from '../../util/sugar.js';
 
 export function watchContentDependencies({
+  mock = null,
   logging = true,
 } = {}) {
   const events = new EventEmitter();
@@ -46,6 +47,23 @@ export function watchContentDependencies({
     checkReadyConditions();
   });
 
+  if (mock) {
+    const errors = [];
+    for (const [functionName, spec] of Object.entries(mock)) {
+      try {
+        const fn = processFunctionSpec(functionName, spec);
+        contentDependencies[functionName] = fn;
+      } catch (error) {
+        error.message = `(${functionName}) ${error.message}`;
+        errors.push(error);
+      }
+    }
+    if (errors.length) {
+      throw new AggregateError(errors, `Errors processing mocked content functions`);
+    }
+    checkReadyConditions();
+  }
+
   return events;
 
   async function close() {
@@ -81,13 +99,21 @@ export function watchContentDependencies({
     return functionName;
   }
 
+  function isMocked(functionName) {
+    return !!mock && Object.keys(mock).includes(functionName);
+  }
+
   async function handlePathRemoved(filePath) {
     const functionName = getFunctionName(filePath);
+    if (isMocked(functionName)) return;
+
     delete contentDependencies[functionName];
   }
 
   async function handlePathUpdated(filePath) {
     const functionName = getFunctionName(filePath);
+    if (isMocked(functionName)) return;
+
     let error = null;
 
     main: {
@@ -100,26 +126,11 @@ export function watchContentDependencies({
         break main;
       }
 
-      try {
-        if (typeof spec.data === 'function') {
-          annotateFunction(spec.data, {name: functionName, description: 'data'});
-        }
-
-        if (typeof spec.generate === 'function') {
-          annotateFunction(spec.generate, {name: functionName});
-        }
-      } catch (caughtError) {
-        error = caughtError;
-        error.message = `Error annotating functions: ${error.message}`;
-        break main;
-      }
-
       let fn;
       try {
-        fn = contentFunction(spec);
+        fn = processFunctionSpec(functionName, spec);
       } catch (caughtError) {
         error = caughtError;
-        error.message = `Error loading spec: ${error.message}`;
         break main;
       }
 
@@ -155,11 +166,31 @@ export function watchContentDependencies({
 
     return false;
   }
+
+  function processFunctionSpec(functionName, spec) {
+    if (typeof spec.data === 'function') {
+      annotateFunction(spec.data, {name: functionName, description: 'data'});
+    }
+
+    if (typeof spec.generate === 'function') {
+      annotateFunction(spec.generate, {name: functionName});
+    }
+
+    let fn;
+    try {
+      fn = contentFunction(spec);
+    } catch (error) {
+      error.message = `Error loading spec: ${error.message}`;
+      throw error;
+    }
+
+    return fn;
+  }
 }
 
-export function quickLoadContentDependencies() {
+export function quickLoadContentDependencies(opts) {
   return new Promise((resolve, reject) => {
-    const watcher = watchContentDependencies();
+    const watcher = watchContentDependencies(opts);
 
     watcher.on('error', (name, error) => {
       watcher.close().then(() => {