Understanding DOM and Locators in Playwright: A Beginner’s Guide to Stable Test Automation
- Anuradha Agarwal
- Feb 13
- 8 min read
Updated: Feb 18
If you are new to Playwright and modern web automation, one of the most important concepts you must understand is the DOM (Document Object Model).
Playwright does not interact with the page the way humans do. It does not “see” buttons, textboxes, or labels visually. Instead, it interacts with the structured HTML representation of the page — the DOM.
Before writing stable and reliable automation scripts, you must clearly understand:
What is a DOM tree?
What are element nodes, attribute nodes, and text nodes?
How does the browser represent a web page internally?
What is a locator?
Why do some selectors fail even when the UI looks correct?
In this post, we will:
Break down DOM terminology using a simple HTML example
Learn how to inspect and analyse elements using Chrome Developer Tools
Understand what makes a selector unique
Write a basic Playwright test to fill text inputs using identified CSS selectors
We will intentionally focus only on DOM clarity and locator fundamentals in this article. This forms the foundation for everything that follows in modern Playwright test automation.
Automation Playground:https://www.anuradhaagarwal.com/automationplayground
Why DOM Knowledge Is a Prerequisite for Test Automation
Before we even talk about writing test cases, we must understand:
What is a web element?
How is it structured?
How does automation find it?
What is a locator?
Why do some tests fail even when the UI looks correct?
All these questions are directly related to DOM understanding.
If you understand DOM basics:
You will write stable locators
You will debug faster
You will avoid flaky tests
You will understand automation errors clearly
What Is the DOM?
DOM stands for Document Object Model.
When a browser loads HTML, it converts it into a tree-like structure called the DOM.
Let's take an example of this simple HTML file - simple.html
<!DOCTYPE html>
<html>
<head>
<title>Simple Demo Page</title>
</head>
<body>
<h1 id="title">Welcome</h1>
<input type="text" id="username" placeholder="Enter your name">
<button class="primary-btn">Login</button>
<button class="secondary-btn">Cancel</button
</body>
</html>This is loaded in the browser as

