Initial Setup

Following Protractor’s guide didn’t help us out a lot when we needed to start with an automation project. So here are the details missing, at least for us. Before you start using protractor make sure all the dependencies have been installed correctly. To do that use this command line:

webdriver-manager update (this command will install all needed packages needed by protractor)

To check the webdriver version use this command line:

webdriver-manager update

Now start up a server with:

webdriver-manager start

To start using WebStorm with Protractor, follow the next steps

  1. Open Run > Edit Configurations on the main menu. Click on the toolbar and select Protractor from the list. The Run/Debug Configuration: Protractor dialog box opens.
  2. Specify the Node.js interpreter to use.
  3. Specify the location of the protractor package and the path to the protractor.conf.js configuration file. BUT PLEASE PAY ATTENTION as we installed protractor globally, we have to specify the location of protractor package in global node_modules and NOT the local one.
  4. To change the test suite, change the protractor config, (located in the WebStorm edit configuration panel)

suites:{

      all: [‘RelativePathToScriptFolder’],

      sandbox: [

         ‘relativePathToSpecificScript’

      ]

  },

Then change the WebStormprotractor options to: “–suite sandbox” (it will run the sandbox script) or “–suite all”(it will run the “all” script)

To make a new git project and start working on it you can use the following commands

  1. Create a directory to contain the project.
  2. Open the terminal and navigate to the specific folder (‘cd Desktop/AmazingProject’).
  3. Initiate git using ‘git init’.
  4. Create a folder / Write new code in WebStorm.
  5. To add the new tests/new code, use the following command: ‘git add ‘pathFileToBeAdded’‘.
  6. To commit the changes use the following command: ‘git commit -m ‘my first git commit’‘ then, to push those changes use ‘git push’.
  7. To clone another existing repository, use the following command: “git clone ‘gitLinkHere'”.

To create a new branch with the contents of the master branch and switch to a newly created branch:

git checkout -b “newBranchName”

To switch branches use:

git checkout “branchName”

Browser.ignoreSynchronization=true or false

Like one of our projects, although the tool is written in angular, not all of it is written in angular, so we had to learn the hard way that the only way our scripts were working was to use ignoreSynchronization=true’;

The simple answer is that it makes protractor not wait for Angular promises, such as those from $http or $timeout to resolve,
which you might want to do if you’re testing behavior during $http or $timeout (e.g., a ‘loading’ message), or 
testing non-Angular sites or pages, such as a separate login page (to find out if the web app is built using angular, open the console and search for ng-version(angular version)).

The Conf file

The Conf file is the trigger for the protractor package execution. The execution of protractor starts from the conf file, some people also call it as a config file or protractor.config file. Conf file a javascript file, which will invoke the total framework for execution. An example of the conf file is this one below.

exports.config = {

    framework: ‘jasmine2’,

    // seleniumAddress: ‘http://localhost:4444/wd/hub’,

   directConnect:true,

   capabilities: {

'shardTestFiles': true, 
'maxInstances': 1, 

‘browserName’: ‘chrome’,

       chromeOptions: {

           args: [

              // “–headless”, //runs the script in headless mode

               “–no-sandbox”, “–disable-notifications”]

        },

       acceptInsecureCerts : true,

       loggingPrefs: {

           performance: ‘ALL’,

           browser: ‘ALL’

        }

    },

  jasmineNodeOpts: {

       defaultTimeoutInterval: 300000 //This can be used as a default timeout for protractor expected conditions.

    },

    suites:{

       suiteName: [‘AllTestSuite’],

       specificName: [

           ‘SpecificTest’

        ]

    },

    onPrepare: function() {

       browser.driver.manage().window().setSize(1920, 1080);

       jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: ‘all’}));

    }

};

Important mentions:

directConnect:true – Removes the need to start a selenium server and run the tests directly on the browser. This saves the need to start a selenium server each time test have to be runned.

‘shardTestFiles’: true – with this option, the browser starts a new instance after each test (the cache/passwords/previous options will be deleted before the each execution). This saved our project alot of headaches due to weird interactions between saved password/ saved logins and pages not refreshing when getting to the next test suite.It’s highly recommended to use this option because each new test case will run independently from the last one.

‘maxInstances’: 1, – set how many test will be runned in parallel, this option works locally and on the CI as well. Should stick to two or three because this will take a lot of computing power if more than that will be picked.

How to find elements on a page using Expected Conditions with Protractor?

Expected Conditions usually check for two things when used to find an element. As an example, visibilityOfchecks if the element is present on the DOM of a page and if it is visible.

browser.wait(EC.visibilityOf(element), 5000); //Check the config file, if defaultTimeoutIntervalis set, that value can be used instead, browser.wait(EC.visibilityOf(element), defaultTimeoutInterval);

This means that it will wait up to 5000 ms until the element is rendered.

