Skip to content

Instantly share code, notes, and snippets.

@stephenh
Created April 3, 2021 22:04
Show Gist options
  • Save stephenh/056a500708243e2ea43246c28d19d3ae to your computer and use it in GitHub Desktop.
Save stephenh/056a500708243e2ea43246c28d19d3ae to your computer and use it in GitHub Desktop.
linkedomEnv.js
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;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment