Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Start a free Courses trial
to watch this video
So far, we've been using IDs and CSS selectors to locate elements within a page. Those are usually the best and most stable ways to find elements. But sometimes, an element doesn't have a usable ID, and there's no good way to select it with CSS, either. In that event, WebDriver has a By.js locator that lets you use JavaScript code to find the element. When using the By.js locator, you can write ordinary JavaScript code just like you might write as part of an any web page.
In this video, we'll be using this page.
So far, we've been using IDs and CSS selectors to locate elements within a page. Those are usually the best and most stable ways to find elements. But sometimes, an element doesn't have a usable ID, and there's no good way to select it with CSS, either.
In that event, WebDriver has a By.js
locator that lets you use JavaScript code to find the element. When using the By.js
locator, you can write ordinary JavaScript code just like you might write as part of an any web page. In this last video of the course, I'll show you how it works.
To use the By.js
locator effectively, you'll need to be familiar with writing JavaScript for the web. If you're not, and you'd like to learn more, see our JavaScript Basics course.
- We want to create a form that submits its data via AJAX, without reloading the whole page.
- Right now, we just have Cancel and Save buttons for the form.
- When we click Save, we update the text of a
<span>
element with an ID ofstatus
to show that the form has been saved. - Let's write a test to ensure that the status always gets updated when we click the Save button.
test/buttons.js
// We start out our test just like all the others, importing the WebDriver
// objects and functions we need. We also import the page object class we're
// going to set up.
const {Browser, By, Key, until} = require("selenium-webdriver");
const {suite} = require("selenium-webdriver/testing");
const assert = require('assert');
const ButtonsPage = require('../pages/buttons.js');
suite(function(env) {
describe('Save button', function() {
let driver;
let page;
before(async function() {
driver = await env.builder().build();
page = new ButtonsPage(driver);
await page.open();
});
// Our test is going to ensure that the status text gets updated
// when we click the Save button.
it('Updates status text', async function() {
// The test itself won't be much different from the ones we defined
// in previous videos. We call a method that we're going to define
// on our page object to click the Save button.
await page.clickSave();
// Once that's done, we locate the span element that shows the
// status.
let span = await driver.findElement(page.locators.status);
// We get its text.
let text = await span.getText();
// Then we assert that the status includes the string "Saved!"
assert(text.includes("Saved!"));
});
after(async function() {
driver.quit();
});
});
});
- Not much different than previous tests, right? But writing those methods for the page object is going to be a little more difficult.
- Let's go back to our browser, and I'll show you what I mean.
- If I right-click on the buttons and choose Inspect, it will show their HTML code.
- You can see that they don't have any IDs, or any other attributes that we can use to easily tell them apart using WebDriver. If we just select any old
<button>
element, we could wind up with the Cancel button instead of the Save button. - This isn't really best practice, but sometimes the app is just coded the way it's coded, and it's not really within the QA team's control.
- That's okay, though. We can use a JavaScript locator to help us find the right button.
- Let's go into our page object class and add one.
pages/buttons.js
const {Browser, By, Key, until} = require("selenium-webdriver");
const url = 'https://treehouse-projects.github.io/selenium-webdriver-intermediate/byjs/app/';
class ButtonsPage {
constructor(driver) {
this.driver = driver;
this.locators = {
// The locator for the "status" span is pretty simple. We can locate
// it by its ID.
status: By.id('status'),
// To write a locator for the Save button, we'll use the By.js
// locator. You call the By.js() method, and pass it a callback
// function that returns the element you want to select.
// Within that function, we can use JavaScript code just like
// we would in the web page itself.
saveButton: By.js(function() {
// Just like in ordinary JavaScript code, the "document"
// object represents the web page. And as always, it has
// a getElementsByTagName() method that we can use to find
// all the <button> elements.
var buttons = document.getElementsByTagName('button');
// All the other features of ordinary JavaScript are available
// to us, too. Here, we write a "for" loop to loop over the
// array of button elements and find the button we want.
for (index = 0; index < buttons.length; ++index) {
// We test whether the current button has text content
// of "Save". If it does, we've found our element.
if (buttons[index].textContent === "Save") {
// We return that element from the function, and
// that becomes the result of the By.js locator.
return buttons[index];
}
}
}),
}
}
open() {
this.driver.get(url);
}
// Now we need to add a clickSave() method, which will actually click
// the Save button.
async clickSave() {
// Since we already have the locator written, this part is easy.
// We just call the driver's findElement() method, and pass it the
// locator we defined above.
var button = await this.driver.findElement(this.locators.saveButton);
// Then we call the click() method on the button it returns.
await button.click();
}
}
module.exports = ButtonsPage;
Using WebDriver with testing frameworks for other languages
If you need to write your tests in a different language, visit the Selenium WebDriver documentation. It includes info on setting up WebDriver with a variety or programming languages.
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
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