Automate E2E testing of Angular 4 apps with ProtractorJS & Jasmine

The other thing that works in tandem with any web app development is testing which happens at various levels — Unit testing, Integration testing, End to End testing and a lot more. The E2E or End to End testing can be either performed manually or automated to save a lot of time. And that’s precisely is our topic of discussion in this article. So, if you’re a software tester yearning to expand your horizons towards automation using the hottest web technologies of the era, hold on tight!

It’s not going to be a monotonous textual reading, you’ll have to move some muscles to make the most out of it.

Understanding the rudiments

Automation with Angular apps has been a breeze since the very beginning cause you might not know but Angular was built by software testers at Google. Say what!

ProtractorJS

Protractor is an official library to used for writing E2E test suites with an Angular app. It’s nothing but a wrapper over the Selenium WebDriverJS Api that translates its succinct code and methods to WebDriver JS methods. That said, you can use WebDriverJS methods too inside your e2e script.

Working of Automation Scripts using ProtractorJS

Not delving too much into the technical nitty-gritty, I’ll skim thorough it’s internal dynamics.

  1. There exists a Selenium Web Server that listens to Selenium commands in a special format called JSON Wire Protocol.
  2. The automation script written in WebDriver JS shoots these HTTP commands to the browser driver to “drive” or “dictate” the actions it needs to perform via Selenium web server.
  3. The server determines the steps needed to be performed by the web driver and execute them on the app being tested and send the status back to the automation script.

So, as you can see Protractor is nothing but a wrapper on top of WebDriverJS which in turn is nothing but a language binding of Selenium Web Driver for JavaScript.

Jasmine

Besides all this, Jasmine is something you gotta learn and believe me it’s a piece of cake.

Jasmine Framework Logo
Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests.

Here’s a snapshot from Jasmine docs itself.

And that’s it, indeed it looks “obvious”. You write the test suites and cases using the describe and it blocks respectively. You pass in a name to your test suite or case in the first argument of these blocks and a function object defining that block in the second argument. Inside the test case functions, you can use Jasmine keywords like expect something to be something.

Here’s the link to it’s lucid and well maintained documentation.

JumpStart

The first step is you need to create or obtain an Angular 2+ App. If you don’t have one, you can generate it using the Angular CLI very easily like this:

ng new my-test-project

or you can clone this existing demo github repo as.

git clone https://github.com/paramsinghvc/angular-realworld-example-app
cd angular-realworld-example-app

Open it in your favourite text editor and get started. You can run the app using npm start in the terminal and open http://localhost:4200 in the browser to see the app.

Writing the first Test Suite

All we need to be concerned about is this folder, e2e

index.spect.ts is the main entry file of our automation script.

Let’s write a basic test case to check whether the title of our app is “Conduit” or not. Here’s the code for the same.

Don’t get intimidated if this TypeScript + Jasmine syntax looks pretty new to you. If you aren’t comfortable with ES6, go ahead and use ES5.

The first two lines state we’re importing some stuff of code from other libraries or files like these special keywords by, browser, element from protractor library and HomePage class from our own file home.page.ts residing inside pages folder in the same directory. It’s just a module design pattern implementation since we don’t wanna overcrowd our index.spec.ts file.

Inside home.page.ts is just a class that exposes helper methods for writing our test cases for a certain section of the app.

If you’re coming from any OOPS language background, you’ll feel at home with TS. We’ve just created two methods that returns some operations on browser object of protractor.

And then we’re using these methods in our main index.spec.ts file by instantiating this class as

const homePage = new HomePage();

inside our main app test suite which in turn holds further sub test suites for every page of the app.

beforeAll method of Jasmine runs the function passed to it before running any of its test cases. So, we want to navigate to our home page before running any test cases on the home page.

Moving on to our main test case for determining title of our web page.

The browser.getTitle() method of protractor is asynchronous. It returns a Promise of a value being resolved in the future which is title in our case. In the then function of this returned promise, we write a Jasmine expect case to equate the title got to be “Conduit”.

Now, lets run our test suite using npm run e2e

Test Passing

The test passes successfully. Now let me just mess around, with the case as

expect(title).toEqual('Conduits');

This time it fails with an output like this

Failing test case — Jasmine Reporter

A level up

Congrats, we just ran our first basic test e2e test case. But it’s just the tip of the iceberg. There’s hell lot more things you can do using protractor + jasmine test scripts.

Now, kindly checkout to complete git branch of the project using

git checkout complete

If you now observe home.page.ts file, it has the following function

It’s using the protractor ElementFinder syntax to locate an element in the DOM by it’s tagName. As you can see, the syntax is really intuitive.

You can locate elements using several techniques like through CSS as

or even xpath

For the complete list of protractor locators, refer to docs.

The index.spec.ts has some new things too like some jasmine functions as toContain or toBeTruthy or toBeGreaterThan.

Also, if you have worked on writing automation scripts before in any framework or language, you might have found yourself waiting for the asynchronous events to complete by introducing nasty delays like

browser.sleep(4000);

Cheer up! No more need of these uncertain nasty sleeps with protractor. You can run automation tests with more confidence by using methods like browser.wait

So, basically we’re waiting for our loader element on the page to become hidden which marks the loading of our articles list successfully. In the second argument, we’re passing a max timeout to prevent the wait from running infinitely.

After this statement, we can run our case on the loaded articles in a clean and legit way.

Summary

There’s lot more to cover but the idea of this little tutorial is to help you kickstart automation scripting for Angular apps. So, now that you’ve got your hands dirty with it, go ahead, fork the repo and don’t stop until you finish the complete e2e testing of this app seeking help from those vast Protractor and Jasmine docs. For me, that’s the best way to learn. Learn by practice! Not only does automation helps you save a lot of time for regression testing but also it’s fun letting the magic happening in front of you.

If you’re wondering whether I can use protractor for testing non-angular apps, you’re not wrong. We can. So, stay tuned. Rumour has it, next post coming up would be pertaining to this. Till then, keep automating 🤖.

Happy Testing 🤓