-
Notifications
You must be signed in to change notification settings - Fork 781
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browser: Finish extraction of browser runner from HTML Reporter
This refactors the initFixture and initUrlconfig code to be an exported callable so that it is safe to define without side-effects and can then be called conditionally. The previous code was already conditionally with an inline check for window/document. This is now centralised in prep for making it further conditional on whether or not QUnit was already exported, thus making it safe to load QUnit twice (e.g. ESM and CJS without split-brain conflict). Tracked at #1551. Follows-up e1e03e6. Closes #1118.
- Loading branch information
Showing
6 changed files
with
134 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import initFixture from './fixture'; | ||
import initUrlConfig from './urlparams'; | ||
|
||
export function initBrowser (QUnit, window, document) { | ||
// Report uncaught exceptions to QUnit. | ||
// | ||
// Wrap and preserve any pre-existing window.onerror. | ||
// An existing handller can "accepts" the erorr by returning true. | ||
// | ||
// Returning true from window.onerror suppresses the browser's default error | ||
// reporting. Likewise, we will also not report it in that case. | ||
const originalWindowOnError = window.onerror; | ||
window.onerror = function (message, fileName, lineNumber, columnNumber, errorObj, ...args) { | ||
let ret = false; | ||
if (originalWindowOnError) { | ||
ret = originalWindowOnError.call( | ||
this, | ||
message, | ||
fileName, | ||
lineNumber, | ||
columnNumber, | ||
errorObj, | ||
...args | ||
); | ||
} | ||
|
||
// Treat return value as window.onerror itself does, | ||
// Only do our handling if not suppressed. | ||
if (ret !== true) { | ||
// If there is a current test that sets the internal `ignoreGlobalErrors` field | ||
// (such as during `assert.throws()`), then the error is ignored and native | ||
// error reporting is suppressed as well. This is because in browsers, an error | ||
// can sometimes end up in `window.onerror` instead of in the local try/catch. | ||
// This ignoring of errors does not apply to our general onUncaughtException | ||
// method, nor to our `unhandledRejection` handlers, as those are not meant | ||
// to receive an "expected" error during `assert.throws()`. | ||
if (QUnit.config.current && QUnit.config.current.ignoreGlobalErrors) { | ||
return true; | ||
} | ||
|
||
// According to | ||
// https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror, | ||
// most modern browsers support an errorObj argument; use that to | ||
// get a full stack trace if it's available. | ||
const error = errorObj || new Error(message); | ||
if (!error.stack && fileName && lineNumber) { | ||
error.stack = `${fileName}:${lineNumber}`; | ||
} | ||
QUnit.onUncaughtException(error); | ||
} | ||
|
||
return ret; | ||
}; | ||
|
||
window.addEventListener('unhandledrejection', function (event) { | ||
QUnit.onUncaughtException(event.reason); | ||
}); | ||
|
||
QUnit.on('runEnd', function (runEnd) { | ||
if (QUnit.config.altertitle && document.title) { | ||
// Show ✖ for good, ✔ for bad suite result in title | ||
// use escape sequences in case file gets loaded with non-utf-8 | ||
// charset | ||
document.title = [ | ||
(runEnd.status === 'failed' ? '\u2716' : '\u2714'), | ||
document.title.replace(/^[\u2714\u2716] /i, '') | ||
].join(' '); | ||
} | ||
|
||
// Scroll back to top to show results | ||
if (QUnit.config.scrolltop && window.scrollTo) { | ||
window.scrollTo(0, 0); | ||
} | ||
}); | ||
|
||
initFixture(QUnit, document); | ||
initUrlConfig(QUnit); | ||
QUnit.reporters.perf.init(QUnit); | ||
QUnit.reporters.html.init(QUnit); | ||
|
||
function autostart () { | ||
// Check as late as possible because if projecst set autostart=false, | ||
// they generally do so in their own scripts, after qunit.js. | ||
if (QUnit.config.autostart) { | ||
QUnit.start(); | ||
} | ||
} | ||
if (document.readyState === 'complete') { | ||
autostart(); | ||
} else { | ||
window.addEventListener('load', autostart, false); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const hasOwn = Object.prototype.hasOwnProperty; | ||
|
||
export default function initUrlConfig (QUnit) { | ||
// Wait until QUnit.begin() so that users can add their keys to urlConfig | ||
// any time during test loading, including during `QUnit.on('runStart')`. | ||
QUnit.begin(function () { | ||
const urlConfig = QUnit.config.urlConfig; | ||
|
||
for (let i = 0; i < urlConfig.length; i++) { | ||
// Options can be either strings or objects with nonempty "id" properties | ||
let option = QUnit.config.urlConfig[i]; | ||
if (typeof option !== 'string') { | ||
option = option.id; | ||
} | ||
|
||
// only create new property for user-defined QUnit.config.urlConfig keys | ||
// that don't conflict with a built-in QUnit.config option or are otherwise | ||
// already set. This prevents internal TypeError from bad urls where keys | ||
// could otherwise unexpectedly be set to type string or array. | ||
// | ||
// Given that HTML Reporter renders checkboxes based on QUnit.config | ||
// instead of QUnit.urlParams, this also helps make sure that checkboxes | ||
// for built-in keys are correctly shown as off if a urlParams value exists | ||
// but was invalid and discarded by config.js. | ||
if (!hasOwn.call(QUnit.config, option)) { | ||
QUnit.config[option] = QUnit.urlParams[option]; | ||
} | ||
} | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
import QUnit from './core'; | ||
import './html-runner/fixture'; | ||
import './html-runner/urlparams'; | ||
import { initBrowser } from './browser/browser-runner'; | ||
import { window, document } from './globals'; | ||
|
||
QUnit.reporters.html.init(QUnit); | ||
if (window && document) { | ||
initBrowser(QUnit, window, document); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters