mirror of
https://github.com/webrecorder/pywb.git
synced 2025-03-15 08:04:49 +01:00
wombat: - I: function overrides applied by wombat now better appear to be the original new function name same as originals when possible - I: WombatLocation now looks and behaves more like the original Location interface - I: The custom storage class now looks and behaves more like the original Storage - I: SVG image rewriting has been improved: both the href and xlink:href deprecated since SVG2 now rewritten always - I: document.open now handles the case of creation of a new window - I: Request object rewriting of the readonly href property is now correctly handled - I: EventTarget.addEventListener, removeEventListener overrides now preserve the original this argument of the wrapped listener - A: document.close override to ensure wombat is initialized after write or writeln usage - A: reconstruction of <doctype...> in rewriteHTMLComplete IFF it was included in the original string of HTML - A: document.body setter override to ensure rewriting of the new body or frameset - A: Attr.[value, nodeValue, textContent] added setter override to perform URL rewrites - A: SVGElements rewriting of the filter, style, xlink:href, href, and src attributes - A: HTMLTrackElement rewriting of the src attribute of the - A: HTMLQuoteElement and HTMLModElement rewriting of the cite attribute - A: Worklet.addModule: Loads JS module specified by a URL. - A: HTMLHyperlinkElementUtils overrides to the areaelement - A: ShadowRootoverrides to: innerHTML even though inherites from DocumentFragement and Node it still has innerHTML getter setter. - A: ShadowRoot, Element, DocumentFragment append, prepend: adds strings of HTML or a new Node inherited from ParentNode - A: StylePropertyMap override: New way to access and set CSS properties. - A: Response.redirecthttps rewriting of the URL argument. - A: UIEvent, MouseEvent, TouchEvent, KeyboardEvent, WheelEvent, InputEvent, and CompositionEven constructor and init{even-name} overrides in order to ensure that wombats JS Proxy usage does not affect their defined behaviors - A: XSLTProcessor override to ensure its usage is not affected by wombats JS Proxy usage. - A: navigator.unregisterProtocolHandler: Same override as existing navigator.registerProtocolHandler but from the inverse operation - A: PresentationRequest: Constructor takes a URL or an array of URLs. - A: EventSource and WebSocket override in order to ensure that they do not cause live leaks - A: overrides for the child node interface - Fix: autofetch worker creatation of the backing worker when it is operating within an execution context with a null origin tests: - A: 559 tests specific to wombat and client side rewritting pywb: - Fix: a few broken tests due to iana.org requiring a user agent in its requests rewrite: - introduced a new JSWorkerRewriter class in order to support rewriting via wombat workers in the context of all supported worker variants via - ensured rewriter app correctly sets the static prefix ci: - Modified travis.yml to specifically enumerate jobs documentation: - Documented new wombat, wombat proxy moded, wombat workers auto-fetch: - switched to mutation observer when in proxy mode so that the behaviors can operate in tandem with the autofetcher
1002 lines
36 KiB
JavaScript
1002 lines
36 KiB
JavaScript
import test from 'ava';
|
|
import {
|
|
ElementGetSetAttribute,
|
|
HTMLAssign,
|
|
LinkAsTypes,
|
|
TextNodeTest,
|
|
WB_PREFIX,
|
|
TagToMod
|
|
} from './helpers/testedValues';
|
|
import { extractModifier, parsedURL } from './helpers/utils';
|
|
import TestHelper from './helpers/testHelper';
|
|
|
|
/**
|
|
* @type {TestHelper}
|
|
*/
|
|
let helper = null;
|
|
|
|
test.before(async t => {
|
|
helper = await TestHelper.init(t);
|
|
await helper.initWombat();
|
|
});
|
|
|
|
test.beforeEach(async t => {
|
|
t.context.sandbox = helper.sandbox();
|
|
t.context.server = helper.server();
|
|
t.context.testPage = helper.testPage();
|
|
});
|
|
|
|
test.afterEach.always(async t => {
|
|
if (t.title.includes('SharedWorker')) {
|
|
await helper.fullRefresh();
|
|
} else {
|
|
await helper.ensureSandbox();
|
|
}
|
|
});
|
|
|
|
test.after.always(async t => {
|
|
await helper.stop();
|
|
});
|
|
|
|
test('document.title: should send the "title" message to the top frame when document.title is changed', async t => {
|
|
const { sandbox, testPage } = t.context;
|
|
await sandbox.evaluate(() => (document.title = 'abc'));
|
|
const result = await testPage.evaluate(
|
|
() =>
|
|
window.overwatch.wbMessages.title != null &&
|
|
window.overwatch.wbMessages.title === 'abc'
|
|
);
|
|
t.true(
|
|
result,
|
|
'the "title" message was not sent to the top frame on document.title changes'
|
|
);
|
|
});
|
|
|
|
test('document.write: should not perform rewriting when "write" is called with no arguments', async t => {
|
|
const { sandbox, testPage } = t.context;
|
|
await sandbox.evaluate(() => {
|
|
document.write();
|
|
document.close();
|
|
});
|
|
t.deepEqual(
|
|
await sandbox.evaluate(() => ({
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
})),
|
|
{ doctype: false, html: '<html><head></head><body></body></html>' },
|
|
'this use case failed'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with one argument', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(expectedURL => {
|
|
document.write('<a id="it" href="http://example.com">hi</a>');
|
|
document.close();
|
|
|
|
const elem = document.getElementById('it');
|
|
if (!elem) return false;
|
|
elem._no_rewrite = true;
|
|
return elem.href === expectedURL;
|
|
}, `${WB_PREFIX}mp_/http://example.com`);
|
|
t.true(
|
|
result,
|
|
'wombat is not rewriting elements when document.write is used'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with multiple arguments', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(expectedURL => {
|
|
document.write(
|
|
'<a id="it" href="http://example.com">hi</a>',
|
|
'<a id="it2" href="http://example.com">hi</a>'
|
|
);
|
|
document.close();
|
|
const results = {
|
|
it: { exists: false, rewritten: false },
|
|
it2: { exists: false, rewritten: false }
|
|
};
|
|
const it = document.getElementById('it');
|
|
if (!it) return results;
|
|
results.it.exists = true;
|
|
it._no_rewrite = true;
|
|
results.it.rewritten = it.href === expectedURL;
|
|
const it2 = document.getElementById('it2');
|
|
if (!it2) return results;
|
|
results.it2.exists = true;
|
|
it2._no_rewrite = true;
|
|
results.it2.rewritten = it.href === expectedURL;
|
|
return results;
|
|
}, `${WB_PREFIX}mp_/http://example.com`);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
it: { exists: true, rewritten: true },
|
|
it2: { exists: true, rewritten: true }
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with multiple values'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with a full string of HTML starting with <!doctype html>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<!doctype html><html><head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body></html>`;
|
|
const expectedHTML = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.write(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: {
|
|
exists: document.doctype != null,
|
|
name: document.doctype.name
|
|
},
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: {
|
|
exists: true,
|
|
name: 'html'
|
|
},
|
|
html: expectedHTML
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <!doctype html>'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with a full string of HTML starting with <html>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<html><head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"/></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body></html>`;
|
|
const expectedRW = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.write(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{ doctype: false, html: expectedRW },
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <html>'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with a full string of HTML starting with <head>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"/></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body>`;
|
|
const expectedRW = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.write(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <head>'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with a full string of HTML starting with <body>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<body><script id="theScript" src="http://javaScript.com/script.js"></script></body>`;
|
|
const expectedRW = `<html><head></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.write(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <body>'
|
|
);
|
|
});
|
|
|
|
test('document.write: should perform rewriting when "write" is called with an arbitrary string of HTML', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<script id="theScript" src="http://javaScript.com/script.js"></script>`;
|
|
const expectedRW = `<html><head><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></head></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.write(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <body>'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should not perform rewriting when "writeln" is called with no arguments', async t => {
|
|
const { sandbox, testPage } = t.context;
|
|
await sandbox.evaluate(() => {
|
|
document.writeln();
|
|
document.close();
|
|
});
|
|
const result = await sandbox.evaluate(() => ({
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
}));
|
|
t.deepEqual(
|
|
result,
|
|
{ doctype: false, html: '<html><head></head><body></body></html>' },
|
|
'this use case failed'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with one argument', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(expectedURL => {
|
|
document.writeln('<a id="it" href="http://example.com">hi</a>');
|
|
document.close();
|
|
const elem = document.getElementById('it');
|
|
if (!elem) return false;
|
|
elem._no_rewrite = true;
|
|
return elem.href === expectedURL;
|
|
}, `${WB_PREFIX}mp_/http://example.com`);
|
|
t.true(
|
|
result,
|
|
'wombat is not rewriting elements when document.writeln is used'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with multiple arguments', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(expectedURL => {
|
|
document.writeln(
|
|
'<a id="it" href="http://example.com">hi</a>',
|
|
'<a id="it2" href="http://example.com">hi</a>'
|
|
);
|
|
document.close();
|
|
const results = {
|
|
it: { exists: false, rewritten: false },
|
|
it2: { exists: false, rewritten: false }
|
|
};
|
|
const it = document.getElementById('it');
|
|
if (!it) return results;
|
|
results.it.exists = true;
|
|
it._no_rewrite = true;
|
|
results.it.rewritten = it.href === expectedURL;
|
|
const it2 = document.getElementById('it2');
|
|
if (!it2) return results;
|
|
results.it2.exists = true;
|
|
it2._no_rewrite = true;
|
|
results.it2.rewritten = it.href === expectedURL;
|
|
return results;
|
|
}, `${WB_PREFIX}mp_/http://example.com`);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
it: { exists: true, rewritten: true },
|
|
it2: { exists: true, rewritten: true }
|
|
},
|
|
'wombat is not rewriting elements when document.writeln is used with multiple values'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with a full string of HTML starting with <!doctype html>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<!doctype html><html><head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body></html>`;
|
|
const expectedHTML = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.writeln(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: {
|
|
exists: document.doctype != null,
|
|
name: document.doctype.name
|
|
},
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: {
|
|
exists: true,
|
|
name: 'html'
|
|
},
|
|
html: expectedHTML
|
|
},
|
|
'wombat is not rewriting elements when document.writeln is used with full strings of html with <!doctype html>'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with a full string of HTML starting with <html>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<html><head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"/></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body></html>`;
|
|
const expectedRW = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.writeln(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{ doctype: false, html: expectedRW },
|
|
'wombat is not rewriting elements when document.writeln is used with full strings of html with <html>'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with a full string of HTML starting with <head>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"/></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body>`;
|
|
const expectedRW = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.writeln(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.writeln is used with full strings of html with <head>'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "writeln" is called with a full string of HTML starting with <body>', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<body><script id="theScript" src="http://javaScript.com/script.js"></script></body>`;
|
|
const expectedRW = `<html><head></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.writeln(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.writeln is used with full strings of html with <body>'
|
|
);
|
|
});
|
|
|
|
test('document.writeln: should perform rewriting when "write" is called with an arbitrary string of HTML', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = `<script id="theScript" src="http://javaScript.com/script.js"></script>`;
|
|
const expectedRW = `<html><head><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></head></html>`;
|
|
const result = await sandbox.evaluate(notRW => {
|
|
document.writeln(notRW);
|
|
document.close();
|
|
document.documentElement._no_rewrite = true;
|
|
return {
|
|
doctype: document.doctype != null,
|
|
html: document.documentElement.outerHTML
|
|
};
|
|
}, unRW);
|
|
t.deepEqual(
|
|
result,
|
|
{
|
|
doctype: false,
|
|
html: expectedRW
|
|
},
|
|
'wombat is not rewriting elements when document.write is used with full strings of html with <body>'
|
|
);
|
|
});
|
|
|
|
test(`document.URL: retrievals should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
() => document.URL === 'https://tests.wombat.io/'
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`document.documentURI: retrievals should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
() => document.documentURI === 'https://tests.wombat.io/'
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`document.baseURI: retrievals should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
() => document.baseURI === 'https://tests.wombat.io/'
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`HTMLStyleElement.textContent: assignments should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theStyle, theStyleRw) => {
|
|
const style = document.createElement('style');
|
|
style.textContent = theStyle;
|
|
style._no_rewrite = true;
|
|
return style.textContent === theStyleRw;
|
|
},
|
|
TextNodeTest.theStyle,
|
|
TextNodeTest.theStyleRw
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`HTMLIframeElement.srcdoc: assignments should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const iframe = document.createElement('iframe');
|
|
const unRW = `<html><head><link id="theLink" rel="stylesheet" href="https://cssHeaven.com/angelic.css"/></head><body><script id="theScript" src="http://javaScript.com/script.js"></script></body></html>`;
|
|
const expectedRW = `<html><head><link id="theLink" rel="stylesheet" href="http://localhost:3030/live/20180803160549cs_/https://cssHeaven.com/angelic.css"></head><body><script id="theScript" src="http://localhost:3030/live/20180803160549js_/http://javaScript.com/script.js"></script></body></html>`;
|
|
iframe.srcdoc = unRW;
|
|
return (
|
|
window.WombatTestUtil.getElementPropertyAsIs(iframe, 'srcdoc') ===
|
|
expectedRW
|
|
);
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
test('Element.insertAdjacentElement: should rewrite elements', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
const a = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a.href = 'http://example.com';
|
|
a.id = 'aa';
|
|
div.insertAdjacentElement('afterend', a);
|
|
const results = window.WombatTestUtil.getElementPropertyAsIs(
|
|
div.nextElementSibling,
|
|
'href'
|
|
);
|
|
div.remove();
|
|
return results.endsWith('mp_/http://example.com');
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
test('Element.insertAdjacentHTML: should rewrite strings of html', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
div.insertAdjacentHTML(
|
|
'afterend',
|
|
'<a id="aa" href="http://example.com"></a>'
|
|
);
|
|
const results = window.WombatTestUtil.getElementPropertyAsIs(
|
|
div.nextElementSibling,
|
|
'href'
|
|
);
|
|
div.remove();
|
|
return results.endsWith('mp_/http://example.com');
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
for (const aTest of ElementGetSetAttribute) {
|
|
if (aTest.elem === 'link') {
|
|
for (const [as, mod] of Object.entries(LinkAsTypes)) {
|
|
test(`<link rel="preload" as="${as}">: should rewrite the value set by setAttribute for the href attribute`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw, theMod) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'preload';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
const asis = window.WombatTestUtil.getElementPropertyAsIs(
|
|
elem,
|
|
prop
|
|
);
|
|
return {
|
|
attr: elem.getAttribute(prop) === unrw,
|
|
asis: asis !== unrw
|
|
};
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw,
|
|
mod
|
|
);
|
|
t.deepEqual(result, { attr: true, asis: true });
|
|
});
|
|
|
|
test(`<link rel="preload" as="${as}">: should rewrite the value set by setAttribute for the href attribute using the correct modifier`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw, theMod) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'preload';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
return window.WombatTestUtil.getElementPropertyAsIs(elem, prop);
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw,
|
|
mod
|
|
);
|
|
t.true(
|
|
result.includes(mod),
|
|
`<link rel="preload" as="${as}"> was not rewritten using the "${mod}"`
|
|
);
|
|
});
|
|
|
|
test(`<link rel="import" as="${as}">: should rewrite the value set by setAttribute for the href attribute`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw, theMod) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'import';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
const asis = window.WombatTestUtil.getElementPropertyAsIs(
|
|
elem,
|
|
prop
|
|
);
|
|
return {
|
|
attr: elem.getAttribute(prop) === unrw,
|
|
asis: asis !== unrw
|
|
};
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw,
|
|
mod
|
|
);
|
|
t.deepEqual(result, { attr: true, asis: true });
|
|
});
|
|
|
|
test(`<link rel="import" as="${as}">: should rewrite the value set by setAttribute for the href attribute using the correct modifier`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw, theMod) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'import';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
return window.WombatTestUtil.getElementPropertyAsIs(elem, prop);
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw,
|
|
mod
|
|
);
|
|
t.true(
|
|
result.includes(mod),
|
|
`<link rel="import" as="${as}"> was not rewritten using the "${mod}"`
|
|
);
|
|
});
|
|
|
|
test(`<link rel="preload" as="${as}">: should un-rewrite the value returned by getAttribute for the href attribute`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'preload';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
return elem.getAttribute(prop) === unrw;
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`<link rel="import" as="${as}">: should un-rewrite the value returned by getAttribute for the href attribute `, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, asV, unrw) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'import';
|
|
elem.as = asV;
|
|
elem.setAttribute(prop, unrw);
|
|
return elem.getAttribute(prop) === unrw;
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
as,
|
|
aTest.unrw
|
|
);
|
|
t.true(result);
|
|
});
|
|
}
|
|
|
|
test(`<link rel="stylesheet">: value for href set by setAttribute should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, unrw) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'stylesheet';
|
|
elem.setAttribute(prop, unrw);
|
|
return (
|
|
window.WombatTestUtil.getElementPropertyAsIs(elem, prop) !== unrw
|
|
);
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
aTest.unrw
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`<link rel="stylesheet">: values returned by getAttribute for the href attribute should be un-rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
(theElem, prop, unrw) => {
|
|
const elem = document.createElement(theElem);
|
|
elem.rel = 'stylesheet';
|
|
elem.setAttribute(prop, unrw);
|
|
return elem.getAttribute(prop) === unrw;
|
|
},
|
|
aTest.elem,
|
|
aTest.prop,
|
|
aTest.unrw
|
|
);
|
|
t.true(result);
|
|
});
|
|
} else {
|
|
for (let i = 0; i < aTest.props.length; i++) {
|
|
const prop = aTest.props[i];
|
|
const unrw = aTest.unrws[i];
|
|
test(`${
|
|
aTest.elem
|
|
}.${prop}: the value set using setAttribute should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(testFn, aTest.elem, prop, unrw);
|
|
t.true(result);
|
|
function testFn(theElem, prop, unrw) {
|
|
const elem = document.createElement(theElem);
|
|
elem.setAttribute(prop, unrw);
|
|
return (
|
|
window.WombatTestUtil.getElementPropertyAsIs(elem, prop) !== unrw
|
|
);
|
|
}
|
|
});
|
|
|
|
test(`${
|
|
aTest.elem
|
|
}.${prop}: the value retrieved by getAttribute should be un-rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(testFn, aTest.elem, prop, unrw);
|
|
t.true(result);
|
|
function testFn(theElem, prop, unrw) {
|
|
const elem = document.createElement(theElem);
|
|
elem.setAttribute(prop, unrw);
|
|
return elem.getAttribute(prop) === unrw;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
test('Node.ownerDocument: should return the document Proxy object when accessed', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
() => document.body.ownerDocument === document._WB_wombat_obj_proxy
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test('Node.appendChild: should rewrite a element with no children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
const a = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a.href = 'http://example.com';
|
|
div.appendChild(a);
|
|
return window.WombatTestUtil.getElementPropertyAsIs(a, 'href').endsWith(
|
|
'mp_/http://example.com'
|
|
);
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
test('Node.appendChild: should rewrite a element with multiple children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
const a1 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a2 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a3 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a1.href = 'http://example1.com';
|
|
a2.href = 'http://example2.com';
|
|
a3.href = 'http://example3.com';
|
|
div.appendChild(a2);
|
|
div.appendChild(a3);
|
|
div.appendChild(a1);
|
|
return {
|
|
a1: window.WombatTestUtil.getElementPropertyAsIs(a1, 'href').endsWith(
|
|
'mp_/http://example1.com'
|
|
),
|
|
a2: window.WombatTestUtil.getElementPropertyAsIs(a2, 'href').endsWith(
|
|
'mp_/http://example2.com'
|
|
),
|
|
a3: window.WombatTestUtil.getElementPropertyAsIs(a3, 'href').endsWith(
|
|
'mp_/http://example3.com'
|
|
)
|
|
};
|
|
});
|
|
t.deepEqual(result, { a1: true, a2: true, a3: true });
|
|
});
|
|
|
|
test('Node.insertBefore: should rewrite a element with no children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
const a = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a.href = 'http://example.com';
|
|
document.body.insertBefore(a, div);
|
|
const result = window.WombatTestUtil.getElementPropertyAsIs(
|
|
a,
|
|
'href'
|
|
).endsWith('mp_/http://example.com');
|
|
div.remove();
|
|
a.remove();
|
|
return result;
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
test('Node.insertBefore: should rewrite a element with multiple children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
const div2 = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
const a1 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a2 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a3 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a1.href = 'http://example1.com';
|
|
a2.href = 'http://example2.com';
|
|
a3.href = 'http://example3.com';
|
|
div2.appendChild(a1);
|
|
div2.appendChild(a2);
|
|
div2.appendChild(a3);
|
|
document.body.insertBefore(div2, div);
|
|
const result = {
|
|
a1: window.WombatTestUtil.getElementPropertyAsIs(a1, 'href').endsWith(
|
|
'mp_/http://example1.com'
|
|
),
|
|
a2: window.WombatTestUtil.getElementPropertyAsIs(a2, 'href').endsWith(
|
|
'mp_/http://example2.com'
|
|
),
|
|
a3: window.WombatTestUtil.getElementPropertyAsIs(a3, 'href').endsWith(
|
|
'mp_/http://example3.com'
|
|
)
|
|
};
|
|
div.remove();
|
|
a1.remove();
|
|
return result;
|
|
});
|
|
t.deepEqual(result, { a1: true, a2: true, a3: true });
|
|
});
|
|
|
|
test('Node.replaceChild: should rewrite a element with no children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
const a = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a.href = 'http://example.com';
|
|
document.body.replaceChild(a, div);
|
|
const result = window.WombatTestUtil.getElementPropertyAsIs(
|
|
a,
|
|
'href'
|
|
).endsWith('mp_/http://example.com');
|
|
a.remove();
|
|
return result;
|
|
});
|
|
t.true(result);
|
|
});
|
|
|
|
test('Node.replaceChild: should rewrite a element with multiple children are supplied', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
const div2 = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
const a1 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a2 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
const a3 = window.WombatTestUtil.createUntamperedWithElement('a');
|
|
a1.href = 'http://example1.com';
|
|
a2.href = 'http://example2.com';
|
|
a3.href = 'http://example3.com';
|
|
div2.appendChild(a1);
|
|
div2.appendChild(a2);
|
|
div2.appendChild(a3);
|
|
document.body.replaceChild(div2, div);
|
|
const result = {
|
|
a1: window.WombatTestUtil.getElementPropertyAsIs(a1, 'href').endsWith(
|
|
'mp_/http://example1.com'
|
|
),
|
|
a2: window.WombatTestUtil.getElementPropertyAsIs(a2, 'href').endsWith(
|
|
'mp_/http://example2.com'
|
|
),
|
|
a3: window.WombatTestUtil.getElementPropertyAsIs(a3, 'href').endsWith(
|
|
'mp_/http://example3.com'
|
|
)
|
|
};
|
|
a1.remove();
|
|
return result;
|
|
});
|
|
t.deepEqual(result, { a1: true, a2: true, a3: true });
|
|
});
|
|
|
|
test('Audio: should rewrite the URL argument to the constructor', async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
() =>
|
|
window.WombatTestUtil.getElementPropertyAsIs(
|
|
new Audio('https://music.com/music.mp3'),
|
|
'src'
|
|
) === '/live/20180803160549oe_/https://music.com/music.mp3'
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test('FontFace: should rewrite the source argument to the constructor', async t => {
|
|
const { sandbox, server } = t.context;
|
|
await Promise.all([
|
|
server.waitForRequest(
|
|
'/live/20180803160549mp_/https://tests.wombat.io/daFont.woff2'
|
|
),
|
|
sandbox.evaluate(async () => {
|
|
try {
|
|
const ff = new FontFace('DaFont', 'url(daFont.woff2)');
|
|
await ff.load();
|
|
} catch (e) {}
|
|
})
|
|
]);
|
|
// the server will automatically reject the waitForRequest promise after 15s
|
|
t.pass('URLs used in the construction of FontFaces are rewritten');
|
|
});
|
|
|
|
for (const fnTest of TextNodeTest.fnTests) {
|
|
test(`Text.${fnTest}: data argument should be rewritten when it is a child of a style tag`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
TextNodeTest.evaluationFN,
|
|
fnTest,
|
|
TextNodeTest.theStyle,
|
|
TextNodeTest.theStyleRw,
|
|
true
|
|
);
|
|
t.true(result);
|
|
});
|
|
test(`Text.${fnTest}: data argument should not be rewritten when it is not a child of a style tag`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
TextNodeTest.evaluationFN,
|
|
fnTest,
|
|
TextNodeTest.theStyle,
|
|
TextNodeTest.theStyleRw,
|
|
false
|
|
);
|
|
t.true(result);
|
|
});
|
|
}
|
|
|
|
for (const aTest of HTMLAssign.innerOuterHTML.tests) {
|
|
test(`${aTest.which}: assignments should be rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
HTMLAssign.innerOuterHTML.assignmentFN,
|
|
aTest.which,
|
|
aTest.unrw,
|
|
aTest.rw
|
|
);
|
|
t.true(result);
|
|
});
|
|
|
|
test(`${aTest.which}: retrials should be un-rewritten`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
HTMLAssign.innerOuterHTML.retrieval,
|
|
aTest.which,
|
|
aTest.unrw,
|
|
aTest.rw
|
|
);
|
|
t.is(result, aTest.unrw);
|
|
});
|
|
|
|
test(`${
|
|
aTest.which
|
|
}: assignments to the retrial of the property should work`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const result = await sandbox.evaluate(
|
|
HTMLAssign.innerOuterHTML.assignmentToRetrieval,
|
|
aTest.which,
|
|
aTest.unrw,
|
|
aTest.rw
|
|
);
|
|
t.true(result);
|
|
});
|
|
}
|
|
|
|
for (const [tag, attrMods] of Object.entries(TagToMod.elements)) {
|
|
for (const [attr, mod] of Object.entries(attrMods)) {
|
|
test(`${tag}.${attr}: rewrites of direct attribute assignment should use the "${mod}" modifier`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = 'https://example.com';
|
|
const result = await sandbox.evaluate(TagToMod.testFNDirect, tag, attr, unRW);
|
|
t.true(
|
|
result !== unRW,
|
|
`Assignments to ${tag}.${attr} is not being rewritten`
|
|
);
|
|
const existingModifier = extractModifier(result);
|
|
t.is(
|
|
existingModifier,
|
|
mod,
|
|
`Assignments to ${tag}.${attr} is not being rewritten using the "${mod}" modifier`
|
|
);
|
|
});
|
|
|
|
test(`${tag}.${attr}: rewrites of attribute assignment using setAttribute should use the "${mod}" modifier`, async t => {
|
|
const { sandbox, server } = t.context;
|
|
const unRW = 'https://example.com';
|
|
const result = await sandbox.evaluate(TagToMod.testFNSetAttr, tag, attr, unRW);
|
|
t.true(
|
|
result !== unRW,
|
|
`Assignments to ${tag}.${attr} is not being rewritten`
|
|
);
|
|
const existingModifier = extractModifier(result);
|
|
t.is(
|
|
existingModifier,
|
|
mod,
|
|
`Assignments to ${tag}.${attr} is not being rewritten using the "${mod}" modifier`
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|