Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save RossPatterson/2596952 to your computer and use it in GitHub Desktop.

Select an option

Save RossPatterson/2596952 to your computer and use it in GitHub Desktop.
Changes to add support for capturing JavaScript errors and treating them similar to alerts - the test script must retrieve them right after they occur, or an exception is thrown.
/// <summary>
/// Make sure our IsJavaScriptErrorPresent() and GetJavaScriptError() extensions can correctly intercept an error.
/// </summary>
[Test]
public void ShouldFindOneErrorInBadScript()
{
selenium.Open("http://localhost");
selenium.RunScript("window.ThereBetterNotBeAFunctionByThisName();");
// The error should be:
// window.ThereBetterNotBeAFunctionByThisName is not a function at http://localhost/ics/support/myhistory.asp line 0
AssertTrue(selenium.Processor.GetBoolean("isJavaScriptErrorPresent", new String[] { });)
string errorMessage = selenium.Processor.GetString("getJavaScriptError", new String[] { });
Asserttrue(Regex.IsMatch(errorMessage, @"^window\.ThereBetterNotBeAFunctionByThisName is not a function at https?://[^/]+/ics/support/myhistory\.asp line 0 in cypContent$"));
// Should not be any more errors.
AssertFalse(selenium.Processor.GetBoolean("isJavaScriptErrorPresent", new String[] { });)
}
/* Changes to add support for capturing JavaScript errors and treating them similar
to alerts - the test script must retrieve them right after they occur, or an exception
is thrown.
This support includes modified version of some existing parts of Selenium, lifted out of
selenium-api.js and selenium-browserbot.js.
Existing functions:
selenium-api.js:
Selenium.prototype.ensureNoUnhandledPopups()
Selenium.prototype.P5_unmodified_ensureNoUnhandledPopups() (run-time-copied from ensureNoUnhandledPopups())
selenium-browserbot.js:
BrowserBot.createForWindow()
BrowserBot.P5_unmodified_createForWindow() (run-time-copied from createForWindow())
BrowserBot.prototype.modifyWindowToRecordPopUpDialogs()
BrowserBot.prototype.resetPopups()
BrowserBot.prototype.P5_unmodified_resetPopups() (run-time-copied from resetPopups())
BrowserBot.prototype.P5_unmodified_modifyWindowToRecordPopUpDialogs() (run-time-copied from modifyWindowToRecordPopUpDialogs())
New functions:
selenium-api.js:
bool Selenium.prototype.getIgnoreJavaScriptErrors(bool)
void Selenium.prototype.getIgnoreJavaScriptErrorsLike(string)
string Selenium.prototype.getJavaScriptError() (based on getAlert())
bool Selenium.prototype.isJavaScriptErrorPresent() (based on isAlertPresent())
selenium-browserbot.js:
bool BrowserBot.prototype.hasJavaScriptErrors() (based on hasAlerts())
string BrowserBot.prototype.getNextJavaScriptError() (based on getNextAlert())
void BrowserBot.prototype.ignoreJavaScriptErrorsLike(RegExp)
New data fields:
selenium-browserbot.js:
string[] browserbot.recordedJavaScriptErrors - Errors that have been recorded, in order by occurence.
bool browserbot.isJavaScriptErrorTrapEnabled - Is trapping of JavaScript errors enabled?
RegExp[] browserbot.ignoreJavaScriptErrorRegExps - Regular expressions of JavaScript errors that should not be recorded.
*/
/* ------ Changes and additions for selenium-api.js ------ */
/* Wrap ensureNoUnhandledPopups() to check for unhandled JavaScript errors too. */
Selenium.prototype.P5_unmodified_ensureNoUnhandledPopups = Selenium.prototype.ensureNoUnhandledPopups;
Selenium.prototype.ensureNoUnhandledPopups = function() {
this.P5_unmodified_ensureNoUnhandledPopups();
if (this.browserbot && this.browserbot.isJavaScriptErrorTrapEnabled && this.browserbot.hasJavaScriptErrors && this.browserbot.hasJavaScriptErrors()) {
throw new SeleniumError('There was an unexpected JavaScript error! [' + this.browserbot.getNextJavaScriptError() + ']');
}
}; // Selenium.prototype.ensureNoUnhandledPopups =
/* Add the getJavaScriptError command: */
Selenium.prototype.getJavaScriptError = function() {
/**
* Retrieves the message of a JavaScript error, or '' if none.
*
* @return string the error message, or '' if none.
*/
if (!this.browserbot.hasJavaScriptErrors()) {
return '';
}
return this.browserbot.getNextJavaScriptError();
}; // Selenium.prototype.getJavaScriptError =
Selenium.prototype.getJavaScriptError.dontCheckAlertsAndConfirms = true;
Selenium.prototype.getIgnoreJavaScriptErrors = function(disabled) {
/**
* Enables or disables the JavaScriptError trapping support. Default is enabled.
*
* Note: Calling this "getIgnoreJavaScriptErrors()" is a BAD idea, because it
* changes the state of the trap, but doing so gets this command past Selenium's
* command processor.
*
* @param boolean disabled - true if errors should be ignored.
* @return boolean the previous state of the support.
*
*/
var previousValue = !this.browserbot.isJavaScriptErrorTrapEnabled;
if (typeof(disabled) != 'undefined') {
this.browserbot.isJavaScriptErrorTrapEnabled = !(disabled == 'true' || disabled == '1');
}
return previousValue;
}; // Selenium.prototype.getIgnoreJavaScriptErrors =
Selenium.prototype.getIgnoreJavaScriptErrors.dontCheckAlertsAndConfirms = true;
Selenium.prototype.getIgnoreJavaScriptErrorsLike = function(messagePattern) {
/**
* Suppresses all JavaScript errors matching the specified RegExp pattern.
* Errors that are not suppressed are still subject to the getIgnoreJavaScriptErrors()
* setting. Default is that no messages are suppressed.
*
* Note: Calling this "getIgnoreJavaScriptErrorsLike()" is a BAD idea, because it
* changes the state of the trap, but doing so gets this command past Selenium's
* command processor.
*
* @param string messagePattern - Regex of an error to suppress.
* @return string An empty string to keep the Selenium command processor happy.
*
*/
this.browserbot.ignoreJavaScriptErrorsLike(new RegExp(messagePattern));
return "";
}; // Selenium.prototype.getIgnoreJavaScriptErrorsLike =
Selenium.prototype.getIgnoreJavaScriptErrorsLike.dontCheckAlertsAndConfirms = true;
/* Add the isJavaScriptErrorPresent command: */
Selenium.prototype.isJavaScriptErrorPresent = function() {
/**
* Has a JavaScript error occurred?
*
* This function never throws an exception
*
* @return boolean true if there is a JavaScript error.
*/
return this.browserbot.hasJavaScriptErrors();
}; // Selenium.prototype.isJavaScriptErrorPresent =
Selenium.prototype.isJavaScriptErrorPresent.dontCheckAlertsAndConfirms = true;
/* ------ Changes and additions for selenium-browserbot.js ------ */
/* Wrap createForWindow() to initialize the collection of recorded JavaScript errors: */
BrowserBot.P5_unmodified_createForWindow = BrowserBot.createForWindow;
BrowserBot.createForWindow = function(window, proxyInjectionMode) {
var browserbot = BrowserBot.P5_unmodified_createForWindow(window, proxyInjectionMode);
browserbot.recordedJavaScriptErrors = [];
browserbot.ignoreJavaScriptErrorRegExps = [];
browserbot.isJavaScriptErrorTrapEnabled = true;
return browserbot;
}; // BrowserBot.createForWindow =
/* Add the hasJavaScriptErrors() boolean function: */
BrowserBot.prototype.hasJavaScriptErrors = function() {
return (this.recordedJavaScriptErrors.length > 0);
}; // BrowserBot.prototype.hasJavaScriptErrors =
/* Wrap resetPopups() to discard any recorded JavaScript errors: */
BrowserBot.prototype.P5_unmodified_resetPopups = BrowserBot.prototype.resetPopups;
BrowserBot.prototype.resetPopups = function() {
this.P5_unmodified_resetPopups();
this.recordedJavaScriptErrors = [];
}; // BrowserBot.prototype.resetPopups =
/* Add the ignoreJavaScriptErrorsLike(regexp) function to suppress matching errors: */
BrowserBot.prototype.ignoreJavaScriptErrorsLike = function(messageRegexp) {
this.ignoreJavaScriptErrorRegExps.push(messageRegexp);
}; // BrowserBot.prototype.ignoreJavaScriptErrorsLike =
/* Add the getNextJavaScriptError() function to return the next JavaScript error in recording order: */
BrowserBot.prototype.getNextJavaScriptError = function() {
var t = this.recordedJavaScriptErrors.shift();
if (t) {
t = t.replace(/\n/g, ' '); // because Selenese loses \n's when retrieving text from HTML table
}
this.relayBotToRC('browserbot.recordedJavaScriptErrors');
LOG.info('Returning JavaScript error: ' + t);
return t;
}; // BrowserBot.prototype.getNextJavaScriptError =
/* Wrap modifyWindowToRecordPopUpDialogs() to wrap the window's onerror() function and record the error: */
BrowserBot.prototype.P5_unmodified_modifyWindowToRecordPopUpDialogs = BrowserBot.prototype.modifyWindowToRecordPopUpDialogs;
BrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) {
var self = this;
self.P5_unmodified_modifyWindowToRecordPopUpDialogs(windowToModify, browserBot);
/* Set up to record any JavaScript errors that may occur on the AUT's page: */
var oldonerror;
if (windowToModify.onerror != null && typeof(windowToModify.onerror) != 'undefined' && (typeof(windowToModify.onerror.IS_P5_ONERROR) != 'boolean' || !windowToModify.onerror.IS_P5_ONERROR)) {
oldonerror = windowToModify.onerror;
}
windowToModify.onerror = function(errorMessage, pageUrl, lineNumber) {
if (self.isJavaScriptErrorTrapEnabled) {
var error = errorMessage + ' at ' + pageUrl + ' line ' + lineNumber;
if (windowToModify.name) {
error += (' in ' + windowToModify.name);
}
var suppress = false;
for (var i = 0; i < browserBot.ignoreJavaScriptErrorRegExps.length && !suppress; i++) {
suppress = suppress || self.ignoreJavaScriptErrorRegExps[i].test(error);
}
if (!suppress) {
LOG.info('window.onerror() recorded: ' + error);
browserBot.recordedJavaScriptErrors.push(error);
}
}
if (typeof(oldonerror) != 'undefined')
{
return oldonerror(errorMessage, pageUrl, lineNumber);
}
else
{
return false;
}
}; // windowToModify.onerror =
windowToModify.onerror.IS_P5_ONERROR = true;
}; // BrowserBot.prototype.modifyWindowToRecordPopUpDialogs =
/* Apply our BrowserBot changes to its known pseudo-subclasses. There has to be a better way to do this, but I can't find one. */
var browserBots = [MozillaBrowserBot, KonquerorBrowserBot, SafariBrowserBot, OperaBrowserBot, IEBrowserBot];
for (var i=0; i < browserBots.length; i++) {
browserBots[i].prototype.P5_unmodified_resetPopups = browserBots[i].prototype.resetPopups;
browserBots[i].prototype.resetPopups = BrowserBot.prototype.resetPopups;
browserBots[i].prototype.P5_unmodified_modifyWindowToRecordPopUpDialogs = browserBots[i].prototype.modifyWindowToRecordPopUpDialogs;
browserBots[i].prototype.modifyWindowToRecordPopUpDialogs = BrowserBot.prototype.modifyWindowToRecordPopUpDialogs;
browserBots[i].prototype.hasJavaScriptErrors = BrowserBot.prototype.hasJavaScriptErrors;
browserBots[i].prototype.getNextJavaScriptError = BrowserBot.prototype.getNextJavaScriptError;
browserBots[i].prototype.ignoreJavaScriptErrorsLike = BrowserBot.prototype.ignoreJavaScriptErrorsLike;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment