Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Support happy-dom #878

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
"build:cjs": "rollup -c -f cjs -o dist/purify.cjs.js",
"build:cleanup": "rimraf dist/types",
"test:jsdom": "cross-env NODE_ENV=test BABEL_ENV=rollup node test/jsdom-node-runner --dot",
"test:happy-dom": "cross-env NODE_ENV=test BABEL_ENV=rollup node test/happy-dom-node-runner --dot",
"test:karma": "cross-env NODE_ENV=test BABEL_ENV=rollup karma start test/karma.conf.js --log-level warn ",
"test:ci": "cross-env NODE_ENV=test BABEL_ENV=rollup npm run test:jsdom && npm run test:karma -- --log-level error --reporters dots --single-run --shouldTestOnBrowserStack=\"${TEST_BROWSERSTACK}\" --shouldProbeOnly=\"${TEST_PROBE_ONLY}\"",
"test": "cross-env NODE_ENV=test BABEL_ENV=rollup npm run lint && npm run test:jsdom && npm run test:karma -- --browsers Chrome"
"test:ci": "cross-env NODE_ENV=test BABEL_ENV=rollup npm run test:jsdom && npm run test:happy-dom && npm run test:karma -- --log-level error --reporters dots --single-run --shouldTestOnBrowserStack=\"${TEST_BROWSERSTACK}\" --shouldProbeOnly=\"${TEST_PROBE_ONLY}\"",
"test": "cross-env NODE_ENV=test BABEL_ENV=rollup npm run lint && npm run test:jsdom && npm run test:happy-dom && npm run test:karma -- --browsers Chrome"
},
"main": "./dist/purify.cjs.js",
"module": "./dist/purify.es.mjs",
Expand Down Expand Up @@ -106,6 +107,7 @@
"cross-env": "^7.0.3",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"happy-dom": "^15.11.6",
"jquery": "^3.6.0",
"jsdom": "^20.0.0",
"karma": "^6.3.17",
Expand Down
52 changes: 33 additions & 19 deletions test/jsdom-node.js → test/base-node-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@
/* global QUnit */
'use strict';

// Test DOMPurify + jsdom using Node.js (version 8 and up)
global.QUnit = require('qunit');

const qunitTap = require('qunit-tap');
const argument = process.argv[2];

const createDOMPurify = require('../dist/purify.cjs');
const jsdom = require('jsdom');
const { JSDOM, VirtualConsole } = jsdom;
const virtualConsole = new VirtualConsole();
const { window } = new JSDOM(
`<html><head></head><body><div id="qunit-fixture"></div></body></html>`,
{ runScripts: 'dangerously', virtualConsole }
);
require('jquery')(window);

const sanitizeTestSuite = require('./test-suite');
const bootstrapTestSuite = require('./bootstrap-test-suite');

async function startQUnit() {
async function run(createWindow, runtimeName) {
qunitTap(QUnit, (line) => {
if (/^not ok/.test(line)) {
process.exitCode = 1;
return console.log('\n', line);
}

if (argument === '--dot') {
return process.stdout.write('.');
}

console.log(line);
});

const { default: tests } = await import('./fixtures/expect.mjs');
const xssTests = tests.filter((element) => /alert/.test(element.payload));

Expand All @@ -33,26 +42,31 @@ async function startQUnit() {

QUnit.config.autostart = false;

QUnit.module('DOMPurify - bootstrap', bootstrapTestSuite(JSDOM));

QUnit.module('DOMPurify in jsdom');
QUnit.module('DOMPurify - bootstrap', bootstrapTestSuite(createWindow));

if (!window.jQuery) {
console.warn('Unable to load jQuery');
}
QUnit.module(`DOMPurify in ${runtimeName}`);

const window = createWindow();
const DOMPurify = createDOMPurify(window);
if (!DOMPurify.isSupported) {
console.error('Unexpected error returned by jsdom.env():', err, err.stack);
console.error('DOMPurify reports as not supported');
process.exit(1);
}

window.alert = () => {
window.__proto__.alert = () => {
window.xssed = true;
};

sanitizeTestSuite(DOMPurify, window, tests, xssTests);
QUnit.start();

QUnit.load()
}

module.exports = startQUnit;
module.exports = {
run,
documentHtml: `<html>
<head><</head>
<body><div id="qunit-fixture"></div></body>
</html>`
};
10 changes: 4 additions & 6 deletions test/bootstrap-test-suite.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fs = require('fs');

module.exports = function (JSDOM) {
module.exports = function (createWindow) {
class StringWrapper {
constructor(s) {
this.s = s;
Expand All @@ -19,10 +19,8 @@ module.exports = function (JSDOM) {
onload
) {
const testDone = assert.async();
const { window } = new JSDOM('<head></head>', {
runScripts: 'dangerously',
});
require('jquery')(window);
const window = createWindow();

if (setup) {
setup(window);
}
Expand Down Expand Up @@ -272,4 +270,4 @@ module.exports = function (JSDOM) {
);
}
);
};
}
16 changes: 16 additions & 0 deletions test/happy-dom-node-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* jshint node: true, esnext: true */
'use strict';

const happyDom = require('happy-dom');
const { Window } = happyDom;

const {run, documentHtml} = require('./base-node-runner');

function createWindow() {
const window = new Window();
window.document.documentElement.innerHTML = documentHtml;
require('jquery')(window);
return window;
}

run(createWindow, 'happy-dom');
31 changes: 13 additions & 18 deletions test/jsdom-node-runner.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
/* jshint node: true, esnext: true */
/* global QUnit */
'use strict';

global.QUnit = require('qunit');
const jsdom = require('jsdom');
const { JSDOM, VirtualConsole } = jsdom;

const qunitTap = require('qunit-tap');
const argument = process.argv[2];
const {run, documentHtml} = require('./base-node-runner');

qunitTap(QUnit, (line) => {
if (/^not ok/.test(line)) {
process.exitCode = 1;
return console.log('\n', line);
}
function createWindow() {
const virtualConsole = new VirtualConsole();
const { window } = new JSDOM(
documentHtml,
{ runScripts: 'dangerously', virtualConsole }
);
require('jquery')(window);
return window;
}

if (argument === '--dot') {
return process.stdout.write('.');
}

console.log(line);
});

const startQUnit = require('./jsdom-node');
startQUnit().then(() => QUnit.load());
run(createWindow, 'jsdom');
Loading