Thursday, January 16, 2014

ExtJS Grid Cell Rendered with Mixed Image and Text

Rendering

To render mixed image and text in ExtJS grid, I found the following two approaches

  • Implement custom renderer, return a value like this 
      <img src="..."/>you text content
  • Use CSS to add background image to the cell (see Reference)
Problem: misaligned columns in the first approach
However, when I examine a grid with "locked" columns, I starting to see problem in the first implementation. Often times, the locked columns and floating columns are misaligned. Turns out image tag in the cell will cause grid to adjust row hight. However, ExtJS does not adjust fixed columns and floating columns together. So, if there is image in fixed column only, it will frequently make it taller than the floating columns, thus causing misalignment. To solve this problem, I added the following style to the image tag:

   margin-top: -4px;
   margin-bottom: -4px;

Event Handling

The image in the cell is usually an active component. In order to intercept the click event, I found two good approaches, again.
  • In JS code, hookup event handlers to the image component, and fire event from there. Refer to implementation of ActionColumn (ExtJS source grid\column\Action.js)
  • Change the selType of grid to 'cellmodel', and add select event listener




Reference

Displaying an Image Inside an Ext JS GridPanel Cell http://miamicoder.com/2009/displaying-an-image-inside-an-ext-js-gridpanel-cell-part-2/

Friday, January 10, 2014

New Years Resolution: do not update to .NET 4.5.1

Ok, just kidding. Should not be a new year's resolution. But serious, it was causing me nightmares over the holiday season. All of a sudden, several clients starting to have problem using an ActiveX control in IE (to be precise, ChartFx 6/7 ActiveX controls). After some really boring days researching, installing/uninstalling/reinstalling and testing, I finally found out .NET 4.5.1 was causing the problem.

I have no idea why it's a problem, but I know if I uninstall 4.5.1 and rollback to 4.5.0, then all the problems are gone. So, it's official, .NET 4.5.1 update is banned.

Problem with Intranet Web Site Content?

Did your Intranet web application users complain about your website not working at all? Here is one of the root cause: IE running in emulation mode of older browsers. It will mess up some JavaScript functions that relies on relative new features.

