Tuesday, October 22, 2013

ExtJS Image Component with Link

Trying to create an image in ExtJS that links to another page? I have tried direct html, button with image src, ... They all have layout problems. The image component seem to work the best, but there is no direct way to put a link in it. Finally, I found a way using the autoEl configuration. It works beautifully.
 See it in action on jsfiddle: http://jsfiddle.net/hnPbm/
See the sample code for more details:

Saturday, October 12, 2013

Always Maximize Browser Window (Selenium Web Driver + JUnit + ExtJS)

Selenium WebDriver test will fail if you ask it to click a button that is out of sight. Since WebDriver is designed to simulates human interaction, this behavior is correct. But for most of us, scrolling the object into view is a trivial task that is not the subject of testing. So to reduce a lot of trivial errors like this, it's usually preferable to start browser window in maximum size.

Here is the Java code to maximize browser window:
  WebDriver driver;
  ... 
  driver.manage().window().maximize();

Examine ExtJS Grid Data (Selenium Web Driver + JUnit + ExtJS)

This post continue the same idea I used in previous posts: use Javascript to examine data, query component and use WebDriver to simulate user interaction, and JUnit to driver assertions. Below are code snippets that will get data of the currently selected row in a data grid, and do some assertion against this data:
String gridQuery = "viewport #grid1";
String js = "return Ext.ComponentQuery.query('" + gridQuery
+ "')[0].getSelectionModel().getSelection()[0].data";
@SuppressWarnings(value="unchecked")
Map<String, Object> row = (Map<String, Object>)((JavascriptExecutor) _driver).executeScript(js);
assertThat("Project name", row.get("ProjectName").toString(), equalTo("Expected Project Name"));

Remeber to Reset IE Zoom (Selenium Web Driver + JUnit + ExtJS)

If you are unlucky as me, you may be doing research of this error message right now:

org.openqa.selenium.remote.SessionNotFoundException: Unexpected error launching Internet Explorer. Browser zoom level was set to 125%. It should be set to 100% (WARNING: The server did not provide any stacktrace information)

Everything was working perfectly, and all tests passed with green color. Then all of a sudden all test cases failed with the error above. It's very a clear error message, and you don't need any research to fix the problem. Just open IE and visit the website under test, then set zoom level to 100%. Then all tests should pass again (of course, only if they were passing before).

However, I do not want to ensure zoom level before every test runs, so I found the following code snippet to ask Selenium WebDriver to ignore IE zoom level:
// ask IE to ignore zoom level, otherwise IE may have problem starting
DesiredCapabilities caps = DesiredCapabilities
.internetExplorer();
caps.setCapability("ignoreZoomSetting", true);
driver = new InternetExplorerDriver(caps);

Things were quiet for a while until I was hit by a strange error message about object not clickable. Of course, when I put it in context, you knew I should check for zoom level immediately. However, in real life, it threw me a big loop, and I spent a good hour researching how to click ExtJS component or related catches that I may not know before. Until, I accidentally saw the zoom level is not 100%. Now after I reset zoom level back to 100%, problem is gone. I imagine WebDriver has some coordinate conversion issue when IE's zoom level is 100%.

So what is the conclusion? Two bullet points for IE testing:

  • Do NOT use the code snippet above to ignore zoom level
  • Always ensure zoom level is 100%

Thursday, October 10, 2013

Capture Runtime JavaScript Errors (Selenium Web Driver + JUnit + ExtJS)

In my previous post Capture ExtJS Ajax Error (Selenium Web Driver + JUnit + ExtJS), I showed how to capture Ajax errors. In this post, I'm going to show how to use similar approach to capture general Javascript errors.

First, need to inject the following Javascript code to the page under testing:
//Client side utilities for Selenium tests of ExtJS web applications
//requires ExtJS and Underscore libraries
//SJTXE - Selenium JavaScript Testing eXtension for ExtJS
(function(root, Ext) {
var root = root || window;
var me = root;
var Ext = Ext;
//private vars
var hasJSError = false;
var onJSError = function(conn, response, options, eOpts) {
hasJSFailure = true;
};
window.onerror = onJSError;
//exposed object
var SJTXE = {
VERSION: '0.0',
hasJSError: function() {return hasJSError}
};
root.SJTXE = SJTXE;
return SJTXE;
})(this, Ext);
view raw JSError.js hosted with ❤ by GitHub
The Java code to inject the JS code above and to check runtime script error:

