Semantic element targeting for Playwright - click by description, not selectors
npm install semantic-playwrightClick by description, not selectors.
A Playwright extension for semantic element targeting. Write resilient tests that survive website redesigns.
``bash`
npm install semantic-playwright playwright
`typescript
import { test } from '@playwright/test';
import { semantic } from 'semantic-playwright';
test('login flow', async ({ page }) => {
await page.goto('https://example.com/login');
const s = semantic(page);
// Click and fill by description - no CSS selectors needed
await s.fill('email input', 'user@example.com');
await s.fill('password field', 'secret123');
await s.click('sign in button');
// Wait for success
await s.waitFor('welcome message');
});
`
Modern web UIs change constantly. CSS selectors like #main-nav > ul > li:nth-child(3) > a.btn-primary break the moment a designer moves a button. This library provides self-healing locators that target elements by their semantic purpose.
`typescript
// Fragile - breaks on redesign
await page.click('#nav-signin-btn');
// Resilient - survives redesign
await s.click('sign in button');
`
The semantic engine classifies DOM elements using multiple signals:
- ARIA roles: role="button", role="navigation"
- Semantic HTML:
No LLM required. Pure heuristic matching. Fast, local, privacy-preserving.
Wrap a Playwright page with semantic methods:
`typescript`
const s = semantic(page);
Click an element by description:
`typescript`
await s.click('submit button');
await s.click('login', { purposeHint: 'action' });
Fill a form field by description:
`typescript`
await s.fill('email input', 'test@example.com');
await s.fill('search box', 'playwright');
Get a Playwright Locator for chaining:
`typescript`
const btn = await s.locator('checkout button');
await btn.hover();
await btn.click();
Analyze page structure:
`typescript`
const { elements, summary } = await s.analyze();
console.log(summary);
// { navigation: 12, action: 8, form: 5, content: 20, data: 3, unknown: 0 }
Find elements by category:
`typescript`
const buttons = await s.query('action');
const searchInputs = await s.query('form', 'search');
Find all matching elements with scores:
`typescript${text}: ${score}
const matches = await s.findAll('submit');
for (const { locator, score, text } of matches) {
console.log();`
}
Wait for element to appear:
`typescript`
await s.waitFor('success notification', { timeout: 10000 });
| Category | Description | Examples |
|----------|-------------|----------|
| navigation | Navigation elements | Nav bars, menus, breadcrumbs |action
| | Interactive actions | Buttons, CTAs, links styled as buttons |form
| | Form inputs | Text fields, selects, checkboxes |content
| | Main content | Articles, headings, paragraphs |data
| | Data display | Tables, lists, grids |
`typescript`
interface SemanticOptions {
purposeHint?: 'navigation' | 'action' | 'form' | 'content' | 'data';
timeout?: number; // Default: 5000ms
minScore?: number; // Default: 20
}
``
src/
├── index.ts # Main API - SemanticPage wrapper
├── semantic-mapper.ts # Classification engine & JS generators
Key design decisions:
- Scripts execute in browser context via page.evaluate()
- Classification is entirely heuristic-based (no external calls)
- Selectors generated are full CSS paths for reliability
- Scoring system prefers exact matches, falls back gracefully
`bash`
npm install
npm run build
npm test
Tests should use real websites to validate resilience:
1. Test against sites that redesign frequently
2. Snapshot selectors, verify semantic descriptions still work after updates
3. Compare failure rates: CSS selectors vs semantic descriptions
page wrapper
- [x] click(), fill(), locator() methods
- [x] analyze() and query() methods
- [x] findAll() and waitFor() methods$3
- [ ] Playwright Test fixtures (useSemanticPage)
- [ ] Custom matchers (expect(s).toHaveElement('login button')`)This library is inspired by and aims to improve upon:
- Browser-Use: AI agent browser automation (requires LLM)
- Healenium: Self-healing Selenium (Java-focused)
- Test.ai: AI-powered testing (SaaS, expensive)
Our differentiator: No LLM required. Fast, local, free.
MIT