Modify serialized DOM using domTransformation
Learn how to customize and manipulate serialized DOM using the domTransformation feature.
In certain scenarios, you may need to modify the DOM to ensure it renders correctly in Percy. For example, you might hide ad banners or adjust UI states that are not captured as expected. When Percy sends the serialized DOM to its backend for re-rendering across different browsers and devices, you can modify it by passing a domTransformation
function. Learn more about the basics of Percy SDKs workflow by reviewing this guide.
The domTransformation
function accepts documentElement
as an argument and doesn’t require a return value. Check out the following examples to see how it works.
Examples
If you use the percy snapshot command, follow this configuration.
- This feature requires Percy CLI v1.24.0 or higher.
- It’s only available for per-snapshot configuration, and not global configuration.
Percy snapshot
- name: Example
url: https://example.com
widths: [1280]
domTransformation: |
(documentElement) => {
function changeHeader(root) {
documentElement.querySelector('h1').innerText = 'Changed using domTransformation'
}
changeHeader(documentElement);
SDKs
If you’re using any SDKs then you can check the following SDK examples.
- This applies to both BrowserStack SDK and Percy SDK.
- Use
percy_snapshot
function if you’re using the Percy SDK for web projects. For Automate projects with the Percy SDK or when using the BrowserStack SDK, usepercy_screenshot
function.
Selenium
dom_transformation = """ (documentElement) => { documentElement.querySelector('body').style.color = 'green'; } """
percy_snapshot(driver, 'Home Page', domTransformation=dom_transformation )
String domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';";
Map<String, Object> options = new HashMap<>();
options.put("domTransformation", domTransformation);
Percy.Snapshot("Snapshot Name", options);
Percy.Snapshot(driver, "Snapshot Name", new { domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';" });
or
string domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';";
Percy.Options snapshotOptions = new Percy.Options();
snapshotOptions.Add("domTransformation", domTransformation);
Percy.Snapshot(page, ".NET typed options", snapshotOptions);
dom_transformation = "(documentElement) => documentElement.querySelector('body').style.color = ‘green';"
# Use %Q{} for Multi-Line Strings
Percy.snapshot(driver, 'Home Page', { domTransformation: dom_transformation })
Playwright
dom_transformation = """ (documentElement) => { documentElement.querySelector('body').style.color = 'green'; } """
percy_snapshot(driver, 'Home Page', domTransformation=dom_transformation )
String domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';";
Map<String, Object> options = new HashMap<>();
options.put("domTransformation", domTransformation);
Percy.Snapshot("Snapshot Name", options);
Percy.Snapshot(driver, "Snapshot Name", new { domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';" });
or
string domTransformation = "(documentElement) => documentElement.querySelector('body').style.color = 'green';";
Percy.Options snapshotOptions = new Percy.Options();
snapshotOptions.Add("domTransformation", domTransformation);
Percy.Snapshot(page, ".NET typed options", snapshotOptions);
it('example test', async () => {
// ...
domTransformation = "(documentElement) => documentElement.querySelector('h1').innerText = 'Changed using domTransformation'"
await page.setViewport({ width: 1280, height: 1024 });
await percySnapshot(page, 'Home Page', { width: 1280, domTransformation });
// ...
Cypress
// ...
domTransformation = "(documentElement) => documentElement.querySelector('h1').innerText = 'Changed using domTransformation'"
cy
.viewport(1280, 1024)
.percySnapshot('Home page', { width: 1280, domTransformation });
// ...
Puppeteer
// ...
domTransformation = "(documentElement) => documentElement.querySelector('h1').innerText = 'Changed using domTransformation'"
await page.setViewport({ width: 1280, height: 1024 });
await percySnapshot(page, 'Home Page', { width: 1280, domTransformation });
// ...
Storybook
Note: It only works with enableJavaScript: false
// ...
App.parameters = {
percy: {
domTransformation: `
(documentElement) => {
documentElement.querySelector('h1').innerText = 'Changed using domTransformation';
}`
}
};
// ...
Advanced use case
Accessing DOM elements inside shadow DOM:
// you could use multiline string syntax that might be available in your language
domTransformation = (documentElement) => {
function updateLinks(root) {
root.querySelectorAll('.myLink').forEach(link => {
console.log(link);
// do stuff here
});
// we mark shadow host with following marker during serialisation
root.querySelectorAll('[data-percy-shadow-host]')
.forEach(
shadowHost => {
console.log(shadowHost);
if (shadowHost?.shadowRoot)
updateLinks(shadowHost.shadowRoot);
});
}
updateLinks(documentElement);
}
// in JS
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
Thank you for your valuable feedback!