In this second part of the Protractor for Beginners tutorial, we will cover two tasks. The first task will recap what you learnt in Task 1.1 with a bit more information about the matchers isDisplayed and isPresent, and the second task will cover some new things: how to enter text, and the jasmine matchers toEqual and toContain.
Remember if you get stuck at all to use the example code here.
Task 1.2: Describe “Download button should open up a download modal”
In Task 1.1 you learnt how to use the isDisplayed matcher, so in this second task you will be using it alongside the matcher isPresent. You will be checking that the download button modal is present as well as displayed, and the differences between the two.
- Open up the angularjs.org site.
- When the download modal is open, right click on the modal and inspect the element. Hover over the different levels of divs until the full modal is highlighted (hover over
classname = “modal fade download-modal in”). - Using the class
download-modal, create a variable calledDownloadModaland within it create a page object for the download modal:var DownloadModal = function() { this.downloadModal = element(by.css(".download-modal")); } - Create a new
describesuite anditspec:describe('Download button', function() { beforeEach(function() { browser.get('https://angularjs.org/'); }); it('should open up a download modal', function() { }); }); - Within the
describe, call thehomePageanddownloadModalvariables (homePage = new HomePage();etc ) - For this test, we need to prove that the modal is non-existent before the button is pressed, and is visible after it is pressed. To do this we need to use
isPresentwhen the modal is not visible. This is because when an item is not present in the DOM or present on the page,isDisplayedwill throw an exception error. - In the
itcreate an expect to show that the download modal is not present in the DOM:expect(downloadModal.downloadModal.isPresent()).toBe(false); - Underneath this, tell protractor to click on the download button by using
.click:homePage.downloadButton.click(); - After the click, create an expect to show that download modal is now present both in the DOM and on the screen:
expect(downloadModal.downloadModal.isDisplayed()).toBe(true); - Run the test.
- Did both pass? If not, check the code is correct here:
describe('Download button', function() { var homePage = new HomePage(); var downloadModal = new DownloadModal(); beforeEach(function() { browser.get('https://angularjs.org/'); }); it('should open up a download modal', function() { expect(downloadModal.downloadModal.isPresent()).toBe(false); homePage.downloadButton.click(); expect(downloadModal.downloadModal.isDisplayed()).toBe(true); }); });
Note: Remember to double check that the opposites also fail, to ensure you aren’t getting an false positives:
expect(downloadModal.downloadModal.isPresent()).toBe(true)
before the .click and
expect(downloadModal.downloadModal.isDisplayed()).toBe(false);
after the .click.
Now we want to see how isDisplayed differs from isPesent:
-
In the
itfunction, create anexpectforisDisplayedto befalseunderneathexpect(downloadModal.downloadModal.isPresent()).toBe(false). - Run the test.
-
Observe an error appears in the console, which says "No element found using...". This happens because the download modal doesn't appear in the DOM until it is selected and opened, so the matcher
isDisplayedcannot find the element, causing it to throw an unsightly error.
What have you learnt from this task?
- How to use the
.clickmethod. - The difference between
isDisplayedandisPresentand when to use them.
Task 1.3: Describe "In The Basics tutorial, entering a name should output 'Hello [name]'"
In this task we will be looking at ‘The Basics’ section of the angularjs.org page. Scroll down to it and have a play about with it to get an idea of what it involves.
For this task we will be inputting a name in to the Name field, and checking that the output after ‘Hello’ is correct. To do this we can use the matchers toEqual and toContain. There is a small difference between toEqual and toContain. toEqual is a matcher that compares the values exactly. For example, using toEqual to compare “hell” to “hello” would fail, but comparing “hello” and “hello” would pass. toContain is a matcher that compares the values and passes if the compared value simply contains part of the expected value. For example, comparing “hell” to “hello” would pass since “hell” is a part of “hello”.
- Right click on the part of the page surrounding The Basics and select ‘Inspect element’. Navigate through the divs until you find the one that highlights the entire ‘The Basics’ section of the page.
- The code for The Basics section is
class="row example", so type in to the console$(‘.row.example’)and press enter. Observe multiple elements with the namerow exampleappear, but you only need the first one. - Right click on the Name field, and select ‘Inspect element’. The highlighted HTML code says that the Name field is
ng-model="yourName" - Right click on the ‘Hello !’ text. The highlighted HTML code says that the Hello ! text is
class=ng-binding, however there will be many manyng-bindings on the page. Double check this by typing$(‘.ng-binding’)in to the console and pressing Enter. So we will use the tagh1by usingelement.tagName(“h1”). - Using the model and class locators, create a page object for The Basics:
var TheBasics = function() { this.helloBox = element.all(by.css(".row.example")).get(0); this.nameField = this.helloBox.element(by.model("yourName")); this.helloOutput = this.helloBox.element(by.tagName("h1")); } - In your spec file, disable the other
describesuites by putting an ‘x’ in front of them:xdescribe. You can also disable individual specs by putting an ‘x’ in front of them:xit. Putting an x in front of the otherdescribesuites will stop those suites from running whilst you might only want one to run. - Create the
describesuite and theitspec for this test:describe('In "The Basics" tutorial', function() { var homePage = new HomePage(); var theBasics = new TheBasics(); beforeEach(function() { browser.get('https://angularjs.org/'); }); it('entering a name should output "Hello Name"', function() { }); }); - First thing you want to do in the
itspec is send keys to the name field. Do this using thesendKeysmethod and use your own name as a string:theBasics.nameField.click(); theBasics.nameField.sendKeys('yourname'); - Run the test. Watch the test run and observe “Hello yourname!” appears in the output box.
- Now you want to check that ‘yourname’ appears in the text using the method
.getText:expect(theBasics.helloOutput.getText()).toContain('yourname'); - Run the test and it should pass! If it doesn't, check your code against this:
- Use
toEqualto create the next test:expect(theBasics.helloOutput.getText()).toEqual('Hello yourname!'); - Run the test to see if it passes!
- It is good practice to place things like strings or numbers in their own variables. If something is hardcoded in but needs changing later on, and especially if it will be used multiple times, it takes much more effort to change them all individually. Creating variables to contain these at the top of each test (or even in page objects depending where they are needed) instead of hardcoding them can save a lot of headache later on.
- Create a variable called name, and make it equal to a string of your name:
var name = 'yourname'; theBasics.nameField.click(); theBasics.nameField.sendKeys(name); expect(theBasics.helloOutput.getText()).toContain(name); expect(theBasics.helloOutput.getText()).toEqual('Hello' + ' ' + name + '!'); - Place it all together:
describe('In "The Basics" tutorial', function() { var homePage = new HomePage(); var theBasics = new TheBasics(); beforeEach(function() { browser.get('https://angularjs.org/'); }); it('entering a name should output "Hello Name"', function() { var name = 'yourname'; theBasics.nameField.click(); theBasics.nameField.sendKeys('yourname'); expect(theBasics.helloOutput.getText()).toEqual('Hello yourname!'); expect(theBasics.helloOutput.getText()).toContain('yourname'); theBasics.nameField.click(); theBasics.nameField.sendKeys(name); expect(theBasics.helloOutput.getText()).toContain(name); expect(theBasics.helloOutput.getText()).toEqual('Hello' + ' ' + name + '!'); }); }); - Run this to ensure it passes. You can now play around with different combinations of strings and matchers to create your own tests.
theBasics.nameField.click();
theBasics.nameField.sendKeys('yourname');
expect(theBasics.helloOutput.getText()).toContain('yourname');
What have you learnt from this task?
- The different between
toEqualandtoContain - Practicing using the
sendKeysmethod - Touched on some good practices when working with hardcoded strings. Variables are your friend!
In the next tutorial we will be using getText a bit more, and we will cover how to use .count to find the number of items in a list.