Jasmine is a famous unit testing framework where you can organize your testing code by defining specs for each individual part of test. When using Protractor for end to end testing, you can define those Jasmine specs in the Protractor config file inside an array, and have Protractor run them one after another.

Let’s say we are testing a hypothetical web app which allows users to register by email, login, change their account settings, and logout. We have created four specs using Jasmine and Protractor for each operation with names signup, login, changeSettings, and logout respectively. Then we create our Protractor config file and add those four specs to form our test:

Then we run the test and everything looks okay. But wait! What if our app is not changing the user’s email correctly and has a bug that can’t be detected on the spot? How do we take such a bug into account? We should run the login spec again to make sure that user can login with his new email after the settings has changed. So we change the Protractor config file and add another instance of the login spec to the array:

And our test is ready to run again and catch the settings bug (if any)… Wait! The test hasn’t changed at all! It’s like we have never added the second login spec!

Unfortunately this is one of Jasmine’s shortcomings. Jasmine allows each spec to run only once per test. With that being said, when we run the test again, the second login never occurs because its spec file has already been executed once.

So what would be the right approach to free ourselves from this Jasmine constraint? Let’s take a look at what a Jasmine spec looks like from the inside:

That’s the common structure of a Jasmine spec, and all of our specs follow that structure. The trick here is to use Node.js’ module.exports functionality (which allows our code to get used as a module by calling require on it). We will export all of our specs as a node module, and then have another ‘master’ spec (more like a pseudo-suite) require all of them in any order and as many times as we want. Then we’ll have Protractor run that master spec without any limitations from Jasmine (since all Jasmine knows at that point is that we’re running one spec only, thus the workaround is complete!).

Let’s break this down…

Step 1: Turn Specs Into Modules


As mentioned above, we’ll move each spec code inside module.exports. This is what the structure of all the specs should look like:

We can now require our specs anywhere we want (note that at this point specs can’t be used directly by Jasmine/Protractor).

Step 2: Create Master Spec


We’ll create a master spec (master.js), and then require our specs to form the flow of the test. The desired flow is signup, login, changeSettings, logout, login:

Everything is ready for the final step, all we have to do now is to trick Jasmine into thinking this is our one and only spec.

Step 3: Trick Jasmine!


Let’s update our Protractor config file:

Done! Now if we run our test, it would go with our desired flow and will run the login spec one more time at the end to check for the hypothetical bug (user’s email won’t change properly through settings, thus user can’t log back into the app using his new email).

The same trick can easily be applied with ‘Suites’ as well, where you create your suite file/master spec, require all the specs needed, and add the suite file in the Protractor config under suites property.

I hope you can make a great use out of this simple trick and save yourself from lots of frustration and headache, I know I did!