Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(client): Enable loading different file types when running in parent mode without iframe #3289

21 changes: 18 additions & 3 deletions client/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
17 changes: 14 additions & 3 deletions lib/middleware/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -192,8 +191,6 @@ function createKarmaMiddleware (
}
}

scriptUrls.push(filePath)

if (fileType === 'css') {
scriptTags.push(`<link type="text/css" href="${filePath}" rel="stylesheet">`)
} else if (fileType === 'dom') {
Expand All @@ -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, '\\x3C').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
Expand Down