Let's give styling to buttons using class names :
!DOCTYPE html>
<html>
<head>
<title>Simple Demo Page</title>
<style>
.primary-btn {
background-color: orange;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
margin-right: 10px;
}
.secondary-btn {
background-color: gray;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1 id="title">Welcome</h1>
<input type="text" id="username" placeholder="Enter your name">
<button class="primary-btn">Login</button>
<button class="secondary-btn">Cancel</button>
</body>
</html>which is loaded in the browser as

When a browser loads HTML, it converts it into a tree-like structure called the DOM.
You can simple paste your html code in this website to see how the DOM looks for this HTML page

What Happens When Browser Loads This Page?
The browser converts HTML into a tree structure:
Document
└── html
├── head
│ ├── title → "Simple Demo Page"
│ └── style
│
└── body
├── h1 id="title" → "Welcome"
├── input id="username"
├── button class="primary-btn" → "Login"
└── button class="secondary-btn" → "Cancel"
Every item here is called a node. Before learning Playwright locators and test automation, it is essential to understand basic DOM terminology, as it forms the foundation for identifying and interacting with web elements.
1️⃣ Document Node (Root Owner)
The top-most node.
DocumentRepresents the entire webpage
Owns all elements
Starting point of automation
2️⃣ Element Nodes (HTML Tags)
These are actual HTML tags.
From our example:
<html>
<head>
<body>
<h1>
<input>
<button>
Element nodes define page structure.
Playwright interacts mostly with element nodes.
Example:
page.locator("button")
3️⃣ Attribute Nodes (Extra Information About Elements)
Attributes provide additional details about elements.
From our example:
id="title"
id="username" (unique identifier)
class="primary-btn" (for styling purpose)
class="secondary-btn"
placeholder="Enter your name"
Attributes help automation identify elements uniquely.
Example:
page.locator("#username")
page.locator(".primary-btn")
4️⃣ Text Nodes (Visible Content)
Text inside elements becomes text nodes.
Examples:
"Welcome"
"Login"
"Cancel"
Playwright validates text using assertions.
await expect(page.locator("h1")).toHaveText("Welcome")How to View DOM in Chrome (Inspect Tool)
Understanding the DOM becomes easier using browser developer tools.
Open any website(eg. https://www.anuradhaagarwal.com/automationplayground) in chrome
Open Developer Tools-> Right click → Inspect OR press F12
View Elements Tab. You will see:
HTML structure
Attributes
Nested elements
Text content
Hovering elements highlights them on screen. This shows exactly what automation interacts with.

What is a Locator?
Now that we understand the DOM structure, the next important concept in Playwright automation is a locator.
A locator is a way to identify and find a specific element in the DOM so that automation can interact with it.
Why Do We Need Locators?
A webpage contains many elements:
Multiple buttons
Multiple input fields
Multiple text elements
Multiple links
An automation tool must know exactly which element to interact with.
For example:
Which button should be clicked?
Which input field should receive text?
Which heading should be validated?
Locators solve this problem.
How Locators Work Internally
When you write:
page.locator("#username")Playwright:
Starts from the document node
Searches the DOM tree
Finds the matching element node
Acts on that element
This is why understanding DOM structure is essential.
Types of Information Used by Locators
Locators typically use:
id attribute → #username
class attribute → .primary-btn
text content → "Login"
element type → button
roles and accessibility attributes
CSS selectors or XPath
All of these come from the DOM structure we just learned.
Example Using Our HTML Page
From our example:
<input type="text" id="username">
<button class="primary-btn">Login</button>
Possible locators:
#username
.primary-btn
button
Playwright uses these to find elements inside the DOM tree.
Why Locator Strategy Matters
If you look at the dom structure of the Automation Playground page or the Test Demo Store, you will notice that these applications closely resemble real-world web applications. Unlike our simple HTML example, identifying elements in such applications is not always straightforward.
This is why having a clear locator strategy becomes critical in UI test automation.
In real-world applications:
Pages often contain duplicate elements
Some attributes are dynamically generated
Certain elements may be hidden or conditionally rendered
The DOM structure may change frequently
Using poor or unstable locators can lead to flaky tests, unreliable automation, and frequent test failures.
Good automation practices always focus on using stable, unique, and maintainable locators to ensure reliable test execution.
Identifying Elements Before Using Playwright Locators
Before we start using Playwright’s built-in methods for locating or interacting with elements, it is important to understand how to identify elements in the browser uniquely.
As we discussed earlier, real-world applications contain:
multiple similar elements
dynamic attributes
nested DOM structures
hidden or duplicate components
Because of this complexity, we must first learn how to identify elements correctly using browser tools.
Using Chrome Inspect Tool and SelectorHub
To understand how elements are identified in real applications, we will use:
Chrome Developer Tools (Inspect) — to view the DOM structure(already seen)
SelectorHub — a browser extension that helps generate and validate selectors
SelectorHub helps us:
Identify unique selectors
Verify whether a selector matches one element or multiple elements
Choose stable attributes for automation
Practical Example — Identifying the First Name Field
We will use our Automation Playground page for practice:
Using Chrome Inspect and SelectorHub, we will:
Inspect the First Name input field
Analyse its attributes (id, class, name, placeholder, etc.)
Identify a unique CSS selector for the element
Verify the selector’s uniqueness
A CSS selector is a pattern used to locate elements based on attributes such as:
id
class
name
placeholder
element type
This selector will serve as the element’s unique identity for automation.
From Selector to Playwright Test
Once we identify a stable CSS selector, we will use it in our Playwright test to:
locate the element
interact with the element
validate its behavior
This shows the complete workflow:
Inspect Element → Identify Unique Selector → Use in Playwright → Automate Action
So let's first install the selector hub if you don't have it already
Install SelectorHub
Open Chrome Web Store
Search "SelectorHub"
Install extension
Open Inspect → SelectorHub tab appears

Using SelectorHub
Open Inspect
Click element
SelectorHub suggests a locator
Verify uniqueness
For example, if we need to reach the username input text field in our automationplayground page, through the inspect tool after highlighting, we can see:

To find a unique identifier, we can take the help of a selector hub, like below

Creating a Unique Identity for First Name Field
From the DOM, we observed:
<input name="first-name" id="input_comp-ml6m44v5" type="text">
We can identify the element using different attributes.
Not Reliable — Generic Selector
inputMatches many elements → not unique.
Risky — Dynamic ID
#input_comp-ml6m44v5May be auto-generated and change → not stable.
Better — Meaningful Attribute
input[name="first-name"]Create a Simple Playwright Test Using Our Identified Selector
Now that we have identified a unique CSS selector for the First Name field, let’s use it inside a Playwright test and input a value.
We will use this selector:
input[name="first-name"]
This means:
input → the element type
[name="first-name"] → an attribute filter
So Playwright finds the input element whose name attribute equals first-name
Playwright Test: Fill First Name Field
Create a test file inside your tests folder, for example:
tests/automationplayground-form.spec.ts
import { test, expect } from '@playwright/test';
test('Fill form fields on Automation Playground', async ({ page }) => {
await page.goto('https://www.anuradhaagarwal.com/automationplayground');
// Fill First Name
await page.locator('input[name="first-name"]').fill('Anuradha');
// Optional: verify the value was entered
await expect(page.locator('input[name="first-name"]')).toHaveValue('Anuradha');
});
Run the test:
npx playwright test
Hands-On Exercise: Locator for Feedback Textbox
Now that you know how we identified the First Name selector using Chrome Inspect and SelectorHub, try the same for:
✅ Feedback field

Your task:
Inspect each field in the browser
Use SelectorHub to find a unique CSS selector
Update the same Playwright test to fill values for all three fields
// Fill Feedback (replace selector based on what you identify)
await page.locator('YOUR_FEEDBACK_SELECTOR').fill('This is my feedback message.');
That must be easy and would have added output something like below
// Fill Textbox feedback
await page.locator("textarea[placeholder='How can we improve?']").fill("keep working with your best..")
await expect(page.locator("textarea[placeholder='How can we improve?']")).toHaveValue("keep working with your best..")
Surprisingly if you try to find css selector for the email field with input[name='email'], selectorhub will show 2 elements:

Can you guess where the second element with the same tag and attribute
Use the Elements Tab Search to find the other email
Go to the Elements tab
Press:
Ctrl + F
Type:
input[name='email']
Chrome will jump to the first match.
Press Enter again to go to the next match. You will find this highlighted.

Clearly, this is not a unique CSS selector for the email field. Before we find which is the other email, let's find a unique CSS selector for this email input field by trying other attribute filters.
I can't use IDs, they seem to be dynamic in nature. I can try placeholder and it works:

Now modify your Playwright script to input a value in the email field, and also add an assertion
Final code so far
import { test, expect } from '@playwright/test';
test('Test fields on Automation Playground', async ({ page }) => {
await page.goto('https://www.anuradhaagarwal.com/automationplayground');
// Fill First Name
await page.locator('input[name="first-name"]').fill('Anuradha');
// Optional: verify the value was entered
await expect(page.locator('input[name="first-name"]')).toHaveValue('Anuradha');
//Fill email field
await page.locator("input[placeholder='example@domain.com']").fill("anuradha.learn@gmail.com")
await expect(page.locator("input[placeholder='example@domain.com']")).toHaveValue("anuradha.learn@gmail.com")
// Fill Textbox feedback
// await page.locator("textarea[placeholder='How can we improve?']:visible").fill("keep working with your best..")
// const feedback = page.locator("textarea[placeholder='How can we improve?']")
// console.log("Feedback value:", await feedback.inputValue());
// await expect(page.locator("textarea[placeholder='How can we improve?']")).toHaveValue("keep working with your best..")
//press sequential and press key method
const feedback = page.locator("textarea[placeholder='How can we improve?']")
await feedback.pressSequentially('Hello'); // Types instantly
await feedback.pressSequentially('World', { delay: 100 });
await feedback.press('Enter'); // Types slower, like a user
});At this stage, you should now clearly understand:
How a browser converts HTML into a DOM tree
The difference between document, element, attribute, and text nodes
How to inspect elements using Chrome Developer Tools
Why unique selectors are critical for stable automation
How Playwright uses those selectors to interact with text input fields
This is not just theory — this is the backbone of reliable test automation.
Many beginners jump directly into framework features and built-in locator methods without understanding what is happening underneath. That often leads to fragile tests, confusing errors, and unnecessary debugging.
By mastering DOM structure and locator fundamentals first, you are building strong automation thinking — not just learning syntax.
In the next post, we will move deeper into CSS selector fundamentals and UI controls, and start building more structured Playwright tests for real-world elements like radio buttons, checkboxes, dropdowns, and buttons on our demo-store.
And now that your DOM foundation is solid, everything ahead will feel much clearer and more powerful.




Comments