Initial Setup

In our case, following the Protractor’s guide didn’t help us out too much when it came to starting an automation project. 

So, we thought we’d help other people by filling in the gaps we noticed.

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

Start using WebStorm with Protractor by following these 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. 

Pay attention here; as we installed protractor globally, we must specify the location of the 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)

Use these commands to make a new git project: 

  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 this command: ‘git add ‘pathFileToBeAdded”.
  6. To commit the changes use this command: ‘git commit -m ‘my first git commit” then, to push those changes, use ‘git push’.
  7. To clone another existing repository, use this 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

Note: Although the tool is written in angular, not all of it is written in angular.

We had to learn the hard way in one of our projects. 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

You’re testing non-Angular sites or pages, such as a separate login page.

*To determine if the web app was 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 a config file or protractor.config file. Conf file a javascript file, which will invoke the total framework for execution. Here’s an example:

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. It saves the need to start a selenium server each time tests have to be run.

‘shardTestFiles’: true – with this option, the browser starts a new instance after each test (the cache/passwords/previous options will be deleted before each execution). 

This spared us a lot of headaches due to weird interactions between saved passwords/ saved logins and pages not refreshing when getting to the next test suite.

We highly recommended using this option because each new test case will run independently from the last one.

‘maxInstances’: 1, – set how many tests run in parallel. This option works locally and on the CI as well. However, you should stick to two or three because it 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. For example, visibilityOfchecks if the element is present on the DOM of a page and if it’s 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 msJust like that, 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, it will wait 100ms, then check again. If after 30000ms the element is still 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, so 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 is a common issue, so there 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 are 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.

For example, when 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 it’s present on page elements.

In this case, change the wait method to another method like ‘isPresent, isDisplayed etc’ or notify the issue.

You can always get in touch here if you have any questions:

https://calendly.com/betterqa