From fa72f1f124ae13e5cc72f99b651010253c116c43 Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Wed, 6 Dec 2017 15:12:37 +0100 Subject: [PATCH] Improve `PluginEnvironment` helper to support tapable's hooks Test cases use `PluginEnvironment` to monitor plugins' actions. Before this change, it only mocked `.plugin()` which is not enough to test plugins written using `Tapable#hooks`. This implementation uses a `Proxy` to trap hook calls and log them as events. --- test/helpers/PluginEnvironment.js | 48 ++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/test/helpers/PluginEnvironment.js b/test/helpers/PluginEnvironment.js index 8500129d6..1b7ad46d7 100644 --- a/test/helpers/PluginEnvironment.js +++ b/test/helpers/PluginEnvironment.js @@ -1,14 +1,48 @@ module.exports = function PluginEnvironment() { - var events = []; + const events = []; + + function addEvent(name, handler) { + events.push({ + name, + handler + }); + } + + function getEventName(hookName) { + // Convert a hook name to an event name. + // e.g. `buildModule` -> `build-module` + return hookName.replace(/[A-Z]/g, c => "-" + c.toLowerCase()); + } this.getEnvironmentStub = function() { + const hooks = new Map(); return { - plugin: function(name, handler) { - events.push({ - name, - handler - }); - } + plugin: addEvent, + // TODO: Figure out a better way of doing this + // In the meanwhile, `hooks` is a `Proxy` which creates fake hooks + // on demand. Instead of creating a dummy object with a few `Hook` + // method, a custom `Hook` class could be used. + hooks: new Proxy({}, { + get(target, hookName) { + let hook = hooks.get(hookName); + if (hook === undefined) { + const eventName = getEventName(hookName); + hook = { + tap(_, handler) { + addEvent(eventName, handler); + }, + tapAsync(_, handler) { + addEvent(eventName, handler); + }, + tapPromise(_, handler) { + addEvent(eventName, handler); + } + }; + hooks.set(hookName, hook); + } + return hook; + } + }) }; };