162 lines
26 KiB
JavaScript
162 lines
26 KiB
JavaScript
|
"use strict";
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
const testcafe_hammerhead_1 = require("testcafe-hammerhead");
|
||
|
const injectables_1 = require("../assets/injectables");
|
||
|
const empty_page_markup_1 = __importDefault(require("./empty-page-markup"));
|
||
|
const http_status_codes_1 = require("http-status-codes");
|
||
|
const test_run_1 = require("../errors/test-run");
|
||
|
const cdp_1 = require("./utils/cdp");
|
||
|
const debug_loggers_1 = require("../utils/debug-loggers");
|
||
|
const string_1 = require("./utils/string");
|
||
|
const safe_api_1 = require("./request-pipeline/safe-api");
|
||
|
const RESPONSE_REMOVED_HEADERS = [
|
||
|
'cross-origin-embedder-policy',
|
||
|
'cross-origin-opener-policy',
|
||
|
'cross-origin-resource-policy',
|
||
|
];
|
||
|
class ResourceInjector {
|
||
|
constructor(testRunBridge, specialServiceRoutes) {
|
||
|
this._specialServiceRoutes = specialServiceRoutes;
|
||
|
this._testRunBridge = testRunBridge;
|
||
|
}
|
||
|
_getRestoreContextStorageScript(contextStorage) {
|
||
|
const currentTestRun = this._testRunBridge.getCurrentTestRun();
|
||
|
const value = JSON.stringify((contextStorage === null || contextStorage === void 0 ? void 0 : contextStorage[currentTestRun.id]) || '');
|
||
|
return `Object.defineProperty(window, '%proxylessContextStorage%', { configurable: true, value: ${value} });`;
|
||
|
}
|
||
|
_getRestoreStoragesScript(restoringStorages) {
|
||
|
if (!restoringStorages)
|
||
|
return '(function() {})()';
|
||
|
return `(function() {
|
||
|
window.localStorage.clear();
|
||
|
window.sessionStorage.clear();
|
||
|
|
||
|
const snapshot = ${JSON.stringify(restoringStorages)};
|
||
|
const ls = JSON.parse(snapshot.localStorage);
|
||
|
const ss = JSON.parse(snapshot.sessionStorage);
|
||
|
|
||
|
for (let i = 0; i < ls[0].length; i++)
|
||
|
window.localStorage.setItem(ls[0][i], ls[1][i]);
|
||
|
|
||
|
for (let i = 0; i < ss[0].length; i++)
|
||
|
window.sessionStorage.setItem(ss[0][i], ss[1][i]);
|
||
|
})();
|
||
|
`;
|
||
|
}
|
||
|
_resolveRelativeUrls(proxy, relativeUrls) {
|
||
|
return relativeUrls.map(url => proxy.resolveRelativeServiceUrl(url));
|
||
|
}
|
||
|
async _prepareInjectableResources({ isIframe, restoringStorages, contextStorage, userScripts }) {
|
||
|
if (!this._testRunBridge.getCurrentTestRun())
|
||
|
return null;
|
||
|
const taskScript = await this._testRunBridge.getTaskScript({ isIframe, restoringStorages, contextStorage, userScripts });
|
||
|
const proxy = this._testRunBridge.getBrowserConnection().browserConnectionGateway.proxy;
|
||
|
const injectableResources = {
|
||
|
stylesheets: [
|
||
|
injectables_1.TESTCAFE_UI_STYLES,
|
||
|
],
|
||
|
scripts: [
|
||
|
...testcafe_hammerhead_1.INJECTABLE_SCRIPTS.map(hs => (0, testcafe_hammerhead_1.getAssetPath)(hs, proxy.options.developmentMode)),
|
||
|
...injectables_1.SCRIPTS.map(s => (0, testcafe_hammerhead_1.getAssetPath)(s, proxy.options.developmentMode)),
|
||
|
],
|
||
|
embeddedScripts: [this._getRestoreStoragesScript(restoringStorages), this._getRestoreContextStorageScript(contextStorage), taskScript],
|
||
|
userScripts: userScripts || [],
|
||
|
};
|
||
|
injectableResources.scripts = this._resolveRelativeUrls(proxy, injectableResources.scripts);
|
||
|
injectableResources.userScripts = this._resolveRelativeUrls(proxy, injectableResources.userScripts);
|
||
|
injectableResources.stylesheets = this._resolveRelativeUrls(proxy, injectableResources.stylesheets);
|
||
|
return injectableResources;
|
||
|
}
|
||
|
_processResponseHeaders(headers) {
|
||
|
if (!headers)
|
||
|
return [];
|
||
|
headers = headers.filter(header => !RESPONSE_REMOVED_HEADERS.includes(header.name.toLowerCase()));
|
||
|
return (0, string_1.stringifyHeaderValues)(headers);
|
||
|
}
|
||
|
async _fulfillRequest(client, fulfillRequestInfo, body) {
|
||
|
await (0, safe_api_1.safeFulfillRequest)(client, {
|
||
|
requestId: fulfillRequestInfo.requestId,
|
||
|
responseCode: fulfillRequestInfo.responseCode || http_status_codes_1.StatusCodes.OK,
|
||
|
responsePhrase: fulfillRequestInfo.responsePhrase,
|
||
|
responseHeaders: this._processResponseHeaders(fulfillRequestInfo.responseHeaders),
|
||
|
body: (0, string_1.toBase64String)(body),
|
||
|
});
|
||
|
}
|
||
|
async redirectToErrorPage(client, err, url) {
|
||
|
const currentTestRun = this._testRunBridge.getCurrentTestRun();
|
||
|
if (!currentTestRun)
|
||
|
return;
|
||
|
currentTestRun.pendingPageError = new test_run_1.PageLoadError(err, url);
|
||
|
await (0, cdp_1.navigateTo)(client, this._specialServiceRoutes.errorPage1);
|
||
|
}
|
||
|
async getDocumentResourceInfo(event, client) {
|
||
|
const { requestId, request, responseErrorReason, resourceType, } = event;
|
||
|
if (resourceType !== 'Document') {
|
||
|
return {
|
||
|
error: null,
|
||
|
body: null,
|
||
|
};
|
||
|
}
|
||
|
try {
|
||
|
if (responseErrorReason === 'NameNotResolved') {
|
||
|
const err = new Error(`Failed to find a DNS-record for the resource at "${event.request.url}"`);
|
||
|
return {
|
||
|
error: err,
|
||
|
body: null,
|
||
|
};
|
||
|
}
|
||
|
const responseObj = await client.Fetch.getResponseBody({ requestId });
|
||
|
const responseStr = (0, string_1.getResponseAsString)(responseObj);
|
||
|
return {
|
||
|
error: null,
|
||
|
body: Buffer.from(responseStr),
|
||
|
};
|
||
|
}
|
||
|
catch (err) {
|
||
|
(0, debug_loggers_1.resourceInjectorLogger)('Failed to process request: %s', request.url);
|
||
|
return {
|
||
|
error: err,
|
||
|
body: null,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
async processAboutBlankPage(event, userScripts, client) {
|
||
|
(0, debug_loggers_1.resourceInjectorLogger)('Handle page as about:blank. Origin url: %s', event.frame.url);
|
||
|
const injectableResources = await this._prepareInjectableResources({ isIframe: false, userScripts });
|
||
|
const html = (0, testcafe_hammerhead_1.injectResources)(empty_page_markup_1.default, injectableResources);
|
||
|
await client.Page.setDocumentContent({
|
||
|
frameId: event.frame.id,
|
||
|
html,
|
||
|
});
|
||
|
}
|
||
|
async processHTMLPageContent(fulfillRequestInfo, injectableResourcesOptions, client) {
|
||
|
const injectableResources = await this._prepareInjectableResources(injectableResourcesOptions);
|
||
|
// NOTE: an unhandled exception interrupts the test execution,
|
||
|
// and we are force to redirect manually to the idle page.
|
||
|
if (!injectableResources)
|
||
|
await (0, cdp_1.redirect)(client, fulfillRequestInfo.requestId, this._specialServiceRoutes.idlePage);
|
||
|
else {
|
||
|
const updatedResponseStr = (0, testcafe_hammerhead_1.injectResources)(fulfillRequestInfo.body, injectableResources, this._getPageInjectableResourcesOptions(injectableResourcesOptions));
|
||
|
await this._fulfillRequest(client, fulfillRequestInfo, updatedResponseStr);
|
||
|
}
|
||
|
}
|
||
|
async processNonProxiedContent(fulfillRequestInfo, client) {
|
||
|
await this._fulfillRequest(client, fulfillRequestInfo, fulfillRequestInfo.body);
|
||
|
}
|
||
|
_getPageInjectableResourcesOptions(injectableResourcesOptions) {
|
||
|
const { url, restoringStorages } = injectableResourcesOptions;
|
||
|
if (url && restoringStorages) {
|
||
|
return {
|
||
|
host: new URL(url).host,
|
||
|
sessionId: this._testRunBridge.getSessionId(),
|
||
|
};
|
||
|
}
|
||
|
return void 0;
|
||
|
}
|
||
|
}
|
||
|
exports.default = ResourceInjector;
|
||
|
module.exports = exports.default;
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaW5qZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJveHlsZXNzL3Jlc291cmNlLWluamVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBTUEsNkRBUTZCO0FBQzdCLHVEQUFvRTtBQUNwRSw0RUFBb0Q7QUFDcEQseURBQWdEO0FBQ2hELGlEQUFtRDtBQUNuRCxxQ0FBbUQ7QUFTbkQsMERBQWdFO0FBQ2hFLDJDQUl3QjtBQUN4QiwwREFBaUU7QUFHakUsTUFBTSx3QkFBd0IsR0FBRztJQUM3Qiw4QkFBOEI7SUFDOUIsNEJBQTRCO0lBQzVCLDhCQUE4QjtDQUNqQyxDQUFDO0FBRUYsTUFBcUIsZ0JBQWdCO0lBSWpDLFlBQW9CLGFBQTRCLEVBQUUsb0JBQTBDO1FBQ3hGLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxvQkFBb0IsQ0FBQztRQUNsRCxJQUFJLENBQUMsY0FBYyxHQUFVLGFBQWEsQ0FBQztJQUMvQyxDQUFDO0lBRU8sK0JBQStCLENBQUUsY0FBMEM7UUFDL0UsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQy9ELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQSxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUcsY0FBYyxDQUFDLEVBQUUsQ0FBQyxLQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRXhFLE9BQU8sMkZBQTJGLEtBQUssTUFBTSxDQUFDO0lBQ2xILENBQUM7SUFFTyx5QkFBeUIsQ0FBRSxpQkFBc0Q7UUFDckYsSUFBSSxDQUFDLGlCQUFpQjtZQUNsQixPQUFPLG1CQUFtQixDQUFDO1FBRS9CLE9BQU87Ozs7K0JBSWdCLElBQUksQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUM7Ozs7Ozs7Ozs7U0FVdkQsQ0FBQztJQUNOLENBQUM7SUFFTyxvQkFBb0IsQ0FBRSxLQUFZLEVBQUUsWUFBc0I7UUFDOUQs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
|