Skip to content

Commit e7a7733

Browse files
author
Mark Skelton
authored
Playwright 1.18 (#26)
* Update to Playwright release candidate * Add ESLint plugin * Add a new `hasText` option * Add changeset * Cleanup old docs
1 parent 68c4274 commit e7a7733

File tree

7 files changed

+307
-29
lines changed

7 files changed

+307
-29
lines changed

.changeset/purple-parents-taste.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'lariat': minor
3+
---
4+
5+
Add `hasText` option to `Collection.el()` to filter by text using the `hasText`
6+
locator option introduced in Playwright 1.18.

.eslintrc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
{
22
"parser": "@typescript-eslint/parser",
33
"plugins": ["@typescript-eslint"],
4-
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
4+
"extends": [
5+
"eslint:recommended",
6+
"plugin:@typescript-eslint/recommended",
7+
"plugin:playwright/playwright-test"
8+
],
59
"env": {
610
"node": true
711
}

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ const todoPage = new TodoPage(page)
6666
await todoPage.saveButton.click()
6767
```
6868

69+
### Matching Text Content
70+
71+
Elements can be matched by text content using the `hasText` option. This will
72+
only return elements that include the specified text or contain a child with the
73+
specified text.
74+
75+
```ts
76+
class TodoPage extends Collection<Page> {
77+
saveButton = this.el('button', { hasText: 'Save' })
78+
}
79+
```
80+
6981
### Dynamic selectors
7082

7183
Because collections in Lariat are plain JavaScript classes, you can easily

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@
2929
"release": "./scripts/release.sh"
3030
},
3131
"dependencies": {
32-
"playwright-core": "^1.17.0"
32+
"playwright-core": "^1.18.0-rc1"
3333
},
3434
"devDependencies": {
3535
"@changesets/cli": "^2.19.0",
36-
"@playwright/test": "^1.17.2",
36+
"@playwright/test": "^1.18.0-rc1",
3737
"@typescript-eslint/eslint-plugin": "^5.9.1",
3838
"@typescript-eslint/parser": "^5.9.1",
3939
"eslint": "^8.6.0",
40+
"eslint-plugin-playwright": "^0.7.1",
4041
"prettier": "^2.5.1",
4142
"typescript": "^4.5.4"
4243
}

src/Collection.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,46 @@ import { enhance, NestedCollection } from './enhance'
33
import { Handle, isLocator } from './utils'
44

55
export interface ElementOptions {
6+
/**
7+
* When true, the locator will be based off the `frame`, rather than the
8+
* `root` thus escaping from any collection nesting. This is useful to
9+
* represent a page structure whose visual appearance differs from it's
10+
* DOM structure.
11+
*
12+
* @default false
13+
*/
614
portal?: boolean
15+
/**
16+
* When defined, creates a frame locator which the element will be nested
17+
* inside of.
18+
*/
719
frame?: string
20+
/**
21+
* Matches elements containing specified text somewhere inside, possibly in a
22+
* child or a descendant element.
23+
*/
24+
hasText?: string | RegExp
825
}
926

1027
export class Collection<T extends Handle = Locator> {
1128
constructor(public root: T) {}
1229

1330
/**
1431
* Retrieve a locator to a given element on the page identified by the
15-
* selector. The locator is lazily initialized when retrieved to ensure that
16-
* the most current `root` element is used.
17-
*
18-
* If `options.portal` is set to true, the locator will be based off the
19-
* `frame`, rather than the `root` thus escaping from any collection nesting.
20-
* This is useful to represent a page structure whose visual appearance
21-
* differs from it's DOM structure.
32+
* selector.
2233
*
2334
* @param selector - The selector that identifies the element.
2435
* @param options - Options for how to build the locator.
2536
*/
26-
protected el(selector: string, options?: ElementOptions): Locator {
27-
const root = options?.portal ? this.frame : this.root
37+
protected el(
38+
selector: string,
39+
{ portal, frame, hasText }: ElementOptions = {}
40+
): Locator {
41+
const root = portal ? this.frame : this.root
2842

29-
return options?.frame
30-
? root.frameLocator(options.frame).locator(selector)
31-
: root.locator(selector)
43+
return frame
44+
? root.frameLocator(frame).locator(selector, { hasText })
45+
: root.locator(selector, { hasText })
3246
}
3347

3448
/**

test/elements.spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expect, test } from '@playwright/test'
1+
import { expect, Page, test } from '@playwright/test'
22
import Collection from '../src'
33

44
class RootPage extends Collection {
@@ -27,4 +27,14 @@ test.describe('Elements', () => {
2727
const modalPage = new ModalPage(page.locator('#content'))
2828
await expect(modalPage.modal).toHaveText('Hi')
2929
})
30+
31+
test('locates elements with specific text', async ({ page }) => {
32+
class TodoPage extends Collection<Page> {
33+
button = this.el('button', { hasText: 'Ho' })
34+
}
35+
36+
await page.setContent('<button>Hi</button><button>Ho</button>')
37+
const todoPage = new TodoPage(page)
38+
await expect(todoPage.button).toHaveText('Ho')
39+
})
3040
})

0 commit comments

Comments
 (0)