packages/vscode-bootstrap/test-utils/amd.ts (43 lines of code) (raw):

import { defineType } from '../src/amd/types'; interface DefineProvider { define: defineType; } // why: This is needed for shim() to work declare global { interface Window extends DefineProvider {} } /** * This class mocks an AMD environment for testing purposes. * * Usage: * * ```javascript * const amd = new MockAMDEnvironment(); * amd.shim(); * * beforeEach(() => { * amd.define('/required/dependency', { ... }); * }); * ``` */ class MockAMDEnvironment implements DefineProvider { private readonly modules: Map<string, any>; constructor() { this.modules = new Map(); } define<T, Deps extends any[] = []>( path: string, ...args: [string[], (...deps: Deps) => T] | [(...deps: Deps) => T] ) { let dependencies: string[]; let callback: Function; if (args.length === 2) { [dependencies, callback] = args; } else { dependencies = []; [callback] = args; } // what: Let's fail early if we are expecting undefined dependencies const missingDependencies = dependencies.filter(path => !this.modules.has(path)); if (missingDependencies.length) { const missingDependenciesStr = missingDependencies.map(x => ` - ${x}`).join('\n'); throw new Error( `Some dependencies have not been defined yet. Are you missing a call to \`define("path/to/module", ...)\` for the following:\n\n${missingDependenciesStr}`, ); } const dependencyObjs = dependencies.map(path => this.modules.get(path)); const newModuleObj = callback(...dependencyObjs); this.modules.set(path, newModuleObj); } /** * Clear all previously defined modules. */ cleanup() { this.modules.clear(); } /** * Shim `define` for this MockAMDEnvironment into the global scope. */ shim() { window.define = this.define.bind(this); } } export const useMockAMDEnvironment = () => new MockAMDEnvironment();