From c6f1011722dc6fe50afb3a63ee414c70dbfd6abf Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 27 Mar 2023 12:47:04 -0300 Subject: 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). --- src/content/dependencies/index.js | 67 ++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 18 deletions(-) (limited to 'src/content/dependencies/index.js') 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(() => { -- cgit 1.3.0-6-gf8a5