package net.jsourcerer.webdriver.jserrorcollector; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxProfile; /** * Holds information about a JavaScript error that has occurred in the browser. * This can be currently only used with the {@link FirefoxDriver} (see * {@link #addExtension(FirefoxProfile)}. * * @author Marc Guillemot * @version $Revision: $ */ public class JavaScriptError { private final String errorMessage; private final String sourceName; private final int lineNumber; JavaScriptError(final Map<String, ? extends Object> map) { errorMessage = (String) map.get("errorMessage"); sourceName = (String) map.get("sourceName"); lineNumber = ((Number) map.get("lineNumber")).intValue(); } JavaScriptError(final String errorMessage, final String sourceName, final int lineNumber) { this.errorMessage = errorMessage; this.sourceName = sourceName; this.lineNumber = lineNumber; } public String getErrorMessage() { return errorMessage; } public int getLineNumber() { return lineNumber; } public String getSourceName() { return sourceName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode()); result = prime * result + lineNumber; result = prime * result + ((sourceName == null) ? 0 : sourceName.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; final JavaScriptError other = (JavaScriptError) obj; if (errorMessage == null) { if (other.errorMessage != null) return false; } else if (!errorMessage.equals(other.errorMessage)) return false; if (lineNumber != other.lineNumber) return false; if (sourceName == null) { if (other.sourceName != null) return false; } else if (!sourceName.equals(other.sourceName)) return false; return true; } @Override public String toString() { return errorMessage + " [" + sourceName + ":" + lineNumber + "]"; } /** * Gets the collected JavaScript errors that have occurred since last call * to this method. * * @param driver * the driver providing the possibility to retrieved JavaScript * errors (see {@link #addExtension(FirefoxProfile)}. * @return the errors or an empty list if the driver doesn't provide access * to the JavaScript errors */ @SuppressWarnings("unchecked") public static List<JavaScriptError> readErrors(final WebDriver driver) { final List<Object> errors = (List<Object>) ((JavascriptExecutor) driver) .executeScript("return window.JSErrorCollector_errors.pump()"); final List<JavaScriptError> response = new ArrayList<JavaScriptError>(); for (final Object rawError : errors) { response.add(new JavaScriptError( (Map<String, ? extends Object>) rawError)); } return response; } /** * Adds the Firefox extension collecting JS errors to the profile what * allows later use of {@link #readErrors(WebDriver)}. * <p> * Example:<br> * <code><pre> * final FirefoxProfile profile = new FirefoxProfile(); * JavaScriptError.addExtension(profile); * final WebDriver driver = new FirefoxDriver(profile); * </pre></code> * * @param ffProfile * the Firefox profile to which the extension should be added. * @throws IOException * in case of problem */ public static void addExtension(final FirefoxProfile ffProfile) throws IOException { ffProfile.addExtension(JavaScriptError.class, "JSErrorCollector.xpi"); } }