Sunday, July 31, 2011

NoSuchElementException after click() in Selenium 2

Sometimes in Selenium 2 after clicking on some element, it does not execute actual click (but does not throws error that element is not found), cann't find element from next page and therefore throws this exception:

Unable to locate element: {"method":"class name","selector":"alert"} For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48' System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24' Driver info: driver.version: RemoteWebDriver

org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"class name","selector":"alert"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: RemoteWebDriver
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:131)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:105)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:405)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:193)
    at org.openqa.selenium.remote.RemoteWebDriver.findElementByClassName(RemoteWebDriver.java:250)
    at org.openqa.selenium.By$ByClassName.findElement(By.java:349)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:185)
    at org.openqa.selenium.WebDriver$findElement.call(Unknown Source)
...
Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException: Unable to locate element: {"method":"class name","selector":"alert"}
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: unknown

First, you should check that there is no element with same selector and it does not tries to click some div. Second, I found that sometimes if there is floating div, especial over your links or buttons, it cann't properly click it. In latter case, best solution for form buttons is to use submit, instead of click, like:
driver.findElement(By.id("update")).submit();
Another thing that helps - especially with links, is to remove overflowing div (closing it - depends on your application logic) and waiting for second, like:
Thread.sleep(1000);

Tuesday, July 26, 2011

How to ignore failed database migrations

When using Grails database migration plugin, failing migrations is sign of some problem - usually some syntax error. But in some cases it is not needed and it is ok to ignore them. For example, I faced this problem while testing application which created db in memory from Hibernate entities. Some particular migrations, like ones dealing with existing records or legacy columns, were failing with no meaning.
Fortunately, there is easy way to ignore some migrations. Just add failOnError:'false' to change set definition and it will report exception in logs, but will continue with loading. There is example:

  changeSet(author: "user", id: "96", failOnError:'false') {
    update(tableName: "table") {
      column(name: "column", valueBoolean: false)
      where ('column is null')
    }
  }


This is good that it is specified per change set, as only these dealing with particular columns will be able to fail, it will be still strict with others. Only way it would be better, if there would be global property, so it would be still strict in production, but more forgiving in test environment.

Unable to locate element in Selenium 2

There is new version of Selenium, which is very good and easy to use, unfortunately there is too little documentation yet. After I started to use it, one of the first issues I found is this:

org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"link text","selector":"Home"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: RemoteWebDriver
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:131)
        at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:105)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:405)
        at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:193)
        at org.openqa.selenium.remote.RemoteWebDriver.findElementByLinkText(RemoteWebDriver.java:218)
        at org.openqa.selenium.By$ByLinkText.findElement(By.java:223)
        at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:185)
        at org.openqa.selenium.WebDriver$findElement.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
        at selenium.run(selenium.groovy:14)
        at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:266)
        at groovy.lang.GroovyShell.run(GroovyShell.java:229)
        at groovy.lang.GroovyShell.run(GroovyShell.java:159)
        at groovy.ui.GroovyMain.processOnce(GroovyMain.java:514)
        at groovy.ui.GroovyMain.run(GroovyMain.java:329)
        at groovy.ui.GroovyMain.process(GroovyMain.java:315)
        at groovy.ui.GroovyMain.processArgs(GroovyMain.java:112)
        at groovy.ui.GroovyMain.main(GroovyMain.java:93)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:108)
        at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:130)
Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException: Unable to locate element: {"method":"link text","selector":"Home"}
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: unknown

even when element is present on the page. After some googling I found easy solution to this issue:

    driver = new FirefoxDriver();
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 

This is default period which Selenium will try to wait for element to appear on the page, before throwing error, and this works perfectly for me.


Saturday, July 23, 2011

MissingMethodException when running test with baseUrl in Grails

Running functional test with baseUrl option can end with exception:

Error executing script TestApp: groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean)
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean) values: [grails.testing.functio
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
        at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:391)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
        at gant.Gant.withBuildListeners(Gant.groovy:427)
        at gant.Gant.this$2$withBuildListeners(Gant.groovy)
        at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
        at gant.Gant.dispatch(Gant.groovy:415)
        at gant.Gant.this$2$dispatch(Gant.groovy)
        at gant.Gant.invokeMethod(Gant.groovy)
        at gant.Gant.executeTargets(Gant.groovy:590)
        at gant.Gant.executeTargets(Gant.groovy:589)
Caused by: groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean) values: [grails.test
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
        at _GrailsTest_groovy$_run_closure11.doCall(_GrailsTest_groovy:366)
        at _GrailsTest_groovy$_run_closure11.doCall(_GrailsTest_groovy)
        at _GrailsTest_groovy$_run_closure1_closure21.doCall(_GrailsTest_groovy:184)
        at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:174)
        at TestApp$_run_closure1.doCall(TestApp.groovy:82)
        at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
        ... 10 more

This can be easily worked around by running tests in interactive mode. Just run:

grails interactive

and you can execute your tests from there like:

