diff --git a/packages/happy-dom/package.json b/packages/happy-dom/package.json index a206fcd1c..8c6c8e077 100644 --- a/packages/happy-dom/package.json +++ b/packages/happy-dom/package.json @@ -27,11 +27,10 @@ "watch": "tsc -w --preserveWatchOutput", "lint": "eslint --ignore-path .gitignore --max-warnings 0 .", "lint:fix": "eslint --ignore-path .gitignore --max-warnings 0 --fix .", - "test": "jest", - "test:coverage": "jest --collectCoverage", - "test:watch": "jest --watch", - "test:update-snapshot": "jest --updateSnapshot", - "test:debug": "node --inspect-brk ./node_modules/.bin/jest --runInBand" + "test": "jest --setupFilesAfterEnv ./test/setup.js", + "test:coverage": "jest --setupFilesAfterEnv ./test/setup.js --collectCoverage", + "test:watch": "jest --setupFilesAfterEnv ./test/setup.js --watch", + "test:debug": "node --inspect-brk ./node_modules/.bin/jest --setupFilesAfterEnv ./test/setup.js --runInBand" }, "jest": { "transform": { diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts index 8233dae27..1033f02ec 100644 --- a/packages/happy-dom/src/window/Window.ts +++ b/packages/happy-dom/src/window/Window.ts @@ -1,5 +1,6 @@ import GlobalWindow from './GlobalWindow'; import VM from 'vm'; +import GlobalProperties from './GlobalProperties'; /** * Browser window without a VM in the global scope. @@ -8,75 +9,16 @@ import VM from 'vm'; * https://developer.mozilla.org/en-US/docs/Web/API/Window. */ export default class Window extends GlobalWindow { - // Node.js Globals - public ArrayBuffer; - public Boolean; - public Buffer; - public DataView; - public Date; - public Error; - public EvalError; - public Float32Array; - public Float64Array; - public GLOBAL; - public Infinity; - public Int16Array; - public Int32Array; - public Int8Array; - public Intl; - public JSON; - public Map; - public Math; - public NaN; - public Number; - public Promise; - public RangeError; - public ReferenceError; - public RegExp; - public Reflect; - public Set; - public Symbol; - public SyntaxError; - public String; - public TypeError; - public URIError; - public Uint16Array; - public Uint32Array; - public Uint8Array; - public Uint8ClampedArray; - public WeakMap; - public WeakSet; - public clearImmediate; - public decodeURI; - public decodeURIComponent; - public encodeURI; - public encodeURIComponent; - public escape; - public global; - public isFinite; - public isNaN; - public parseFloat; - public parseInt; - public process; - public root; - public setImmediate; - public queueMicrotask; - public undefined; - public unescape; - public gc; - public v8debug; - public AbortController; - public AbortSignal; - public Array; - public Object; - public Function; - /** * Constructor. */ constructor() { super(); + for (const property of GlobalProperties) { + delete this[property]; + } + if (!VM.isContext(this)) { VM.createContext(this); } diff --git a/packages/happy-dom/test/fetch/ResourceFetchHandler.test.ts b/packages/happy-dom/test/fetch/ResourceFetchHandler.test.ts index 174a15ff4..6fac713ea 100644 --- a/packages/happy-dom/test/fetch/ResourceFetchHandler.test.ts +++ b/packages/happy-dom/test/fetch/ResourceFetchHandler.test.ts @@ -4,30 +4,16 @@ import IDocument from '../../src/nodes/document/IDocument'; import ResourceFetchHandler from '../../src/fetch/ResourceFetchHandler'; import IResponse from '../../src/fetch/IResponse'; -let syncRequestStatusCode; -let syncRequestBody; -let syncRequestOptions; - -jest.mock('sync-request', () => (method: string, url: string) => { - syncRequestOptions = { - method, - url - }; - return { - getBody: () => syncRequestBody, - isError: () => syncRequestStatusCode !== 200, - statusCode: syncRequestStatusCode - }; -}); +const MOCKED_SYNC_REQUEST = global['mockedModules']['sync-request']; describe('ResourceFetchHandler', () => { let window: IWindow; let document: IDocument; beforeEach(() => { - syncRequestOptions = null; - syncRequestStatusCode = 200; - syncRequestBody = 'test'; + MOCKED_SYNC_REQUEST.options = null; + MOCKED_SYNC_REQUEST.statusCode = 200; + MOCKED_SYNC_REQUEST.body = 'test'; window = new Window(); document = window.document; }); @@ -61,7 +47,7 @@ describe('ResourceFetchHandler', () => { const test = ResourceFetchHandler.fetchSync(document, 'path/to/script/'); - expect(syncRequestOptions).toEqual({ + expect(MOCKED_SYNC_REQUEST.options).toEqual({ method: 'GET', url: 'https://localhost:8080/base/path/to/script/' }); @@ -71,7 +57,7 @@ describe('ResourceFetchHandler', () => { it('Handles error when resource is fetched synchrounously.', () => { window.location.href = 'https://localhost:8080/base/'; - syncRequestStatusCode = 404; + MOCKED_SYNC_REQUEST.statusCode = 404; expect(() => { ResourceFetchHandler.fetchSync(document, 'path/to/script/'); diff --git a/packages/happy-dom/test/setup.js b/packages/happy-dom/test/setup.js new file mode 100644 index 000000000..bc51b5c89 --- /dev/null +++ b/packages/happy-dom/test/setup.js @@ -0,0 +1,75 @@ +global.mockedModules = { + 'sync-request': { + statusCode: null, + body: null, + options: null + }, + 'node-fetch': { + url: null, + init: null, + error: null, + response: { + arrayBuffer: Symbol('arrayBuffer'), + blob: Symbol('blob'), + buffer: Symbol('buffer'), + json: Symbol('json'), + text: Symbol('text'), + textConverted: Symbol('textConverted') + } + } +}; + +jest.mock('sync-request', () => (method, url) => { + global.mockedModules['sync-request'].options = { + method, + url + }; + return { + getBody: () => global.mockedModules['sync-request'].body, + isError: () => global.mockedModules['sync-request'].statusCode !== 200, + statusCode: global.mockedModules['sync-request'].statusCode + }; +}); + +/* eslint-disable jsdoc/require-jsdoc */ +class NodeFetchResponse { + arrayBuffer() { + return Promise.resolve(global.mockedModules['node-fetch'].response.arrayBuffer); + } + blob() { + return Promise.resolve(global.mockedModules['node-fetch'].response.blob); + } + buffer() { + return Promise.resolve(global.mockedModules['node-fetch'].response.buffer); + } + json() { + return Promise.resolve(global.mockedModules['node-fetch'].response.json); + } + text() { + return Promise.resolve(global.mockedModules['node-fetch'].response.text); + } + textConverted() { + return Promise.resolve(global.mockedModules['node-fetch'].response.textConverted); + } +} + +class NodeFetchRequest extends NodeFetchResponse {} +class NodeFetchHeaders {} + +jest.mock('node-fetch', () => { + return Object.assign( + (url, options) => { + global.mockedModules['node-fetch'].url = url; + global.mockedModules['node-fetch'].init = options; + if (global.mockedModules['node-fetch'].error) { + return Promise.reject(global.mockedModules['node-fetch'].error); + } + return Promise.resolve(new NodeFetchResponse()); + }, + { + Response: NodeFetchResponse, + Request: NodeFetchRequest, + Headers: NodeFetchHeaders + } + ); +}); diff --git a/packages/happy-dom/test/window/GlobalWindow.test.ts b/packages/happy-dom/test/window/GlobalWindow.test.ts index 846448ec9..833267360 100644 --- a/packages/happy-dom/test/window/GlobalWindow.test.ts +++ b/packages/happy-dom/test/window/GlobalWindow.test.ts @@ -4,7 +4,6 @@ import IHTMLLinkElement from '../../src/nodes/html-link-element/IHTMLLinkElement import IHTMLElement from '../../src/nodes/html-element/IHTMLElement'; import ResourceFetchHandler from '../../src/fetch/ResourceFetchHandler'; import IHTMLScriptElement from '../../src/nodes/html-script-element/IHTMLScriptElement'; -import IRequestInit from '../../src/fetch/IRequestInit'; import GlobalWindow from '../../src/window/GlobalWindow'; import IWindow from '../../src/window/IWindow'; import Navigator from '../../src/navigator/Navigator'; @@ -12,70 +11,16 @@ import Headers from '../../src/fetch/Headers'; import Response from '../../src/fetch/Response'; import Request from '../../src/fetch/Request'; -const MOCKED_RESPONSES = { - arrayBuffer: Symbol('arrayBuffer'), - blob: Symbol('blob'), - buffer: Symbol('buffer'), - json: Symbol('json'), - text: Symbol('text'), - textConverted: Symbol('textConverted') -}; - -/* eslint-disable jsdoc/require-jsdoc */ -class NodeFetchResponse { - public arrayBuffer(): Promise { - return Promise.resolve(MOCKED_RESPONSES.arrayBuffer); - } - public blob(): Promise { - return Promise.resolve(MOCKED_RESPONSES.blob); - } - public buffer(): Promise { - return Promise.resolve(MOCKED_RESPONSES.buffer); - } - public json(): Promise { - return Promise.resolve(MOCKED_RESPONSES.json); - } - public text(): Promise { - return Promise.resolve(MOCKED_RESPONSES.text); - } - public textConverted(): Promise { - return Promise.resolve(MOCKED_RESPONSES.textConverted); - } -} - -class NodeFetchRequest extends NodeFetchResponse {} -class NodeFetchHeaders {} - -let fetchedUrl: string; -let fetchedInit: IRequestInit; -let fetchError: Error; - -jest.mock('node-fetch', () => { - return Object.assign( - (url: string, options: IRequestInit) => { - fetchedUrl = url; - fetchedInit = options; - if (fetchError) { - return Promise.reject(fetchError); - } - return Promise.resolve(new NodeFetchResponse()); - }, - { - Response: NodeFetchResponse, - Request: NodeFetchRequest, - Headers: NodeFetchHeaders - } - ); -}); +const MOCKED_NODE_FETCH = global['mockedModules']['node-fetch']; describe('GlobalWindow', () => { let window: IWindow; let document: IDocument; beforeEach(() => { - fetchedUrl = null; - fetchedInit = null; - fetchError = null; + MOCKED_NODE_FETCH.url = null; + MOCKED_NODE_FETCH.init = null; + MOCKED_NODE_FETCH.error = null; window = new GlobalWindow(); document = window.document; }); @@ -136,7 +81,7 @@ describe('GlobalWindow', () => { it(`Handles the "${method}" method with the async task manager.`, async () => { const response = new window.Response(); const result = await response[method](); - expect(result).toBe(MOCKED_RESPONSES[method]); + expect(result).toBe(MOCKED_NODE_FETCH.response[method]); }); } }); @@ -151,7 +96,7 @@ describe('GlobalWindow', () => { it(`Handles the "${method}" method with the async task manager.`, async () => { const request = new window.Request('test'); const result = await request[method](); - expect(result).toBe(MOCKED_RESPONSES[method]); + expect(result).toBe(MOCKED_NODE_FETCH.response[method]); }); } }); @@ -296,9 +241,9 @@ describe('GlobalWindow', () => { const response = await window.fetch(expectedUrl, expectedOptions); const result = await response[method](); - expect(fetchedUrl).toBe(expectedUrl); - expect(fetchedInit).toBe(expectedOptions); - expect(result).toEqual(MOCKED_RESPONSES[method]); + expect(MOCKED_NODE_FETCH.url).toBe(expectedUrl); + expect(MOCKED_NODE_FETCH.init).toBe(expectedOptions); + expect(result).toEqual(MOCKED_NODE_FETCH.response[method]); }); } @@ -311,18 +256,18 @@ describe('GlobalWindow', () => { const response = await window.fetch(expectedPath, expectedOptions); const textResponse = await response.text(); - expect(fetchedUrl).toBe('https://localhost:8080' + expectedPath); - expect(fetchedInit).toBe(expectedOptions); - expect(textResponse).toEqual(MOCKED_RESPONSES.text); + expect(MOCKED_NODE_FETCH.url).toBe('https://localhost:8080' + expectedPath); + expect(MOCKED_NODE_FETCH.init).toBe(expectedOptions); + expect(textResponse).toEqual(MOCKED_NODE_FETCH.response.text); }); it('Handles error JSON request.', async () => { - fetchError = new Error('error'); + MOCKED_NODE_FETCH.error = new Error('error'); try { await window.fetch('/url/', {}); } catch (error) { - expect(error).toBe(fetchError); + expect(error).toBe(MOCKED_NODE_FETCH.error); } }); }); diff --git a/packages/jest-environment/package.json b/packages/jest-environment/package.json index 59401b8a9..9965d179b 100644 --- a/packages/jest-environment/package.json +++ b/packages/jest-environment/package.json @@ -31,7 +31,6 @@ "lint:fix": "eslint --ignore-path .gitignore --max-warnings 0 --fix .", "test": "jest", "test:watch": "jest --runInBand --watch", - "test:update-snapshot": "jest --runInBand --updateSnapshot", "test:debug": "node --inspect-brk ./node_modules/.bin/jest --runInBand" }, "jest": {