blob: 1bb4941e63b8950844b5d3816588732da05cd2e8 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview using private properties isn't a Closure violation in tests.
* @suppress {accessControls}
*/
BindingsTestRunner.cleanupURL = function(url) {
if (!url.startsWith('debugger://')) {
return url;
}
return url.replace(/VM\d+/g, 'VM[XXX]');
};
BindingsTestRunner.dumpWorkspace = function(previousSnapshot) {
const uiSourceCodes = Workspace.workspace.uiSourceCodes().slice();
let urls = uiSourceCodes.map(code => code.url());
urls = urls.map(BindingsTestRunner.cleanupURL);
urls.sort(String.caseInsensetiveComparator);
const isAdded = new Array(urls.length).fill(false);
let removedLines = [];
if (previousSnapshot) {
const diff = Diff.Diff.lineDiff(previousSnapshot, urls);
const removedEntries = diff.filter(entry => entry[0] === Diff.Diff.Operation.Delete).map(entry => entry[1]);
removedLines = [].concat.apply([], removedEntries);
let index = 0;
for (const entry of diff) {
if (entry[0] === Diff.Diff.Operation.Delete) {
continue;
}
if (entry[0] === Diff.Diff.Operation.Equal) {
index += entry[1].length;
continue;
}
// eslint-disable-next-line no-unused-vars
for (const line of entry[1]) {
isAdded[index++] = true;
}
}
const addedEntries = diff.filter(entry => entry[0] === Diff.Diff.Operation.Insert).map(entry => entry[1]);
addedLines = [].concat.apply([], addedEntries);
}
TestRunner.addResult(`Removed: ${removedLines.length} uiSourceCodes`);
for (const url of removedLines) {
TestRunner.addResult('[-] ' + url);
}
TestRunner.addResult(`Workspace: ${urls.length} uiSourceCodes.`);
for (let i = 0; i < urls.length; ++i) {
const url = urls[i];
const prefix = (isAdded[i] ? '[+] ' : ' ');
TestRunner.addResult(prefix + url);
}
return urls;
};
BindingsTestRunner.attachFrame = function(frameId, url, evalSourceURL) {
let evalSource = `(${attachFrame.toString()})('${frameId}', '${url}')`;
if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
}
return TestRunner.evaluateInPageAsync(evalSource);
function attachFrame(frameId, url) {
const frame = document.createElement('iframe');
frame.src = url;
frame.id = frameId;
document.body.appendChild(frame);
return new Promise(x => frame.onload = x);
}
};
BindingsTestRunner.detachFrame = function(frameId, evalSourceURL) {
let evalSource = `(${detachFrame.toString()})('${frameId}')`;
if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
}
return TestRunner.evaluateInPageAnonymously(evalSource);
function detachFrame(frameId) {
const frame = document.getElementById(frameId);
frame.remove();
}
};
BindingsTestRunner.navigateFrame = function(frameId, navigateURL, evalSourceURL) {
let evalSource = `(${navigateFrame.toString()})('${frameId}', '${navigateURL}')`;
if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
}
return TestRunner.evaluateInPageAsync(evalSource);
function navigateFrame(frameId, url) {
const frame = document.getElementById(frameId);
frame.src = url;
return new Promise(x => frame.onload = x);
}
};
BindingsTestRunner.attachShadowDOM = function(id, templateSelector, evalSourceURL) {
let evalSource = `(${createShadowDOM.toString()})('${id}', '${templateSelector}')`;
if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
}
return TestRunner.evaluateInPageAnonymously(evalSource);
function createShadowDOM(id, templateSelector) {
const shadowHost = document.createElement('div');
shadowHost.setAttribute('id', id);
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
const t = document.querySelector(templateSelector);
const instance = t.content.cloneNode(true);
shadowRoot.appendChild(instance);
document.body.appendChild(shadowHost);
}
};
BindingsTestRunner.detachShadowDOM = function(id, evalSourceURL) {
let evalSource = `(${removeShadowDOM.toString()})('${id}')`;
if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
}
return TestRunner.evaluateInPageAnonymously(evalSource);
function removeShadowDOM(id) {
document.querySelector('#' + id).remove();
}
};
BindingsTestRunner.waitForStyleSheetRemoved = function(urlSuffix) {
let fulfill;
const promise = new Promise(x => fulfill = x);
TestRunner.cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, onStyleSheetRemoved);
return promise;
function onStyleSheetRemoved(event) {
const styleSheetHeader = event.data;
if (!styleSheetHeader.resourceURL().endsWith(urlSuffix)) {
return;
}
TestRunner.cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, onStyleSheetRemoved);
fulfill();
}
};
TestRunner.addSniffer(Bindings.CompilerScriptMapping.prototype, '_sourceMapAttachedForTest', onSourceMap, true);
TestRunner.addSniffer(Bindings.SASSSourceMapping.prototype, '_sourceMapAttachedForTest', onSourceMap, true);
const sourceMapCallbacks = new Map();
function onSourceMap(sourceMap) {
for (const urlSuffix of sourceMapCallbacks.keys()) {
if (sourceMap.url().endsWith(urlSuffix)) {
const callback = sourceMapCallbacks.get(urlSuffix);
callback.call(null);
sourceMapCallbacks.delete(urlSuffix);
}
}
}
BindingsTestRunner.waitForSourceMap = function(sourceMapURLSuffix) {
let fulfill;
const promise = new Promise(x => fulfill = x);
sourceMapCallbacks.set(sourceMapURLSuffix, fulfill);
return promise;
};
const locationPool = new Bindings.LiveLocationPool();
const nameSymbol = Symbol('LiveLocationNameForTest');
const createdSymbol = Symbol('LiveLocationCreated');
BindingsTestRunner.createDebuggerLiveLocation = function(name, urlSuffix, lineNumber, columnNumber) {
const script = TestRunner.debuggerModel.scripts().find(script => script.sourceURL.endsWith(urlSuffix));
const rawLocation = TestRunner.debuggerModel.createRawLocation(script, lineNumber || 0, columnNumber || 0);
return Bindings.debuggerWorkspaceBinding.createLiveLocation(
rawLocation, updateDelegate.bind(null, name), locationPool);
};
BindingsTestRunner.createCSSLiveLocation = function(name, urlSuffix, lineNumber, columnNumber) {
const header = TestRunner.cssModel.styleSheetHeaders().find(header => header.resourceURL().endsWith(urlSuffix));
const rawLocation = new SDK.CSSLocation(header, lineNumber || 0, columnNumber || 0);
return Bindings.cssWorkspaceBinding.createLiveLocation(rawLocation, updateDelegate.bind(null, name), locationPool);
};
function updateDelegate(name, liveLocation) {
liveLocation[nameSymbol] = name;
const hint = (liveLocation[createdSymbol] ? '[ UPDATE ]' : '[ CREATE ]');
liveLocation[createdSymbol] = true;
BindingsTestRunner.dumpLocation(liveLocation, hint);
}
BindingsTestRunner.dumpLocation = function(liveLocation, hint) {
hint = hint || '[ GET ]';
const prefix = `${hint} LiveLocation-${liveLocation[nameSymbol]}: `;
const uiLocation = liveLocation.uiLocation();
if (!uiLocation) {
TestRunner.addResult(prefix + 'null');
return;
}
TestRunner.addResult(
prefix + BindingsTestRunner.cleanupURL(uiLocation.uiSourceCode.url()) + ':' + uiLocation.lineNumber + ':' +
uiLocation.columnNumber);
};