When I started writing automated tests in Protractor, I had never programmed anything before (unless you count learning enough html/css on codecademy to create an incredibly basic, 90’s style webpage). Some of the problems I encountered whilst learning Protractor were very hard to find on Google, which did make my learning a lot slower than I would have liked. Luckily I work with amazing people who are more than happy to share their knowledge which has saved me countless times, but unfortunately there are many people out there who do not have access to such resources. So, I have decided to create a tutorial which documents as many issues as possible that I encountered whilst learning.

This tutorial will be broken down into bite sized chunks, with each new blog post as a new task, and it is aimed at people with little to no experience of programming. You will be writing the tests for the AngularJs site itself, since this is a good site for practising writing Protractor tests for as it is written in AngularJs; the JavaScript framework that Protractor runs tests against.

Note: if you get stuck at any point, the entire code can be found in https://github.com/hannimator/angularjs.org_protractor for use as reference. Snippets of the code will be shown as examples throughout.

Introduction:

To begin with, follow this tutorial https://github.com/angular/protractor/blob/master/docs/tutorial.md. It will run through how to setup Protractor and Jasmine, and the basics of running some simple tests. Another good read, but not necessary for this tutorial is https://github.com/angular/protractor/blob/master/docs/toc.md, which has some more in depth information about Protractor and Jasmine. Once you have completed the above tutorials, follow the steps below.

Page Objects, Developer Tools and the DOM

Page objects model the UI objects that your test interacts with inside your tests code. Using page objects keeps the tests easier to maintain (since if anything changes, you only have to change the page objects rather than change every single test). To find these UI objects, open up the browser developer tools by pressing f12 and select the 'elements' tab, or find the element (e.g. a button), right click and select 'Inspect element' from the dropdown list. For this example, use the AngularJs site. Right click on the 'View on Github' button and select 'Inspect element'. Observe the line

   <a class="btn btn-large" href="https://github.com/angular/angular.js">
      <i class="icon-github-sign"></i>
         "View on GitHub"
   </a>
Is highlighted. For this element (or page object) you can see the classname is “btn btn-large”, so when you write the page object, write it like this:
       
    var pageObjectName = element(by.css(“.btn.btn-large”));
       
The reason it is written as ".btn.btn-large" rather than "btn btn-large" is down to locators, which are what tell Protractor where to find certain elements. A CSS selector would look like this: ".someCSS", whereas an ID selector would look like this: "#someID". Some more information on this can be found in the Protractor documentation

If you want to learn a little bit more about the DOM which is mentioned throughout this tutorial, I have found https://css-tricks.com/dom/ to be a very useful and concise explanation.

Disabling Suites and Specs

To disable and enable suites and specs, simply place an x in front of the describe or the it (depending which level you want to disable the tests at, placing an x in front of the describe will disable all tests within that describe) so that it looks like this: xdescribe or xit.

Getting Started: Home Page

Open up https://angularjs.org/. Create a new folder where you want to keep your project. Open up your preferred text editor (I personally use Brackets), and open up the folder that you have just created. Create a new .js file called 'HomePageSpec.js' and create a config file called 'protractorConf.js'. Paste in this code in to the 'protractorConf.js' file:

       
   exports.config = {
      seleniumAddress: 'http://localhost:4444/wd/hub',
      specs: ['HomePageObjectSpec.js'],
      onPrepare: function () {	
         browser.driver.manage().window().setSize(1680, 1050);
      },
   }
       

Task 1.1: Describe “angularjs.org should have three Center Stage buttons”

What will you learn from this task?

  • How to set up a describe suite and it spec.
  • How to create page objects.
  • How to check that something is displayed on the screen or present in the DOM using isDisplayed

In this task you will test that elements are present and visible on the page using the three center stage buttons on the home page of AngularJs.org and the Jasmine matcher .isDisplayed (read more about Jasmine matchers here. isDisplayed checks to see if the element is actually present on the page: if the element is not in the DOM whilst using isDisplayed, it will throw an exception error. See how to use isDisplayed below.

  1. Open up angularjs.org
  2. Right click on the “View on GitHub” button, and select ‘Inspect element’ to bring up the html in the developer console.
  3. Find the code that relates to the “View on GitHub” button (if you hover over
       
                <a class="btn btn-large" href="https://github.com/angular/angular.js">
            
    you will be able to see the button highlight).
  4. If you navigate up through the divs, you will be able to find the html code that contains all three elements. The class for this is center stage-buttons.
  5. In your text editor, open up your “HomePageSpec.js” file, and create a variable called HomePage like this:
           
       var HomePage = function() {
     
       };
           
    This HomePage variable contains page objects, which are the elements on the page. Different page objects will be used for different sections that are tested on.
  6. Create page objects for the center stage buttons with the HomePage variable, like so:
           
       var HomePage = function() { 
          this.centerStageButtons = element(by.css(".center.stage-buttons"));
    
          this.viewOnGitHubButton = this.centerStageButtons.all(by.css(".btn.btn-large")).get(0);
          this.downloadButton = this.centerStageButtons.element(by.css(".btn-primary"));
          this.designDocsButton = this.centerStageButtons.element(by.css(".btn-warning"));
       };
           
    You can see that there has been a page object created for centerStageButtons. It is good practice to write the elements as they match the code in DOM as quite often there will be multiple elements with the same name. Chaining the page objects (as above) creates more readable code as it (most of the time) eliminates the need for using .get(index). I say most of the time, since sometimes having to use .get(index) is inevitable: so if you enter in to the browser console $(".btn.btn-large") you will be able to see multiple results are returned, which is why we use .get(0) for the viewOnGitHubButton example above.
  7. Underneath the HomePage variable, create the test suite and spec like this:
    
       describe('angularjs.org', function() {
    
          beforeEach(function() {
             browser.get('https://angularjs.org/');
          });
      
          it('should have a three buttons', function() {
      
          });
       });
           
  8. In the describe, create a new HomePage object and in the it spec write the expected result of the test as below:
    
       describe('angularjs.org', function() {
          var homePage = new HomePage();
    
          beforeEach(function() {
             browser.get('https://angularjs.org/');
          });
      
          it('should have a three buttons', function() {
             expect(homePage.viewOnGitHubButton.isDisplayed()).toBe(true);
          });
       });
           
  9. Run the test by opening up the command line, navigating to the folder where the config file is located. Type in protractor protractorConf.js and press Enter for the code to start running (make sure you have started the selenium webdriver by typing in webdriver-manager start and pressing enter in the command line).
  10. Did it pass? Yes? Great! No? Double check you have the code written correctly by looking at the code inside the Spec folder here: https://github.com/hannimator/angularjs.org_protractor .
  11. Now that this test has passed, it is always best to check that it fails if set to false, so underneath the first expect, create another one set to false like this:
           
       expect(homePage.viewOnGitHubButton.isDisplayed()).toBe(false);
           
  12. Run the test. Observe the expect set to false fails. This ensures that it isn’t a false positive, and is always a good practice to ensure that you haven't missed anything in your code.
In the next tutorial we will use what we learnt in this tutorial and start to learn how to interact with elements on the webpage, as well as the difference between using the matchers isPresent and isDisplayed.