test test-app functional: MyTests -baseUrl="http://..."

Apart from that it works, this gives also additional benefits like: you can debug with single attachment from IDE (remember to use grails-debug); also you can run grails application before executing tests which allows to use in-memory db with functional testing.

Monday, July 18, 2011

BLOB and TEXT type for fields in GORM

If you need long type for your fields with GORM automatic table creation, you just need to specify appropriate constraint for that field, like:
description(nullable:true, maxSize:1000000)

Sunday, July 17, 2011

c3p0 Connection reset error

By default c3p0 does not pings or destroys opened connections, so it will not know if database closes old connection until someone will try to use it. It leads to bad errors like:

Caused by: java.sql.SQLException: I/O Error: Connection reset
        at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1053)
        at net.sourceforge.jtds.jdbc.TdsCore.submitSQL(TdsCore.java:899)
        at net.sourceforge.jtds.jdbc.ConnectionJDBC2.setAutoCommit(ConnectionJDBC2.java:2259)
        at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:881)
        at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:91)


Fortunately, this can be easily fixed as c3p0 has all necessary facilities for pinging and maintaining connections. There are several options, you can read about them in c3p0 docs, I found easiest for me asynchronously pinging waiting connections every few minutes with trivial select. For example, this will specify ping connection every 3 minute in MS SQL:

         <Set name="idleConnectionTestPeriod">180</Set>
         <Set name="preferredTestQuery">select 1</Set>


Saturday, July 16, 2011

Spring security in grails - roles and permissions

There is nice plugin for using Spring security in Grails - it integrates nicely in application, can be heavily customized and is easy to use. I didn't had extensive experience with Spring security before, but all security frameworks that I used, have something that represents roles and permissions. Role is group of permissions, and permissions are either defined only for groups or can be assigned to users explicitly. From first glance at Spring security there is only concept for roles (or as they called in plugin - Authorities). It confused me very much and created impression of very basic framework.

It took some time to figure out, that on the contrary - Spring security is very powerful and flexible also in this sense. Basically, all it cares is what authorities you return in your users getAuthorities() method. So you can generate whatever hierarchy of permissions you want, possibly adjust it by the time or the day, or simply generate it on the fly.

Friday, July 15, 2011

Rich text component validation

Rich Text Components return HTML code, and if you are going to show it on your pages there is problem that some bad person can submit malicious HTML to your server and if you will display it "as is", this code can do something bad. So you have to check somehow that code that is submitted is generate by your component, or at least is safe. Latter is called HTML sanitization.
Simple pattern matching is too trivial, as malicious code can be hidden behind some strange unicode symbols or so (you can check how tricky it is at http://ha.ckers.org/xss.html). Basically, it usually requires parsing HTML and detecting, what can be used and what can't. Fortunately, there is already nice HTML parser built into JDK. It is intended to be used in Swing, but is abstract enough to be used for validation too. What you need to do is to extend javax.swing.text.html.parser.Parser, like:

import javax.swing.text.html.parser.*
import static javax.swing.text.html.HTML.Tag.*
import static javax.swing.text.html.HTML.Attribute.*

class RteParser extends Parser {
  boolean hasErrors = false
    
  public RteParser() {
    super(DTD.getDTD('html'));
  }
  
  void validateTag(tag) {
    ...
  }
  
  void handleStartTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }
  
  void handleEndTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }
  
  void handleEmptyTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }

  public static boolean validate(String value) {
    RteParser parser = new RteParser()
    StringReader reader = new StringReader("<html>${value}</html>")
    parser.parse(reader)
    return parser.isValid()
  }
  
  public boolean isValid() {
    return !hasErrors
  }

}



All validation can be done by calling static validate method.
All magic is done in validateTag. This method is specific, this is place where you check all tags and attributes against some black list or validation patterns.

Wednesday, July 6, 2011

Whole object validation with Grails

There is nice field validation framework in Grails (based on Spring) with a lot of documentation.
However recently I needed to implement whole object validation (I have some rules across different fields). It is easily supported by Grails, but is not that well documented. All you need to do is to is to implement method beforeValidate in your domain object, like:

def beforeValidate() {
  if (somethingbad()) {
    errors.addError("fieldname", "something bad happened")
  }
}


All errors that you have you should put into errors object, which is instance of
org.springframework.validation.BeanPropertyBindingResult and you can add errors as org.springframework.validation.ObjectError instances.

Monday, July 4, 2011

Handling HTML changes via DOMSubtreeModified

Recently, I needed to handle changes in DOJO rich text editor. It supports all traditional events, but my problem was that I needed to handle also copy/pastes and especially mouse copy/pastes (right button context menu), as I have found, it does not counts as mouse events. After some investigation I have found nice, but for some reason not so popular event DOMSubtreeModified.
So I am able to handle all changes by subscribing to changes like:
rte.addEventListener("DOMSubtreeModified", function(){
   ...
}

One issue with this approach is that it is not supported by all browsers and is depricated by W3, but I need this feature for controlled environment.