@web/test-runner-webdriver
Version:
Webdriver browser launcher for Web Test Runner
150 lines • 5.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IFrameManager = void 0;
const coverage_js_1 = require("./coverage.js");
/**
* Manages tests to be executed in iframes on a page.
*/
class IFrameManager {
constructor(config, driver, isIE) {
this.framePerSession = new Map();
this.inactiveFrames = [];
this.frameCount = 0;
this.initialized = false;
this.config = config;
this.driver = driver;
this.isIE = isIE;
}
async _initialize(url) {
const pageUrl = `${new URL(url).origin}/?mode=iframe`;
await this.driver.navigateTo(pageUrl);
}
isActive(id) {
return this.framePerSession.has(id);
}
async getBrowserUrl(sessionId) {
const frameId = this.getFrameId(sessionId);
const returnValue = (await this.driver.execute(`
try {
var iframe = document.getElementById("${frameId}");
return iframe.contentWindow.location.href;
} catch (_) {
return undefined;
}
`));
return returnValue;
}
getFrameId(sessionId) {
const frameId = this.framePerSession.get(sessionId);
if (!frameId) {
throw new Error(`Something went wrong while running tests, there is no frame id for session ${sessionId}`);
}
return frameId;
}
async scheduleCommand(fn) {
if (!this.isIE) {
return fn();
}
while (this.locked) {
await this.locked;
}
const fnPromise = fn();
this.locked = fnPromise;
const result = await fnPromise;
this.locked = undefined;
return result;
}
async queueStartSession(id, url) {
if (!this.initializePromise && !this.initialized) {
this.initializePromise = this._initialize(url);
}
if (this.initializePromise) {
await this.initializePromise;
this.initializePromise = undefined;
this.initialized = true;
}
this.scheduleCommand(() => this.startSession(id, url));
}
async startSession(id, url) {
let frameId;
if (this.inactiveFrames.length > 0) {
frameId = this.inactiveFrames.pop();
await this.driver.execute(`
var iframe = document.getElementById("${frameId}");
iframe.src = "${url}";
`);
}
else {
this.frameCount += 1;
frameId = `wtr-test-frame-${this.frameCount}`;
await this.driver.execute(`
var iframe = document.createElement("iframe");
iframe.id = "${frameId}";
iframe.src = "${url}";
document.body.appendChild(iframe);
`);
}
this.framePerSession.set(id, frameId);
}
async queueStopSession(id) {
return this.scheduleCommand(() => this.stopSession(id));
}
async stopSession(id) {
const frameId = this.getFrameId(id);
// Retrieve test results from iframe
const returnValue = await this.driver.executeAsync(`
var iframe = document.getElementById("${frameId}");
var testCoverage;
try {
testCoverage = iframe.contentWindow.__coverage__;
} catch (error) {
// iframe can throw a cross-origin error if the test navigated
}
// Don't move on until the iframe has settled after unloading the page
var done = arguments[arguments.length-1];
var loaded = function() {
iframe.removeEventListener('load', loaded);
iframe.removeEventListener('error', loaded);
done({ testCoverage: testCoverage });
};
iframe.addEventListener('load', loaded);
iframe.addEventListener('error', loaded);
// set src after retrieving values to avoid the iframe from navigating away
iframe.src = "about:blank";
`);
if (!(0, coverage_js_1.validateBrowserResult)(returnValue)) {
throw new Error();
}
const { testCoverage } = returnValue;
this.inactiveFrames.push(frameId);
return { testCoverage: this.config.coverage ? testCoverage : undefined };
}
async sendKeys(sessionId, keys) {
const frameId = this.getFrameId(sessionId);
const frame = await this.driver.$(`iframe#${frameId}`);
await this.driver.switchToFrame(frame);
return this.driver.keys(keys);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async performActions(_, _actions) {
throw new Error('Unsupported operation. In order to use device actions in Webdriver, set "concurrency" to 1.');
}
async takeScreenshot(sessionId, locator) {
const frameId = this.getFrameId(sessionId);
const frame = await this.driver.$(`iframe#${frameId}`);
await this.driver.switchToFrame(frame);
const elementData = (await this.driver.execute(locator, []));
const element = await this.driver.$(elementData).getElement();
let base64 = '';
try {
base64 = await this.driver.takeElementScreenshot(element.elementId);
}
catch (err) {
console.log('Failed to take a screenshot:', err);
}
await this.driver.switchToParentFrame();
return Buffer.from(base64, 'base64');
}
}
exports.IFrameManager = IFrameManager;
//# sourceMappingURL=IFrameManager.js.map