If the element is rendered within 1000ms, it will skip the rest of 4000 waiting msTherefore, you saved 4000ms.

Check more information about Protractor API’s here.

How to find elements on a page using smart wait functions

The function below will check if the element is displayed, if it’s not displayed it will wait 100ms then check again, if after 30000ms the element is not displayed, an error will be thrown.

let smartWait = function(param){

    let Displayed = false;

    function checkForElToBeDisplayed(elem){

       elem.isDisplayed().then(function (isDisplayed) {

           if(isDisplayed){

               return Displayed = true;

           }else{

                browser.sleep(100);

            }

        })

    }

   browser.wait(function(){

       checkForElToBeDisplayed(param);

        if (Displayed){

           Displayed = false;

           return true;

        }

    }, 30000, ‘not found’);

};

Webstorm dockerfile

This is how the dockerfile from WebStorm should look like. When ‘npmtest’ is running in the terminal (you need to run this command where the test repository exists), the code below checks/updates all needed protractor dependencies and then runs all test suite (check conf.js file) (updates protractor/updates webdriver).

FROM caltha/protractor

RUN apt-get update && apt-get install -y –no-install-recommends apt-utils \

   && apt-get install -y wget

RUN apt-get update -qqy \

  && apt-get -qqy install

RUN npm install -g protractor && \

    webdriver-manager update && \

    apt-get update && \

    apt-get install -y xvfb wget openjdk-8-jre git && \

    wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \

    dpkg –unpack google-chrome-stable_current_amd64.deb && \

    apt-get install -f -y && \

    apt-get clean && \

    rm google-chrome-stable_current_amd64.deb

RUN apt install -y libappindicator3-1

RUN  curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

RUN dpkg -i google-chrome.deb

RUN apt-get install google-chrome-stable

RUN mkdir /awesomeProjectLocation

COPY  . /awesomeProjectLocation

RUN cd /awesomeProjectLocation

RUN ls

RUN npm install -g npm-install-peers

RUN protractor –version

RUN npm run update-webdriver –prefix awesomeProjectLocation

RUN npm run postinstall –prefix awesomeProjectLocation

RUN npm run pretest –prefix awesomeProjectLocation

RUN npm run instGlobal –prefix awesomeProjectLocation

RUN npm run webdrvGl –prefix awesomeProjectLocation

RUN npm run webdrvGl –prefix awesomeProjectLocation

#RUN npm test –prefix awesomeProjectLocation

WORKDIR /awesomeProjectLocation

Webstorm .gitlab-ci.yml

This is how the .gitlab-ci.yml from WebStorm should look like. This file is where you configure what CI does with your project. On any push to your repository, GitLab will look for the .gitlab-ci.yml file and start jobs on Runners according to the contents of the file, for that commit. (this file automatically runs whenever you push a commit to the server, remember to push .gitlab-ci.yml to the repository).

image: registry.gitlab.com/awesomeProjectLocation – repository location
variables:
TERM: dumb
NODE_OPTIONS: –max-old-space-size=4096 – increases node memory limit
stages:
– test
test:
tags:
– docker – (gitlab runner tag)
only:
– master – the brach where the runners are running
script:
– sh -xe startProtractor.sh

variables:
DOCKER_DRIVER: overlay2 – docker certificates
DOCKER_TLS_CERTDIR: “” – docker certificates

Gitlab CI/CD settings.

To find those settings, go to Settings ➔ CI/CD.

Extend General Pipelines and navigate to ‘Custom CI config path’ and add ‘.gitlab-ci.yml'(check above for more info about gitlab-ci.yml).

To enable a runner for your repo, go to Settings ➔ CI/CD ➔ Expand Runners. Navigate to Specific Runners and click “Enable for this project”.(remember to edit the runner to match the tags from gitlab-ci.yml(check above for more info).

To schedule pipelines for the repo, go to CI/CD ➔ Schedules ➔ New schedule. Here you can set the frequency of the pipelines and when they should run automatically.

How to find elements on a page using smart wait functions

How to troubleshoot if the script cannot find an existing element and how to fix it
This issue is commonly experienced and here are some fixes to the problem:
– check if the used element is present by inspecting the page you are trying to access.(right click on the page element and hit inspect)

– check if no other elements with the same locator is present on the page.

– check if any animations are taking place before handling the element.(remember to add “browser.ignoreSynchronization = true” this makes protractor wait for angular promises)

– check if elements are loaded before the page fully loads.(check if a loading element disappeared before handling page elements)

– there are instances where the element is displayed on the page but not preset in the DOM of the page,and, as example, visibilityOf(checks if the element is present in the DOM and visible) is used, an error will be thrown because the element is not present in the DOM of the page even if is present on page elements.(in this case, change the wait method to another method like ‘isPresent, isDisplayed etc’ or notify the issue)