const { EnvironmentContext, JestEnvironment } = require("@jest/environment"); const { LegacyFakeTimers, ModernFakeTimers } = require("@jest/fake-timers"); const { Config, Global } = require("@jest/types"); const { ModuleMocker } = require("jest-mock"); const JestUtil = require("jest-util"); const { parseHTML } = require("linkedom"); const VM = require("vm"); const { Script } = VM; /** * Happy DOM Jest Environment. */ module.exports = class LinkedomEnv { /** * Constructor. * * @param config Jest config. * @param options Options. */ constructor(config, options) { const { window } = parseHTML(` <!doctype html> <html lang="en"> <head /> <body /> </html> `); this.global = window; this.moduleMocker = new ModuleMocker(this.global); VM.createContext(this.global); // Functions are not an instanceof the "Function" class in the VM context, so therefore we set it to the used "Function" class. VM.runInContext("window.Function = (() => {}).constructor;", this.global); // Node's error-message stack size is limited to 10, but it's pretty useful to see more than that when a test fails. this.global.Error.stackTraceLimit = 100; JestUtil.installCommonGlobals(this.global, config.globals); // Removes window.fetch() as it should not be used in a test environment. delete this.global.fetch; delete this.global.window.fetch; if (options.console) { this.global.console = options.console; this.global.window.console = options.console; } this.fakeTimers = new LegacyFakeTimers({ config, global: this.global, moduleMocker: this.moduleMocker, timerConfig: { idToRef: (id) => id, refToId: (ref) => ref, }, }); this.fakeTimersModern = new ModernFakeTimers({ config, global: this.global, }); } /** * Setup. * * @return Promise. */ async setup() {} /** * Teardown. * * @return Promise. */ async teardown() { this.fakeTimers.dispose(); this.fakeTimersModern.dispose(); // this.global.happyDOM.cancelAsync(); this.global = null; this.moduleMocker = null; this.fakeTimers = null; this.fakeTimersModern = null; } /** * Runs a script. * * @param script Script. * @returns Result. */ runScript(script) { return script.runInContext(this.global); } /** * Returns the VM context. * * @return Context. */ getVmContext() { return this.global; } };