Personal blog

Just sharing stuff.

Using Selenium to Test the AngularUI Datepicker From the Todo Application

In the last post I added a date picker to my todo application which is built using Play framework in Scala and AngularJS. Just to remember, here is a screenshot of the date picker :

What would be nice is to test it with Selenium. So the general goal of the test in my application is as follow :

But what interest us here is this part :

So the point of this part of the test is to be able to select the 9th of the current month from the date picker.

First step is to open the popup date picker, pretty simple I added an ID to the button for opening the date picker. The corresponding code for the test just need to find the ID and click on the button (I’m using FluentLenium) :

browser.$("#date-picker").click()

Now the interesting part, in order to select the 9th we need to find a way to click on this day in the date picker.

The first thing to check is the html generated for the 9th of the month button.

<td id="datepicker-008-6172-9" class="text-center ng-scope" aria-disabled="false" role="gridcell" ng-repeat="dt in row track by dt.date">
   <button class="btn btn-default btn-sm" tabindex="-1" ng-disabled="dt.disabled" ng-click="select(dt.date)" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" style="width:100%;" type="button">
     <span class="ng-binding" ng-class="{'text-muted': dt.secondary, 'text-info': dt.current}">
       09
     </span>
   </button>
</td>

In this html, we need to find a unique pattern for selecting the 9th button. As you can see, the td element has an ID. So we could use it directly. Unfortunately, part of this ID is random but one part is always the same and correspond to the day of the month, so we can actually use this part. Indeed the last part of datepicker-008-6172-9 correspond to the day, here it is 9. So we can use this as the pattern for selecting the day we want!

The following snippet contains the code for selecting the td element corresponding to the 9th day of the current month.

browser.$("td", withId().contains("-9")).find("button").click()

Explanation of the snippet :

In Play framework, $ correspond to the find method in FluentLenium for searching element. So basically, the snippet mean : Find a td element with an ID containing -9. Inside this element search for a button and click on it.

Here is what the general test looks like with selenium in action :

Using AngularJS UI Datepicker With CoffeeScript

I’m currently playing around and building a simple todo application and I wanted to add a date picker for the expected end date of a todo.

Good thing AngularUI Bootstrap proposes one! Here is a screenshot

I chose to use it as a popup when clicking on a button at the right of the input element. So I will explain how to use it this way. But there is many different ways to use it demonstrated in the documentation.

The HTML

First thing first, we need to add the necessary html for displaying the date picker.

Here is the corresponding stripped html :

<div ng-controller="NewTodoCtrl as ntc">
    <div>
      <label id="label_end_time" for="end_time" class="control-label">End date</label>
        <div class="input-group">
          <input type="text" class="form-control" id="end_time" name="end_time"
            placeholder="End date" data-ng-model="ntc.todo.end_time" 
            data-datepicker-popup="" data-is-open="opened">
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="ntc.open()">
              <i class="glyphicon glyphicon-calendar"></i>
            </button>
          </span>
        </div>
    </div>
</div>

You should see something similar to this :

What is important in this snippet :

Since we are using AngularJS, we need a controller that will handle the date and the popup of the date picker. Mine is named NewTodoCtrl.

Inside the input element :

  • Adding a model which will contains the date populated by the date picker. The model is contained inside the controller. data-ng-model=ntc.todo.end_time
  • data-picker-popup which is used to handle the date picker as a popup. The default date format is used here but you can change it.
  • data-is-open="opened" The variable opened is used to notify the view from the controller for opening the popup.

The calendar button next to the input element is calling an open function contained in the controller. The controller will then modify the opened variable to true for displaying the popup.

The controller

The controller is pretty simple, we just initialize the date used as the model in the constructor and corresponding to the data-ng-model in the view. A function open is used to open the popup containing the date picker. We use the $scope to modify the opened variable from the view and $timeout to delay the execution with the default timeout of the navigator.

class NewTodoCtrl

  constructor: (@$scope, @$log, @$timeout) ->
   @$log.debug "constructing NewTodoCtrl"
   @todo = {}
   @todo.end_time = new Date()

  open: () ->
   @$log.debug "Opening the date picker"
   @$timeout (=>
     @$scope.opened = true
   )

With all of this, you should now have an input element that contains the current date selected from a popup date picker.

Current date by default in the input :

When clicking on the calendar icon, the popup date picker is displayed :

You can test the example as a JSFiddle : here

Using Selenium With Scala, Play Framework and Specs2

At work, I used Selenium when I had to build a tool for writting and running automated tests.

I’m currently playing around with the Play framework in Scala and I thought it would be nice to be able to execute tests with Selenium. I’m using Specs2 as a testing framework and I wanted to use Selenium with it.

So let’s do it!

Adding Dependencies

First, we need to add the dependencies for Selenium (the current version is 2.43.1) in the build.sbt file :

libraryDependencies ++= Seq(
  ...
  "org.seleniumhq.selenium" % "selenium-java" % "2.43.1" % "test"
)

To test everything is alright, just use sbt compile or activator compile (depending on what you are using).

Writing a simple test using Selenium

Next step : Creating a simple test for our application(Write a Scala file in the test folder). The goal of this test is actually quite simple! Just launching firefox on our local application to ensure that everything is working.

Here is the test :

import org.openqa.selenium.firefox.FirefoxDriver
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._

import play.api.test._
import play.api.test.Helpers._

@RunWith(classOf[JUnitRunner])
class IntegrationSpec extends Specification {

  "Application" should {

    "work from within a browser" in new WithBrowser(webDriver = WebDriverFactory(Helpers.FIREFOX)) {

      browser.goTo("http://localhost:" + port)
    }
  }
}

Running the test

Running the test is quite simple too, just use sbt test or activator test.

The output should be similar to this :

[info] Loading project definition from /home/.../Scala/project-name/project
[info] Set current project to Todo (in build file:/home/.../Scala/project-name/)
[info] 
[info] Application should
[info] + work from within a browser
[info] 
[info] Total for specification IntegrationSpec
[info] Finished in 7 seconds, 16 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 7 s, completed 29 août 2014 16:45:44

That’s it! You should now be able to write tests that are executing in a browser.