ExtJS 4.2 testing with Selenium WebDriver and Grid (Java)

3,821 views
Skip to first unread message

Claude Gauthier

unread,
Sep 22, 2013, 7:35:48 PM9/22/13
to seleniu...@googlegroups.com
The purpose of this thread is to find out how we are dealing with ExtJS 4.x (4.2 in particular) when it comes to testing with Selenium WebDriver.

So, tips, tricks, code samples, something practical, tangible that can be tested and used.

Now, I've gotta a handle on a few things as you will see from the code examples below, but obviously, the more input the merrier and who is to say what I have is the best way? I'm not, so, if you have a practical and improved alternative, please pass it along! :)

Are you dealing with Grids? Charts? ExtJS Drag and Drop?  

What I'm trying to do is make this thread a place of reference.

As I keep figuring things out myself, I will keep adding to the mix.

Below I will explain for those who don't know but show an interest, why it's so hard to test ExtJS 4.2 and finally, the code samples I've been able to figure out which allowed me to manipulate ExtJS 4.2 using Selenium WebDriver with code written in Java.

WHY EXTJS 4.2 IS HARD TO TEST?

1. ExtJS 4.x uses a splitDOM engine to generate HTML code to the browser. The generated code is
optimized based on the target browser, so, the actual HTML code generated for each browser can be
different. In a nutshell, you cannot expect your HTML to be the same between IE and Firefox for
example.

This means that you can’t rely on XPath with 100% certainty.

2. Sencha’s SMVC does NOT rely on ExtJS components having unique IDs and as such, this means that
the generated code will not have any predictable unique IDs to work with. So, the best way to deal
with this is with the use of WebDriver’s JavascriptExecutor. But even that, as you will see below, can
be a tricky thing, especially when it comes to handling events. At best, you will try and use the
JavascriptExecutor to run command such as Component Queries.


CODE EXAMPLES

1) setting the value of a textfield

StringBuilder s = new StringBuilder();
s.append("with (Ext.ComponentQuery.query(\"textfield[name='username']\")[0]) {
setValue(arguments[0]); fireEvent('blur'); }");
((JavascriptExecutor) driver).executeScript(s.toString(), username);

I found out that unless I blur out of the field, the setValue() method doesn't take effect.


2) clicking an ExtJS button

In the case of buttons, you will find that events do NOT fire as expect.

First, let me show you how we are able to use a ComponentQuery to find a button and change its text.

s = new StringBuilder();
s.append("with (Ext.ComponentQuery.query(\"button[itemId='signInButton']\")[0]) { focus(); setText('new Signing Text'); }"); // this works
((JavascriptExecutor) driver).executeScript(s.toString());

Using a similar code structure, we now try to fire the click event on that captured button.

s = new StringBuilder();
s.append("with (Ext.ComponentQuery.query(\"button[itemId='signInButton']\")[0]) { focus(); fireEvent('click'); }"); // this doesn't work
((JavascriptExecutor) driver).executeScript(s.toString());

The above will not work, and causes the test to crash.


The alternative is to use findElements and/or findElement on a page to old fashion way; Inspecting the code.
But be careful. ExtJS HTML/Dom delivery isn’t identical between browsers. At first, try CSS selectors. The
reason is simple. 1) Performance. CSS Selectors are faster than XPaths. 2) IE and Chrome are very slow on
XPaths. Avoid it if you can.

The following snippet is how we can get a button to fire under ExtJS, it’s not pretty.

ArrayList<WebElement> buttons = (ArrayList) driver.findElements(By.cssSelector("a[class^='x-btn']"));
System.out.println(String.format("*********** Found %d buttons *********** ", buttons.size()));
String bText = "";
for(WebElement button : buttons) {
       bText = button.getText();
       if(bText.equals("Sign In")) { // "Sign In" would have to be part of a dictionary
             button.click();
             break;
       }
}

The reason this was used is that when you inspect the HTML code, you will find that there was nothing
directly identifying the ExtJS component.

Here’s the code which creates the button in ExtJS

{
    xtype: 'button',
    text : "Sign In",
    action : 'submit',
    itemId : 'signInButton',
    margin : '0 33 0 0',
    formBind : true,
    disabled : true
}

The generated HTML in Chrome

<a id="button-1015" unselectable="on" hidefocus="on" role="button" style="margin: 0px; right: auto; left: 1076px; top: 0px; width: 75px;" class="x-btn x-unselectable x-box-item x-toolbar-item x-btn-default-small x-item-disabled x-disabled x-btn-disabled x-btn-default-small-disabled x-noicon x-btnnoicon x-btn-default-small-noicon">
      <span unselectable="on" class="x-btn-wrap" id="button-1015-btnWrap">
            <span class="x-btn-button" id="button-1015-btnEl">
                  <span unselectable="on" class="x-btninner x-btn-inner-center" id="button-1015-btnInnerEl">Sign In</span>
                  <span style="" unselectable="on" class="x-btn-icon-el " id="button-1015-btnIconEl" role="img"></span>
            </span>
      </span>
</a>

When you compare the 2 of them, there is NOTHING that could be used to determine EXACTLY the button we want to use.
Of course, there is something that can be done, but it requires modifying your ExtJS code to add a CSS attribute which would be unique to this element as displayed below.

{
     xtype: 'button',
     text : "Sign In",
     action : 'submit',
     cls: ‘signInButtonCls’,
     itemId : 'signInButton',
     margin : '0 33 0 0',
     formBind : true,
     disabled : true
}

Guogang Hu

unread,
Oct 10, 2013, 4:36:19 PM10/10/13
to seleniu...@googlegroups.com
My take is this: use ExtJS code to find out information of components, but still use WebDriver for the interaction (sendKey, click, ...). JS code give me flexibility and powerful queries, while WebDriver should be responsible to mimic human interaction. I also use a bunch of JS code for assertion purpose.

Based on this philosophy, I build out page object, component hierarchy similar to the JS structure, and also have wrapper components for ExtJS textfield, combo, ... It's been working smoothly and consistently for me so far.

If you are interested, please check my blog for more details: http://developertips.blogspot.com/search/label/WebDriver.
  - sendKeys to combobox, textbox or datefield (Selenium Web Driver + JUnit + ExtJS)
  - Capture ExtJS Ajax Error (Selenium Web Driver + JUnit + ExtJS)
  - Examine ExtJS Store Data (Selenium Web Driver + JUnit + ExtJS)
  - Wait for AJAX Complete (Selenium Web Driver + JUnit + ExtJS)
  - Locate ExtJS Component (Selenium Web Driver + JUnit + ExtJS)
  - Take Screenshot on Failure (Selenium Web Driver + JUnit + ExtJS)

Darek G.

unread,
Oct 11, 2013, 3:00:06 PM10/11/13
to seleniu...@googlegroups.com
Have you ever tried jsoup (jsoup.org)? We found jsoup very useful for finding ids
Reply all
Reply to author
Forward
0 new messages