Skip to content

Commit 510a0e7

Browse files
committed
docs: add advanced selectors guide and robust iframe test coverage
1 parent 56b566e commit 510a0e7

35 files changed

Lines changed: 220 additions & 2 deletions

File tree

artifacts/k11-platform-locator-id-map/element-locator-id-map-locators-lab.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@
2323
"sandbox_title": { "id": "locators-lab-sandbox-title", "type": "heading" },
2424
"sandbox_desc": { "id": "locators-lab-sandbox-desc", "type": "text" },
2525
"loader": { "id": "locators-lab-loader", "type": "container" },
26-
"sandbox_root": { "id": "locators-lab-sandbox-root", "type": "container" }
26+
"sandbox_root": { "id": "locators-lab-sandbox-root", "type": "container" },
27+
"modal_card": { "selector": "[data-k11='modal-card']", "type": "container" },
28+
"user_email": { "selector": "#userEmail", "type": "input" },
29+
"user_pass": { "selector": "#userPass", "type": "input" },
30+
"company_name": { "selector": "#companyName", "type": "input" },
31+
"mobile": { "selector": "#mobile", "type": "input" },
32+
"country": { "selector": "#country", "type": "select" },
33+
"disabled_name": { "selector": "#disabledName", "type": "input" },
34+
"sandbox_form_section": { "selector": "section:has(h3:has-text('Dummy Form'))", "type": "section" },
35+
"sandbox_table_section": { "selector": "section:has(h3:has-text('User Table'))", "type": "section" },
36+
"sandbox_shadow_section": { "selector": "section:has(h3:has-text('Shadow DOM'))", "type": "section" },
37+
"sandbox_popups_section": { "selector": "section:has(h3:has-text('Popups & Actions'))", "type": "section" },
38+
"sandbox_iframe_section": { "selector": "section:has(h3:has-text('iframe Lab (srcDoc)'))", "type": "section" },
39+
"iframe": { "selector": "iframe[title='k11-iframe-lab']", "type": "iframe" }
2740
}
2841
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Playwright Advanced Selectors Guide
2+
3+
This guide demonstrates advanced selector strategies in Playwright using the Locators Lab page. These examples help you robustly target elements in complex UIs, including shadow DOM and iframes.
4+
5+
## Covered Selector Strategies
6+
- **Text and Partial Text**: Locate elements by their visible text or a substring.
7+
- **CSS and XPath**: Use CSS selectors and XPath expressions for precise targeting.
8+
- **Nth Element and Attribute**: Select elements by index or filter by attributes.
9+
- **Role and Label**: Use ARIA roles and accessible names for robust, semantic selection.
10+
- **Shadow DOM**: Target elements inside open shadow roots.
11+
- **Iframe**: Interact with elements inside embedded iframes.
12+
13+
## Example Test Cases
14+
15+
```js
16+
const { test, expect } = require('@playwright/test');
17+
const LocatorsLabPage = require('../../pages/LocatorsLabPage');
18+
19+
test.describe('Selectors Advanced (Locators Lab)', () => {
20+
test('should select element by text and partial text', async ({ page }) => {
21+
const lab = new LocatorsLabPage(page);
22+
await lab.goto();
23+
await expect(page.getByText('Sandbox Area')).toBeVisible();
24+
await expect(page.locator('text=Practice Lab')).toBeVisible();
25+
await expect(lab.title).toBeVisible();
26+
});
27+
28+
test('should select element by CSS and XPath', async ({ page }) => {
29+
const lab = new LocatorsLabPage(page);
30+
await lab.goto();
31+
await expect(lab.title).toBeVisible();
32+
await expect(page.locator('//h2[contains(text(),"Sandbox Area")]')).toBeVisible();
33+
});
34+
35+
test('should select nth element and filter by attribute', async ({ page }) => {
36+
const lab = new LocatorsLabPage(page);
37+
await lab.goto();
38+
const actionButtons = lab.actionButtons.locator('button');
39+
await expect(actionButtons.nth(0)).toBeVisible();
40+
await expect(page.locator('input[id*="user"]').first()).toBeVisible();
41+
});
42+
43+
test('should select element inside shadow DOM', async ({ page }) => {
44+
const lab = new LocatorsLabPage(page);
45+
await lab.goto();
46+
await expect(lab.sandboxShadowSection).toBeVisible();
47+
// Example: page.locator('k11-shadow-root >>> .shadow-element')
48+
});
49+
50+
test('should select element by role and label', async ({ page }) => {
51+
const lab = new LocatorsLabPage(page);
52+
await lab.goto();
53+
await expect(page.getByRole('button', { name: /run/i })).toBeVisible();
54+
await expect(page.getByRole('button', { name: /clear/i })).toBeVisible();
55+
});
56+
57+
test('should select element inside iframe', async ({ page }) => {
58+
const lab = new LocatorsLabPage(page);
59+
await lab.goto();
60+
await expect(lab.sandboxIframeSection).toBeVisible();
61+
await expect(lab.iframe.locator('h3', { hasText: 'Iframe Lab' })).toBeVisible();
62+
await expect(lab.iframe.locator('div > p')).toBeVisible();
63+
await expect(lab.iframe.locator('input#ifEmail')).toBeVisible();
64+
await expect(lab.iframe.locator('table[aria-label="Orders"]')).toBeVisible();
65+
await expect(lab.iframe.locator('td', { hasText: '#A-101' })).toBeVisible();
66+
});
67+
});
68+
```
69+
70+
## Best Practices
71+
- Prefer role and label selectors for accessibility and resilience.
72+
- Use page objects (like `LocatorsLabPage`) to centralize and maintain selectors.
73+
- For shadow DOM, use the `>>>` combinator.
74+
- For iframes, use `frameLocator` and assert on elements inside the frame.
75+
- Always validate selectors against the current DOM structure.
76+
77+
---
78+
For more, see the Playwright [Selectors documentation](https://playwright.dev/docs/selectors).

pages/LocatorsLabPage.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Page object for https://k11softwaresolutions.com/labs/locators
2+
// Generated from artifacts/k11-platform-locator-id-map/element-locator-id-map-locators-lab.json
3+
4+
class LocatorsLabPage {
5+
/**
6+
* @param {import('@playwright/test').Page} page
7+
*/
8+
constructor(page) {
9+
this.page = page;
10+
// ID-based locators
11+
this.root = page.locator('#locators-lab-root');
12+
this.mainGrid = page.locator('#locators-lab-main-grid');
13+
this.controlsPanel = page.locator('#locators-lab-controls-panel');
14+
this.title = page.locator('#locators-lab-title');
15+
this.desc = page.locator('#locators-lab-desc');
16+
this.modeToggle = page.locator('#locators-lab-mode-toggle');
17+
this.modeCss = page.locator('#locators-lab-mode-css');
18+
this.modeXpath = page.locator('#locators-lab-mode-xpath');
19+
this.query = page.locator('#locators-lab-query');
20+
this.deepToggleRow = page.locator('#locators-lab-deep-toggle-row');
21+
this.deepToggle = page.locator('#locators-lab-deep-toggle');
22+
this.actionButtons = page.locator('#locators-lab-action-buttons');
23+
this.runBtn = page.locator('#locators-lab-run-btn');
24+
this.clearBtn = page.locator('#locators-lab-clear-btn');
25+
this.statusRow = page.locator('#locators-lab-status-row');
26+
this.statusError = page.locator('#locators-lab-status-error');
27+
this.statusSuccess = page.locator('#locators-lab-status-success');
28+
this.examples = page.locator('#locators-lab-examples');
29+
this.sandboxPanel = page.locator('#locators-lab-sandbox-panel');
30+
this.sandboxTitle = page.locator('#locators-lab-sandbox-title');
31+
this.sandboxDesc = page.locator('#locators-lab-sandbox-desc');
32+
this.loader = page.locator('#locators-lab-loader');
33+
this.sandboxRoot = page.locator('#locators-lab-sandbox-root');
34+
// Selector-based locators
35+
this.modalCard = page.locator('[data-k11="modal-card"]');
36+
this.userEmail = page.locator('#userEmail');
37+
this.userPass = page.locator('#userPass');
38+
this.companyName = page.locator('#companyName');
39+
this.mobile = page.locator('#mobile');
40+
this.country = page.locator('#country');
41+
this.disabledName = page.locator('#disabledName');
42+
this.sandboxFormSection = page.locator("section:has(h3:has-text('Dummy Form'))");
43+
this.sandboxTableSection = page.locator("section:has(h3:has-text('User Table'))");
44+
this.sandboxShadowSection = page.locator("section:has(h3:has-text('Shadow DOM'))");
45+
this.sandboxPopupsSection = page.locator("section:has(h3:has-text('Popups & Actions'))");
46+
this.sandboxIframeSection = page.locator("section:has(h3:has-text('iframe Lab (srcDoc)'))");
47+
this.iframe = page.frameLocator("iframe[title='k11-iframe-lab']");
48+
}
49+
50+
async goto() {
51+
await this.page.goto('https://k11softwaresolutions.com/labs/locators');
52+
}
53+
}
54+
55+
module.exports = LocatorsLabPage;
150 KB
Loading
613 KB
Loading
564 KB
Loading
517 KB
Loading
406 KB
Loading
154 KB
Loading
631 KB
Loading

0 commit comments

Comments
 (0)