Monday, April 28, 2014

Arquillian Graphene 2: JavaScript Unit Testing Examples

I have been doing work with Arquillian for a while. If you need to do integration and unit testing on your JSF application. This is definitely the path to take. It makes testing so much easier to accomplish.

Recently, I have been trying to use Arquillian Graphene 2 to do JavaScript unit testing. I spent a lot of time trying to get the examples on the Graphene 2 - JavaScript Interface wiki to work. I discovered that they were slightly incorrect and the source of my grief. One of the great things about an Open Source world is that I updated the wiki with the correct information.

I have created a couple of Proof of Concept (POC) projects to demonstrate how to use Graphene to do JS testing. The first example uses Graphene in stand-alone mode. This mode allows you to test your JavaScript outside of a container, but using a browser implementation like: PhantomJS, Chrome, Firefox, or Safari.

The Apache Maven NetBeans 8.0 project can be downloaded from Bitbucket here: graphene-js-poc

You will need to execute this from the command line, or use the JS Unit Test custom goal in NetBeans.

1
mvn -Dbrowser=phantomjs clean test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.bluelotusoftware.example;
 
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.javascript.JavaScript;
import org.jboss.arquillian.junit.Arquillian;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
 
/**
 *
 * @author John Yeary
 * @version 1.0
 */
@RunWith(Arquillian.class)
public class GreetingTest {
 
    @JavaScript
    private Greeting greeting;
    @Drone
    private WebDriver driver;
 
    @Test
    public void testGreeting() {
        assertEquals("Hello John", greeting.greeting("John"));
    }
    @Test
    public void testWarning() {
        assertNull(greeting.warning("John"));
    }
}
The next project is simply a combination of the code from the Arquillian Graphene 2 wiki combined into a more complex project. This project is designed to run in a container. In my case, Glassfish is the container of choice. The slickness of this approach becomes quite apparent when you see the application server start-up, execute the tests, and shutdown gracefully.

The Apache Maven NetBeans 8.0 project can be downloaded from Bitbucket here: graphene-poc.

The project includes a JSF example along with testing JavaScript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bluelotusoftware.example;
 
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.javascript.JavaScript;
import org.jboss.arquillian.junit.Arquillian;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
 
@RunWith(Arquillian.class)
public class HelloWorldTest {
     
    // Required browser injection
    @Drone
    private WebDriver browser;
 
    @JavaScript
    private HelloWorld helloWorld;
 
    @Test
    public void testHelloWorld() {
        assertEquals("Hello World!", helloWorld.hello());
    }
}
If you need to do unit testing of your JavaScript, this may be an option to consider. Please make sure you read the wiki and understand the limitations of the approach however. You can use my code as an example to help guide you along the path.

Friday, April 18, 2014

JSF 2.2 Tip of the Day: Naughty Expression Language (EL)

Unexpected Effects

Many of you may know this already, but I was reminded the other day how this can catch even some of the most brilliant JSF developers. When you comment out a component in your xhtml page that has EL bindings, you may not be REALLY disabling it.
Expression Language (EL) is parsed and evaluated as the page is being rendered. As a result, any exposed EL syntax will be processed including functions which could have deleterious effects. For example, take a look at the following code, and guess what it will do.
1
2
3
4
<!-- #{indexBean.doSomething()} -->
<!-- #{indexBean.doSomething} -->
<!-- <h:commandButton action="#{indexBean.doSomethingElse()}" value="Submit"/> -->
<!-- <h:commandButton action="#{indexBean.doSomethingElse}" value="Submit"/> -->

So what happens?

Scary things happen....
  1. It executes
  2. Parser exception. The parser will try to find a property called doSomething
  3. It will execute, please note that there is no <h:form/>. It is not required since we are evaluating the EL.
  4. Parser exception. The parser will try to find a property called doSomethingElse

Sensei what do I do?

You have a couple of options. The first option is the easiest, and it is likely what you want anyway with your JSF pages. You can disable the comments. No need to transmit your development comments to the end users anyway. The second option is to add a - between the # and the { like this #-{indexBean.doSomethingElse()}.
The first option is handled by adding a configuration parameter to the web.xmlfile as shown below.
1
2
3
4
<context-param>
    <param-name>facelets.SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
</context-param>
Here is a more complete example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Naughty EL</title>
    </h:head>
    <h:body>
        <h1>
Naughty EL</h1>
<p>
            Expression Language (EL) is parsed and evaluated as the
        </p>
<p>
<strong>Note:</strong> You can disable the comments including the EL which may not be disabled by using the following
            configuration parameter in the <strong>web.xml</strong>.
        </p>
<pre>
            <context-param>
                <param-name>facelets.SKIP_COMMENTS</param-name>
                <param-value>true</param-value>
            </context-param>
        </pre>
<p>
If you want to see the EL and its associated issues, please look at the source code and comments</p>
<!-- This example will execute because the EL ends with () -->
        <!-- #{indexBean.doSomething()} -->
        <!-- The result is the following -->
        <p>
Did the EL execute: <h:outputText value="#{indexBean.message}"/></p>
<!-- This example will not execute, but will result in a parse error because their is no property called doSomething -->
        <!-- You would need to remove the - from between # and { -->
        <!--#-{indexBean.doSomething}-->
 
        <!-- Oh, so you thought you disabled the component didn't you? Guess what? It is also not in a h:form ...-->
        <!--<h:commandButton action="#{indexBean.doSomethingElse()}" value="Submit"/>-->
        <!-- The result will be displayed in the messages below -->
        <h:messages globalOnly="true"  style="color:red; font-size: 32px;"/>
        <!-- <h:commandButton action="#-{indexBean.doSomethingElse}" value="Submit"/> -->
    </h:body>
</html>
The result of the code is as follows:

The complete code example was developed using NetBeans 8.0 and GlassFish 4.0 on JDK 8. The code can be found here: auto-execute-el

Popular Posts