Sometimes, you need to deal with sliders in your tests. Playwright does not have any built-in tools to interact with sliders. However, it is not a problem at all.
In this guide, you will learn how to interact with sliders in Playwright.
Let’s start by adding a simple slider element to our page using the setContent() method, which internally calls document.write() and adds anything you want in the DOM.
import {test, expect, Page} from '@playwright/test';
let page: Page;
const sliderHTML = `<div>
<p><input type="range" id="slider" min="0" max="100"/></p>
</div>`
test('Slider test', async ({page}) => {
await page.setContent(sliderHTML);
});
In this case, all you get is the simple range slider on the page.
I suggest making the task more complicated and setting the slider value random. This makes us consider how to interact with the slider depending on its value.
import {test, expect, Page} from '@playwright/test';
let page: Page;
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const sliderHTML = `<div>
<p><input type="range" id="slider" min="0" max="100" value="${getRandomInt(0, 100)}"/></p>
</div>`
test('Slider test', async ({page}) => {
await page.setContent(sliderHTML);
await setSliderValue(page, "//*[@id = 'slider']",75);
});
The solution will include multiple steps:
So, the final task is to set the slider to the given value, let’s say 95%.
- Find the slider element on a page.
- Detect its current value to be able to click on it.
- Move the slider into the final position (95%).
It looks pretty simple. Starting with finding the slider, I will use the XPath locator to find it. Feel free to check my XPath mastering guide.
For this case, I suggest using the following:
"//*[@id = 'slider']"
The next step is getting the bounding box of the slider element to determine its position and size.
const sliderBound = await page.locator("//*[@id = 'slider']").boundingBox();
The bounding box of an element is the smallest possible rectangle (aligned with the axes of that element’s user coordinate system) that entirely encloses it and its descendants.
The bounding box will help us to click and move the mouse cursor inside that box.
Since the slider pin can have random position, we need to find it actual coordinates. To do this, we need to obtain the current slider value from the HTML. It is possible with using page.evaluate() method.
const currentSliderValue = await page.evaluate(`document.evaluate(""//*[@id = 'slider']"", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value`);
This method returns the current slider value as a number. This number will help you to calculate the slider pin coordinate. Actually, you need to calculate two points for X and Y coordinates.
Because the slider pin moves horizontally, the X coordinates is crucial for us. To calculate it, use the formula:
const targetX = sliderBound.x + (sliderBound.width * currentSliderValue / 100);
To get the Y, just calculate the vertical middle point:
const targetY = sliderBound.y + sliderBound.height / 2;
Next, move the mouse cursor to the calculated point and hold its button:
await page.mouse.move(targetX, targetY);
await page.mouse.down();
Now you can move the mouse cursor horizontally to any position you want.
await page.mouse.move(
sliderBound.x + (sliderBound.width * 95) / 100,
sliderBound.y + sliderBound.height / 2,
);
await page.mouse.up();
Let’s bring all parts together and create a method for setting a wanted value to any slider element by its XPath:
async function setSliderValue(page: Page, sliderXPath: string, valueAsPercent: number) {
// Find the slider element using the provided XPath and obtain its bounding box
const sliderBound = await page.locator(sliderXPath).boundingBox();
// Use page.evaluate to obtain the current slider value from the HTML using the same XPath
const currentSliderValue = await page.evaluate(`document.evaluate("${sliderXPath}", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value`);
// Calculate the target X and Y coordinates for the mouse cursor based on the current slider value
const targetX = sliderBound.x + (sliderBound.width * currentSliderValue / 100);
const targetY = sliderBound.y + sliderBound.height / 2;
// Move the mouse cursor to the calculated position
await page.mouse.move(targetX, targetY);
// Simulate a mouse click by pressing the mouse button
await page.mouse.down();
// Move the mouse cursor to the desired position by the provided valueAsPercent
await page.mouse.move(
sliderBound.x + (sliderBound.width * valueAsPercent) / 100,
sliderBound.y + sliderBound.height / 2,
);
// Release the mouse button to complete the interaction
await page.mouse.up();
}
Now you can use it in your test just passing the slider locator and a wanted value:
import {test, expect, Page} from '@playwright/test';
let page: Page;
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
async function setSliderValue(page: Page, sliderXPath: string, valueAsPercent: number) {
// Find the slider element using the provided XPath and obtain its bounding box
const sliderBound = await page.locator(sliderXPath).boundingBox();
// Use page.evaluate to obtain the current slider value from the HTML using the same XPath
const currentSliderValue = await page.evaluate(`document.evaluate("${sliderXPath}", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value`);
// Calculate the target X and Y coordinates for the mouse cursor based on the current slider value
const targetX = sliderBound.x + (sliderBound.width * currentSliderValue / 100);
const targetY = sliderBound.y + sliderBound.height / 2;
// Move the mouse cursor to the calculated position
await page.mouse.move(targetX, targetY);
// Simulate a mouse click by pressing the mouse button
await page.mouse.down();
// Move the mouse cursor to the desired position by the provided valueAsPercent
await page.mouse.move(
sliderBound.x + (sliderBound.width * valueAsPercent) / 100,
sliderBound.y + sliderBound.height / 2,
);
// Release the mouse button to complete the interaction
await page.mouse.up();
}
const sliderHTML = `<div>
<p><input type="range" id="slider" min="0" max="100" value="${getRandomInt(0, 100)}"/></p>
</div>`
const sliderElementLocator = "//*[@id = 'slider']";
test('Slider test', async ({page}) => {
await page.setContent(sliderHTML);
await setSliderValue(page, sliderElementLocator, 75);
});
I hope this guide helped you to understand how to handle the sliders in Playwright.