From 7968db63eb9899961dec19655904502334043735 Mon Sep 17 00:00:00 2001 From: Cyrus Chan Date: Fri, 12 Apr 2019 15:16:12 -0700 Subject: [PATCH] fix(client): Enable loading different file types when running in parent mode without iframe (#3289) * fix(client): Includes attributes like type in script tags when running in parent mode without iframe Back in #2542, a third option to run tests without iframe is implemented, mostly for lightweight browser. It only allows script element to be loaded dynamically. This fix includes file type like .css to be loaded properly. Fixes #3289 --- client/karma.js | 21 ++++++++++++++++++--- lib/middleware/karma.js | 17 ++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/client/karma.js b/client/karma.js index 97b3b62fe..c7f646963 100644 --- a/client/karma.js +++ b/client/karma.js @@ -62,12 +62,27 @@ function Karma (socket, iframe, opener, navigator, location) { childWindow.close() } childWindow = opener(url) - // run context on parent element and dynamically loading scripts + // run context on parent element (client_with_context) + // using window.__karma__.scriptUrls to get the html element strings and load them dynamically } else if (url !== 'about:blank') { var loadScript = function (idx) { if (idx < window.__karma__.scriptUrls.length) { - var ele = document.createElement('script') - ele.src = window.__karma__.scriptUrls[idx] + var parser = new DOMParser() + // Revert escaped characters with special roles in HTML before parsing + var string = window.__karma__.scriptUrls[idx] + .replace(/\\x3C/g, '<') + .replace(/\\x3E/g, '>') + var doc = parser.parseFromString(string, 'text/html') + var ele = doc.head.firstChild || doc.body.firstChild + // script elements created by DomParser are marked as unexecutable, + // create a new script element manually and copy necessary properties + // so it is executable + if (ele.tagName && ele.tagName.toLowerCase() === 'script') { + var tmp = ele + ele = document.createElement('script') + ele.src = tmp.src + ele.crossOrigin = tmp.crossOrigin + } ele.onload = function () { loadScript(idx + 1) } diff --git a/lib/middleware/karma.js b/lib/middleware/karma.js index c51c34491..cf7a93ec6 100644 --- a/lib/middleware/karma.js +++ b/lib/middleware/karma.js @@ -175,7 +175,6 @@ function createKarmaMiddleware ( common.setNoCacheHeaders(response) const scriptTags = [] - const scriptUrls = [] for (const file of files.included) { let filePath = file.path const fileType = file.type || path.extname(filePath).substring(1) @@ -192,8 +191,6 @@ function createKarmaMiddleware ( } } - scriptUrls.push(filePath) - if (fileType === 'css') { scriptTags.push(``) } else if (fileType === 'dom') { @@ -207,6 +204,20 @@ function createKarmaMiddleware ( } } + const scriptUrls = [] + // For client_with_context, html elements are not added directly through an iframe. + // Instead, scriptTags is stored to window.__karma__.scriptUrls first. Later, the + // client will read window.__karma__.scriptUrls and dynamically add them to the DOM + // using DOMParser. + if (requestUrl === '/client_with_context.html') { + for (const script of scriptTags) { + scriptUrls.push( + // Escape characters with special roles (tags) in HTML. Open angle brackets are parsed as tags + // immediately, even if it is within double quotations in browsers + script.replace(//g, '\\x3E')) + } + } + const mappings = data.includes('%MAPPINGS%') ? files.served.map((file) => { const filePath = filePathToUrlPath(file.path, basePath, urlRoot, proxyPath) .replace(/\\/g, '\\\\') // Windows paths contain backslashes and generate bad IDs if not escaped