//make sure it's run after every page load
public static void injectSJTXE(WebDriver driver) throws IOException {
URL url;
String js;
url = Resources.getResource(ExtJSUtil.class, "SJTXE.js");
js = Resources.toString(url, Charsets.UTF_8);
((JavascriptExecutor) driver).executeScript(js);
}
//code to check if there are ExtJS Ajax error
Boolean hasJSError = (Boolean) ((JavascriptExecutor) driver).executeScript("return SJTXE.hasJSError();");
//or check it in @After for each test case
@After
public void tearDown() {
assertThat("No runtime JavaScript error",
(Boolean) ((JavascriptExecutor) driver).executeScript("return SJTXE.hasJSError();"),
equalTo(false));
}
view raw SJTXE.java hosted with ❤ by GitHub

Wednesday, October 02, 2013

sendKeys to combobox, textbox or datefield (Selenium Web Driver + JUnit + ExtJS)

In my previous post Locate ExtJS Component (Selenium Web Driver + JUnit + ExtJS), I introduced some code snippets to find an ExtJS component using ComponentQuery. However, the elements located using that approach generally do not accept user input (except mouse click seems to work for button). Turns out ExtJS render these components using a lot of HTML markups wrapping around the real input element. The inputEl is usually the HTML element that accepts user input. So to send keys to them, a slight change is needed from the code I published in the previous post. We will need to drill down 1 level to retrieve HTML id of inputEl, and get its DOM element:

//find the fully qualified component query of ExtJS component cmp
String query = cmp.componentQuery;
Component parent = cmp.parent;
while (parent != null) {
query = parent.componentQuery + " " + query;
parent = parent.parent;
}
//use component query to find id of inputEl
//the only change here is the addition of inputEl before .id
String js = "return Ext.ComponentQuery.query(\"" + query + "\")[0].inputEl.id;";
String id = (String) ((JavascriptExecutor) _driver).executeScript(js);
WebElement element = driver.findElement(By.id(id));
//Now, this web element accepts sendKeys
element.sendKeys("it works");
view raw SendKeys.java hosted with ❤ by GitHub

Tuesday, October 01, 2013

Capture ExtJS Ajax Error (Selenium Web Driver + JUnit + ExtJS)

Here is sample code to check ExtJS Ajax error. It's highly recommended to check this error during teardown(@After), because WebDriver won't automatically capture these problems.

First, need to inject the following JS code to the page under testing:
//Client side utilities for Selenium tests of ExtJS web applications
//requires ExtJS and Underscore libraries
//SJTXE - Selenium JavaScript Testing eXtension for ExtJS
(function(root, Ext) {
var root = root || window;
var me = root;
var Ext = Ext;
//private vars
var hasAjaxFailure = false;
var onAjaxError = function(conn, response, options, eOpts) {
hasAjaxFailure = true;
};
Ext.onReady(function() {
Ext.Ajax.on({
requestexception: onAjaxError
});
});
//exposed object
var SJTXE = {
VERSION: '0.0',
hasAjaxFailure: function() {return hasAjaxFailure}
};
root.SJTXE = SJTXE;
return SJTXE;
})(this, Ext);
view raw ExtJSError.js hosted with ❤ by GitHub
 Java code to inject the code and to check ExtJS Ajax error:

//make sure it's run after every page load
public static void injectSJTXE(WebDriver driver) throws IOException {
URL url;
String js;
url = Resources.getResource(ExtJSUtil.class, "SJTXE.js");
js = Resources.toString(url, Charsets.UTF_8);
((JavascriptExecutor) driver).executeScript(js);
}
//code to check if there are ExtJS Ajax error
Boolean hasAjaxFailure = (Boolean) ((JavascriptExecutor) driver).executeScript("return SJTXE.hasAjaxFailure();");
view raw SJTXE.java hosted with ❤ by GitHub