Symptoms


  • Your clients use IE
  • Only have problem when using Intranet like URLs
  • JavaScript console shows weried error messages like: 'JSON' is undefined
  • IE 11 Emulation (or IE10 document mode) is showing IE 7 or older or even quirk mode (however, if you see Edge then the solution I provide below won't help you)
  • DOM view showing your nice HTML5 doc type being commented out
IE commented out doctype

Root Cause

IE option "Display intranet sites in Compatibility View" forced it to emulate behavior of older browser for Intranet web applications, regardless what is in the web page's header.

Solution

This worked for me: change IIS HTTP header
  • In IIS admin, go to the folder or file that you want to enable IE "Edge" mode
  • Click "HTTP Response Headers"
  • Click "Add", and type Name: X-UA-Compatible, Value: IE=edge

HTTP Header that will fix the problem

Saturday, November 16, 2013

Javascript JSON Trailing Comma and IE

Seems like Google Chrome and Firefox are both pretty tolerant when it comes to trailing commas in JSON. However IE can be really pissed off by those extra characters.

Two symptoms I typically see:

  • Syntax Error: IE will simply report a syntax error like this: SCRIPT1028: Expected identifier, string or number
JSON string that can cause above error message:

var x = {
    a: 1,
    b: 2,};

  • Undefined object: when the trailing comma is in an array declaration, IE will add a undefined object at the end of the array (Firefox, and Chrome does not do this). For example, for the code below, my test results are: IE -> 4, Firefox -> 3, Google Chrome -> 3

var x = [1, 2, 3,];
alert(x.length);

       This usually will cause unexpected error in the code down below, which may loop through the array and try to access the undefined last element.

It is the second kind of problem that causes the most headache. Because in the first case, IE will pinpoint line number so that we can fix the problem immediately. In the second case, you are likely to get an obscure error message from a code that is trying to access the undefined last object.

Make Coldfusion 1000 Times Faster

Here is a well kept secret to make Coldfusion runs 1000 times faster: make your initial implementation 1000 time SLOWER.

Kidding aside, here are some performance tips:

  • Clean up debug code, especially CFDUMP. I have a production server that runs a query for 14 minutes, turns out a CFDUMP for debugging purpose is left behind. After it's removed, the query only took less than 5 seconds to finish;
  • JSON serialization is not as fast as you wished. I have a query that took 1 second to get result from SQL server, but then it took about 10 seconds to serialize the result to JSON string;
  • Similarly WDDX, SOAP could take significant amount of time to serialize large object;
  • Use AMF binary communication if possible (at least if you use Flex, or Coldfusion to Coldfusion communication, do give AMF some serious consideration). Moving from SOAP webservice call to AMF have make our response time order of magnitude faster;
  • Other usual suspects that are applicable to many other programming languages: loop, nested loop, multiply vs. divide, ...
  • Profiling: I was not able to find a good profiling tool for Coldfusion, so end up roll my own hand coded profiler. It's a little cumbersome, requires manually insert check points to collect performance statistics. Never the less, it helps in quickly identify bottlenecks;
  • Caching: turn on caching in Coldfusion is very easy. So, whenever it make sense, do turn on query caching, page caching, ... This often can be a 10 second job that improves performance by 100 times;
  • Coldfusion Admin: trusted cache, disable debugging
  • Always use fully qualified variable names to save scope lookup time;
  • Application.cfc: double check, triple check this file, because any performance issue here will affect ALL the pages of your website;
  • use cfqueryparam instead of text in cfquery;
  • Fine tune JVM parameters
  • Hardware: CPU, RAM, network, and Disk (again measure and identify bottleneck, before purchase any expensive upgrades)
  • Scale out: use load-balancer to distribute work load
  • Last but not least: make sure your SQL queries are all in good shape. Often times, Coldfusion server itself is not the bottleneck, your SQL server is;

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:

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:
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:
The Java code to inject the JS code above and to check runtime script error:

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:

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:
 Java code to inject the code and to check ExtJS Ajax error:

Monday, September 30, 2013

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

Part of the goal of unit test is to check result against expected values using various assertions. An essential data structure in ExtJS web application is store. So, no test case is complete without some assertion against the stores. For example, we might want to verify number of records, or value of certain column, ... Here are some code samples to access store data, get number of rows, or retrieve value of a column:

Saturday, September 28, 2013

Wait for AJAX Complete (Selenium Web Driver + JUnit + ExtJS)

With AJAX, Seleinum testing can have a lot of tricky timing issue. Tests can fail due to slightly delayed AJAX response. Implicit wait solved the problem to some extent, but would be nicer to have a way to wait for all AJAX calls to be finished.

Here is a solution for ExtJS AJAX requests:
Core concept is this JS code: Ext.Ajax.requests && !_.isEmpty(Ext.Ajax.requests). It works for ExtJS 4 only, might change for future or older version of ExtJS due to how AJAX calls are managed.

Thursday, September 26, 2013

Locate ExtJS Component (Selenium Web Driver + JUnit + ExtJS)

Selenium WebDriver offers many ways to find an element. You can find it by class, name, partial link text, xpath, css selector, ... However, when it comes to ExtJS component, none of them works very well, because ExtJS page elements tend to be generated dynamically, their xpath/id/... are all moving target. Trying to figure out a repeatable way to locate any of them can be very time consuming and the result is fragile.

Fortunately, as all ExtJS developers should know, Ext.ComponentQuery provides a powerful and very reliable way to find your component. So, the idea is to use Ext ComponentQuery to find the component of interest, then pass it along to WebDriver. Along this line, below is my approach to locate components:
  • PageObject owns all the top level components, and specify a ComponentQuery that can uniquely identify them;
  • All views or components of interest have their hierarchy represented in the test code, and at each level, they should have a ComponentQuery that can unique identify each of them within the container;
  • When it's time to get the element, we should traverse up from element to page, rebuild the fully qualified component query

Ok, some sample code might explain the idea better:

Wednesday, September 25, 2013

Take Screenshot on Failure (Selenium Web Driver + JUnit + ExtJS)

First a little background: this is the first of a series of lessons I learned using Selenium Web Driver to test ExtJS web application.

It's usually desirable to always take a screenshot when test failed. The concept of JUnit rules makes this an easy task. First, implement a rule as shown below:

Then in your test classes, you just need to declare this rule, then all test methods in it will automatically take screenshot on failure.
The examples here are just for illustration purpose. In real world application, you might make some improvement like:

  • Make sure the file name is legal for the OS (for example, the following characters are not allowed in Windows file name: \/:?*<>|\
  • Pictures might be further organized into folders by test cases?
  • The rule might be declared in a base class so that all test cases have the same behavior without extra boiler plate code

Wednesday, August 28, 2013

Link shared folder in SVN

Found this article, and followed it's instruction. Very straight forward.
TortoiseSVN and Subversion Cookbook, Part 4: Sharing Common Code
https://www.simple-talk.com/dotnet/.net-framework/tortoisesvn-and-subversion-cookbook-part-4-sharing-common-code/

What I did is just these steps (assuming both folder1 and folder2 want to have a subfolder: sharedlib):
  1. Open repo-browser
  2. Drag and drop shared folder into a root folder (folder name sharedlib, level same as folder 1 and folder 2)
  3. Right click on folder 1,Show Properties > New > External > New, local path: sharedlib, URL: ../sharedlib
  4. Do the same thing for folder 2
Now both folder 1 and folder 2 have sharedlib.

OpenCV in Visual Studio 2012

It's surprisingly easy, just took about 15 minutes to see some example code running.

Steps to create the first OpenCV project using Visual Studio 2012
  1. Download: opencv.org > OpenCV for Windows
  2. Run the downloaded executable and decompress to d:\opencv (to help the examples below)
  3. Open Visual Studio 2012, create new project  Visual C++ > Win32 > Win32 Console Application
  4. Add "Include Directories": Project Properties > Configuration Properties > C/C++ > General > Additional Include Directories, add: D:\opencv\build\include
  5. Change to static link (optional, but if this is not done, then the library below need to be changed slightly): Project Properties > Configuration Properties > C/C++ > Code Generation > Runtime Library, select Multi-threaded (Debug)
  6. Add "Library Directories": Project Properties > Configuration Properties > Linker > General > Additional Library Directories, add:D:\opencv\build\x86\vc11\staticlib (or  D:\opencv\build\x86\vc11\lib if you don't want static link)
  7. Add lib files: Project Properties > Configuration Properties > Linker > Input >Additional Dependencies, add the libraries listed below. (Note: 1. comctl32 is a Windows library; 2. replace "246" to version number you have; 3. files ending with "d" is debug version, for release configuration, remove it)
IlmImfd.lib
libjasperd.lib
libjpegd.lib
libpngd.lib
libtiffd.lib
opencv_calib3d246d.lib
opencv_contrib246d.lib
opencv_core246d.lib
opencv_features2d246d.lib
opencv_flann246d.lib
opencv_gpu246d.lib
opencv_haartraining_engined.lib
opencv_highgui246d.lib
opencv_imgproc246d.lib
opencv_legacy246d.lib
opencv_ml246d.lib
opencv_nonfree246d.lib
opencv_objdetect246d.lib
opencv_ocl246d.lib
opencv_photo246d.lib
opencv_stitching246d.lib
opencv_superres246d.lib
opencv_ts246d.lib
opencv_video246d.lib
opencv_videostab246d.lib
zlibd.lib
comctl32.lib


Now, for a quick sanity check, run one of the sample code from opencv.org (the example I used is "Hough Circle Transform" http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html
 
Environment:
  • Windows 7
  • Visual Studio 2012
  • OpenCV 2.4.6

Monday, August 26, 2013

Selenium WebDriver

Two lessons learned

  • IE driver need to start with "ignoreZoomSettings" true
  • JavascriptExecutor return for JS object

IE driver need to start with "ignoreZoomSettings" true

Got this error when using WebDriver for IE: "
org.openqa.selenium.remote.SessionNotFoundException". Turns out I was using IE to visit the same site I'm testing, and I adjusted zooming to 120% there. Fix for this problem is easy, simply change IE web driver creation to this:


DesiredCapabilities caps = DesiredCapabilities.internetExplorer();
caps.setCapability("ignoreZoomSetting", true);
driver = new InternetExplorerDriver(caps);

JavascriptExecutor return for JS object

What can be returned from JavaScriptExecutor.executeScript? According to the documentation, these are the types that it handles: Boolean, Long, String, List, or WebElement or null. I did a little experiment, and pleasantly surprise by the fact that array of JSON can be handled too. The return will be ArrayList of Maps. Calling obj.toString (Java side) will actually give me expected JSON string too.
Figure: Return Object as Shown in Eclipse Variables View

Thursday, August 22, 2013

Selenium WebDriver sendKey is very slow in IE

sendKey for IE is very slow. Turns out there is an easy fix. Simply download 32 bit IE driver (guess it's my bad used 64 bit driver before).

Environment:
Windows 7 Pro 64 bit
IE 10
Selenium 2