Using Protractor in an ionic app
Since a few days I’ve been playing around with Protractor and I am also involved on an internal project in which an Ionic app has to be created. So I thought:
Why not use Protractor in my Ionic app?
So here we are.
It’s not hard to get started and I will explain how I got it working. For the full example please refer to the ionic documentation
1. Getting started
First of all you need Node.js.
When Node.js is installed you should install Ionic and Cordova using npm (Node Package Manager):
I personally needed an app with tabs, but you can also start a blank app or an app with a side menu:
You can also choose
sidemenu instead of
2. Running the app in the browser
Once the Ionic app has been generated, you can run t it in the browser using the following command:
It’s worth noting that Ionic has live reload built in by default. So any changes will be immediately reflected in the browser.
To view the application using the iOS and Android styling applied you can use the following command:
There are many more awesome things you can do with the Ionic CLI. If you want to know more about the CLI you can find it in the Ionic documentation.
3. Structuring the application
At this moment you are set up with an Ionic starter app. The first thing I did was refactor the code from technical to functional modules.
I strongly advise to use functional modules, it’s easier to work with.
Related code should be in one folder and when testing you can use the same structure to test each module separately while coding.
You’ll find yourself navigating less trough your open tabs or a tree-view.
Additionally, it makes your code more comprehensible to other developers. The style guide from John Papa on how to structure AngularJS applications is a very good resource.
4. Sign-in page
The one we’ll be testing
After refactoring, I implemented a sign-in page, which has no access to the tabs.
The code can be seen below.
If you work in functional modules like I do, it is as easy as referring to the controller and the service from index.html, then pass
starter.sign-in as a module to your application.
Next you need to provide a state, so add the following in
and change redirect to
/signin by default:
For complete authentication you should check the authenticated state when changing pages, but that’s not in the scope of this blog
5. Preparing protractor
The sign-in part is the one I am going to test with Protractor. First thing to do, is to install Protractor on your system:
webdriver manager is a helper tool to easily get a Selenium server running.
Run the following commands in order to start it:
To keep your code clean, you could put tests in a dedicated folder, but many argue against it.
Since I work in functional modules, tests of these modules should live in the module itself.
Next I created a Protractor configuration file in the root of my project called
Don’t forget to set the correct URL to your running app. If not, you’ll see many errors, except that you might be referring to a wrong URL
6. Preparing the tests
As you can see, there is already a spec file defined in the protractor config file, so let’s create it:
In the newly created file, you can start writing your tests. If everything went well, you can simply add another test and it should validate to true. It only tests if the first page you see, is the login page:
Basically, we define a
describe function which will describe the whole scope of our specs.
Every ‘it’ function is called a spec.
We only created one for now.
As you can see this is a very readable way of testing.
We expect the browsers title to be equal to ‘Sign in’.
expect statement evaluates to
true, the spec has passed without failures, otherwise it will have a failure.
Feel free to change
Sign into something else to fail the test.
To run the tests, we can execute the following command in the folder of our
Running this command will read the config file and run all the spec-files defined. You will get some output in the command line. At the end you’ll get a summary like 1 specs, 0 failures Finished in x.xxx seconds.
This is a simple test but it doesn’t show the full potential of Protractor at all. Lets add a new spec as part of the describe.
So here we test the availability of the sign-in button when the fields are empty. Next is to test if the button becomes available if the fields are filled in with valid data. So lets add another test:
All these tests should pass correctly in protractor.
7. Page Object Pattern
You might have noticed that your tests run synchronous after each other. In this scenario this might be useful, but sometimes you need to start with a ‘clean page’ which would mean you need to duplicate a lot of code (for finding the button and text-fields).
When you are working in an agile team, it is quite common that requirements or user stories change. This can implicate you’ll have to change a lot of duplicated code. How can we work around that.
The solution is called the page object pattern.
Lets dive into
This file should also be put into the module folder:
In the constructor we make sure our browser opens the signin page by passing the correct URL.
Then we use the
prototype method to link our HTML elements with the object.
Finally, it is wise to create helper methods for basic functionality, such as filling in a username, in case you ever would want to change that behaviour.
Then you only need to change that line and all your tests will still pass.
Using logical method names keeps your tests readable which is what you’ll want when you look back in a few months.
We can now change our
sign-in.spec.js to this:
We created a page variable and before each
it we assigned a new SignInPage object to the page variable.
This way, your page gets loaded again before running every spec.
This means it always returns in the same state.
Now you can create your specs as user stories.
Protractor is an awesome way to test your app’s functionality. Using a descriptive syntax you can emulate almost every user action and run trough the whole app in no time, again and again. Using Protractor, you won’t have to spend a lot of time testing your application manually, and you can focus on feature development without having to worry about accidentally breaking some functionality. Protractor will ensure that your user gets a working app without frustrations!