Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Let's follow best practices and move the code that interacts with our page to a page object class.
In this video, we'll be using this version of the RSVP site.
- It's best practice to use "page objects" with WebDriver. See this video if you're not familiar with them.
- Make
pages
directory.- Make
pages/rsvp.js
file.
- Make
const {Browser, By, Key, until} = require("selenium-webdriver");
const url = "https://treehouse-projects.github.io/selenium-webdriver-intermediate/waits/app/index.html";
// Define a class to represent the page.
// Instances of this class will be responsible for controlling WebDriver to do operations on the page.
class RsvpPage {
// The class constructor sets up new instances of the class.
// We're going to have the test pass in a browser driver object when creating a page object.
// The page object will call methods on the driver object to control the page.
constructor(driver) {
// We'll set the "driver" property of the new object to equal the driver that's passed in.
this.driver = driver;
// The locators property will be an object containing locators for the different page
// elements we need to find.
this.locators = {
// Our first test uses this locator to find the list that we'll populate with invitees.
// We'll move the locator from the test to here.
invitedList: By.id('invitedList'),
// Our second tests uses this locator to find the form to register invitees.
// We'll move that here, too.
registrationForm: By.id('registrar'),
}
}
// This method will load the page. It will use whatever driver object we pass into the constructor.
open() {
this.driver.get(url);
}
}
// We need to set the values that will be returned when this module is required from another module.
// We'll set it up to return the RsvpPage class.
module.exports = RsvpPage;
- Then we need to update our test to load our new module and use the class.
const {Browser, By, Key, until} = require("selenium-webdriver");
const {suite} = require("selenium-webdriver/testing");
const assert = require('assert');
// Load the RsvpPage class.
const RsvpPage = require('../pages/rsvp.js')
suite(function(env) {
describe('RSVP site', async function() {
let driver;
// Define a variable to hold the page object here so that it stays in scope
// for all our tests as well.
let page;
before(async function() {
driver = await env.builder().build();
// Create a new page object that will use our driver object.
// Store it in the page variable.
page = new RsvpPage(driver);
// Instead of calling driver.get() ourselves, we'll let the page object
// load the page for us.
await page.open();
});
it('has invitee list', async function() {
// Use the locator from the page object instead.
let elements = await driver.findElements(page.locators.invitedList);
assert(elements.length > 0);
});
it('has registration form', async function() {
// Use the locator from the page object instead.
let elements = await driver.findElements(page.locators.registrationForm);
assert(elements.length > 0);
});
after(async function() {
driver.quit();
});
});
});
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
We've made a lot of improvements
to our test code, but
0:00
there's one more change we need to make
to bring it in line with best practices.
0:02
In Selenium, it's generally best to wrap
up interactions with the actual page in
0:06
a page object class.
0:11
If you're not familiar with Selenium
page object, see the teacher's notes.
0:12
Let's create a new directory
that'll hold our page object code.
0:17
So within our project directory,
0:20
I'm gonna create a new subdirectory
to hold all our page object code.
0:22
I'll name it Pages,
within the Pages subdirectory,
0:26
I'll create a new file to
hold our RSVP page object.
0:30
And I'll name it rsvp.js.
0:36
First up we're going to need to import
some of the code from Selenium web driver
0:40
into this file as well.
0:43
So I'm gonna copy this over
from the actual test code.
0:44
And part of the whole point for creating
a page object class is to ensure that our
0:52
test itself doesn't have to know
the details of how to connect to the page.
0:56
So I'm going to move this URL for
the page out of our test and
0:59
over to the page object class file.
1:04
Now I need to define a class
to represent the page.
1:08
Instances of this class
will be responsible for
1:10
controlling web driver to
do operations on the page.
1:13
So, I'll say class RsvpPage,
1:16
we need to set the values that we will be
returned when this module is required from
1:23
another module.
1:27
We'll set it up to return
the RsvpPage class.
1:28
So I'll say module.exports=RsvpPage.
1:31
The class constructor sets up
new instances of the class.
1:39
We're going to have the test pass in
a browser driver object when creating
1:43
a page object.
1:47
The page object will call methods on
the driver object to control the page.
1:48
We'll set the driver property of the new
object to equal the driver that's
1:53
passed in.
1:56
The locators property will be
an object containing locators for
2:01
the different page
elements we need to find.
2:04
Our first test uses a locator to find
the list that will populate with invitees.
2:09
We'll move the locator
from the test to here.
2:14
So I'll set the invitedList
attribute of the locators object
2:17
to equal By.id, and we'll look for
an ID of invitedList.
2:22
Our second test uses a locator to
find the form to register invitees,
2:30
we'll move that here, too.
2:34
We'll set up a property
named registationForm.
2:36
And we'll use the By.id locator
with an ID of registrar.
2:41
We're also going to want
a method to load the page.
2:49
It'll use whatever driver object
we pass into the constructor.
2:52
So we'll name our method open.
2:55
And within the open method,
3:00
we'll use the driver object that
belongs to this page object.
3:02
And we'll call the get method on it to
get the URL constant that we set above.
3:08
Let's save that, and now we need to update
our test to load our new module and
3:14
use the class.
3:18
So up here, I'll load the RsvpPage
class from our new module.
3:20
The double dot here means to
go to the parent directory,
3:32
the parent of the test directory.
3:35
And then go to the pages subdirectory,
and load the rsvp.js module.
3:38
Next, just as we did for our driver
variable, we need to define the variable
3:45
up here to hold the page object, so
that it stays in scope for all our tests.
3:49
So, we'll say let's page,
3:53
we won't actually assign anything to the
page variable until our before function.
3:56
Where we'll say that
the page = new RsvpPage
4:01
object and we'll pass the driver to
the constructor for that object.
4:07
And instead of calling
driver.get ourselves,
4:14
we'll let the page object
load the page for us.
4:16
So we'll say page.open Now remember,
we're trying to move all knowledge
4:18
of how to interact with the page, from our
test itself into the page object class.
4:24
So we're gonna take this snippet
of code here, that looks for
4:29
an element with an id of invitedList.
4:33
And instead,
4:36
we're going to use the locator that we
set up here in our page object class.
4:37
So we'll say page.locaters.invitedList.
4:41
We'll do the same down here
instead of looking an element up
4:49
with an id of registrar.
4:52
We'll just say that we're going
to use the locater that is
4:54
defined in our page object class,
which is registrationForm.
4:59
Let's make sure that our test is saved and
make sure that our page objects is
5:06
saved as well, and go back to our
terminal, and try running mocha again.
5:12
And our test will run
the same as they ever have.
5:19
The difference is that the tails
of how they interact with the page
5:21
have been moved to the page object class.
5:24
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up