promod 2.5.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/cjs/config.d.ts +43 -0
- package/built/cjs/config.js +161 -0
- package/built/cjs/config.js.map +1 -0
- package/built/cjs/helpers/execute.script.d.ts +1 -1
- package/built/cjs/helpers/execute.script.js +1 -3
- package/built/cjs/helpers/execute.script.js.map +1 -1
- package/built/cjs/index.d.ts +3 -1
- package/built/cjs/index.js +4 -1
- package/built/cjs/index.js.map +1 -1
- package/built/cjs/interface.d.ts +8 -4
- package/built/cjs/mappers.d.ts +1 -1
- package/built/cjs/mappers.js.map +1 -1
- package/built/cjs/pw/index.d.ts +2 -2
- package/built/cjs/pw/pw_client.d.ts +11 -10
- package/built/cjs/pw/pw_client.js +37 -56
- package/built/cjs/pw/pw_client.js.map +1 -1
- package/built/cjs/pw/pw_element.d.ts +17 -16
- package/built/cjs/pw/pw_element.js +19 -46
- package/built/cjs/pw/pw_element.js.map +1 -1
- package/built/cjs/shared/custom_selector_filter.d.ts +19 -0
- package/built/cjs/shared/custom_selector_filter.js +40 -0
- package/built/cjs/shared/custom_selector_filter.js.map +1 -0
- package/built/cjs/shared/validate_browser.d.ts +7 -0
- package/built/cjs/shared/validate_browser.js +29 -0
- package/built/cjs/shared/validate_browser.js.map +1 -0
- package/built/cjs/swd/swd_alignment.d.ts +1 -1
- package/built/cjs/swd/swd_alignment.js +2 -28
- package/built/cjs/swd/swd_alignment.js.map +1 -1
- package/built/cjs/swd/swd_client.d.ts +13 -10
- package/built/cjs/swd/swd_client.js +95 -31
- package/built/cjs/swd/swd_client.js.map +1 -1
- package/built/cjs/swd/swd_element.d.ts +14 -13
- package/built/cjs/swd/swd_element.js +13 -12
- package/built/cjs/swd/swd_element.js.map +1 -1
- package/built/esm/config.d.ts +43 -0
- package/built/esm/config.js +158 -0
- package/built/esm/config.js.map +1 -0
- package/built/esm/helpers/execute.script.d.ts +1 -1
- package/built/esm/helpers/execute.script.js +5 -9
- package/built/esm/helpers/execute.script.js.map +1 -1
- package/built/esm/index.d.ts +3 -1
- package/built/esm/index.js +4 -7
- package/built/esm/index.js.map +1 -1
- package/built/esm/interface.d.ts +8 -4
- package/built/esm/interface.js +1 -2
- package/built/esm/internals/index.js +1 -5
- package/built/esm/internals/index.js.map +1 -1
- package/built/esm/internals/logger.js +3 -6
- package/built/esm/internals/logger.js.map +1 -1
- package/built/esm/mappers.d.ts +1 -1
- package/built/esm/mappers.js +1 -7
- package/built/esm/mappers.js.map +1 -1
- package/built/esm/pw/index.d.ts +2 -2
- package/built/esm/pw/index.js +7 -10
- package/built/esm/pw/index.js.map +1 -1
- package/built/esm/pw/pw_client.d.ts +11 -10
- package/built/esm/pw/pw_client.js +93 -116
- package/built/esm/pw/pw_client.js.map +1 -1
- package/built/esm/pw/pw_element.d.ts +17 -16
- package/built/esm/pw/pw_element.js +84 -118
- package/built/esm/pw/pw_element.js.map +1 -1
- package/built/esm/shared/custom_selector_filter.d.ts +19 -0
- package/built/esm/shared/custom_selector_filter.js +38 -0
- package/built/esm/shared/custom_selector_filter.js.map +1 -0
- package/built/esm/shared/validate_browser.d.ts +7 -0
- package/built/esm/shared/validate_browser.js +27 -0
- package/built/esm/shared/validate_browser.js.map +1 -0
- package/built/esm/swd/index.js +7 -10
- package/built/esm/swd/index.js.map +1 -1
- package/built/esm/swd/swd_alignment.d.ts +1 -1
- package/built/esm/swd/swd_alignment.js +13 -42
- package/built/esm/swd/swd_alignment.js.map +1 -1
- package/built/esm/swd/swd_client.d.ts +13 -10
- package/built/esm/swd/swd_client.js +171 -111
- package/built/esm/swd/swd_client.js.map +1 -1
- package/built/esm/swd/swd_element.d.ts +14 -13
- package/built/esm/swd/swd_element.js +90 -97
- package/built/esm/swd/swd_element.js.map +1 -1
- package/docs/client.md +335 -111
- package/docs/config.md +176 -0
- package/docs/element.md +214 -141
- package/docs/elements.md +125 -65
- package/docs/init.md +66 -12
- package/oxlintrc.json +20 -0
- package/package.json +15 -18
- package/readme.md +114 -14
- package/tsconfig.esm.json +6 -2
- package/tsconfig.json +4 -1
package/docs/elements.md
CHANGED
|
@@ -1,116 +1,176 @@
|
|
|
1
1
|
# Elements
|
|
2
2
|
|
|
3
|
-
Elements has "lazy" interface (as it was in protractor)
|
|
3
|
+
Elements has a "lazy" interface (as it was in protractor). The collection is not resolved until an action is performed on it.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
All examples work identically with both `playwrightWD` and `seleniumWD`.
|
|
6
|
+
|
|
7
|
+
- [Selector strategies](#selector-strategies)
|
|
6
8
|
- [get](#get)
|
|
7
9
|
- [first](#first)
|
|
8
10
|
- [last](#last)
|
|
11
|
+
- [count](#count)
|
|
12
|
+
- [getFirstVisible](#getfirstvisible)
|
|
13
|
+
- [getAllVisible](#getallvisible)
|
|
9
14
|
- [each](#each)
|
|
10
15
|
- [map](#map)
|
|
11
16
|
- [some](#some)
|
|
12
17
|
- [every](#every)
|
|
18
|
+
- [find](#find)
|
|
19
|
+
- [filter](#filter)
|
|
20
|
+
- [getEngineElements](#getengineelements)
|
|
21
|
+
|
|
22
|
+
---
|
|
13
23
|
|
|
14
|
-
##
|
|
24
|
+
## Selector strategies
|
|
15
25
|
|
|
16
26
|
```js
|
|
17
|
-
const {
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
27
|
+
const { playwrightWD } = require('promod');
|
|
28
|
+
const { $$ } = playwrightWD;
|
|
29
|
+
|
|
30
|
+
const byCss = $$('.class #id div a[href*="link"]');
|
|
31
|
+
const byXpath = $$('xpath=.//div[@data-test="id"]/span');
|
|
32
|
+
const byJS = $$(() => document.querySelectorAll('div > span'));
|
|
33
|
+
const byCustom = $$({ query: 'button', text: 'Submit' });
|
|
24
34
|
```
|
|
25
35
|
|
|
26
36
|
## get
|
|
27
37
|
|
|
38
|
+
Returns a single element from the collection by index. Negative indexes count from the end.
|
|
39
|
+
|
|
28
40
|
```js
|
|
29
|
-
const
|
|
30
|
-
const { $$ } = seleniumWD;
|
|
31
|
-
const someInput = $$('input').get(3);
|
|
41
|
+
const buttons = $$('button');
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
const first = buttons.get(0);
|
|
44
|
+
const third = buttons.get(2);
|
|
45
|
+
const last = buttons.get(-1);
|
|
46
|
+
|
|
47
|
+
await first.click();
|
|
36
48
|
```
|
|
37
49
|
|
|
38
50
|
## first
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
const { seleniumWD } = require('promod');
|
|
42
|
-
const { $$ } = seleniumWD;
|
|
43
|
-
const someButton = $$('button').first();
|
|
52
|
+
Shorthand for `get(0)`.
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
```js
|
|
55
|
+
const button = $$('button').first();
|
|
56
|
+
await button.click();
|
|
48
57
|
```
|
|
49
58
|
|
|
50
59
|
## last
|
|
51
60
|
|
|
61
|
+
Shorthand for `get(-1)`.
|
|
62
|
+
|
|
52
63
|
```js
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
const button = $$('button').last();
|
|
65
|
+
await button.click();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## count
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
Returns the number of elements matching the selector.
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
const count = await $$('button').count();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## getFirstVisible
|
|
77
|
+
|
|
78
|
+
Returns the first visible (displayed) element in the collection.
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
const visibleButton = $$('button').getFirstVisible();
|
|
82
|
+
await visibleButton.click();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## getAllVisible
|
|
86
|
+
|
|
87
|
+
Returns a new elements collection containing only visible elements.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const visibleButtons = $$('button').getAllVisible();
|
|
91
|
+
const visibleCount = await visibleButtons.count();
|
|
60
92
|
```
|
|
61
93
|
|
|
62
94
|
## each
|
|
63
95
|
|
|
96
|
+
Iterates over each element in the collection.
|
|
97
|
+
|
|
64
98
|
```js
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
await someButtons.each((someButton) => {
|
|
71
|
-
await someButton.click()
|
|
72
|
-
})
|
|
73
|
-
})()
|
|
99
|
+
const buttons = $$('button');
|
|
100
|
+
|
|
101
|
+
await buttons.each(async (button, index) => {
|
|
102
|
+
await button.click();
|
|
103
|
+
});
|
|
74
104
|
```
|
|
75
105
|
|
|
76
106
|
## map
|
|
77
107
|
|
|
108
|
+
Maps each element to a value.
|
|
109
|
+
|
|
78
110
|
```js
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const allButtonTexts = await someButtons.map((button) => {
|
|
85
|
-
return await someButton.getText()
|
|
86
|
-
})
|
|
87
|
-
})()
|
|
111
|
+
const buttons = $$('button');
|
|
112
|
+
|
|
113
|
+
const texts = await buttons.map(async (button) => {
|
|
114
|
+
return await button.getText();
|
|
115
|
+
});
|
|
88
116
|
```
|
|
89
117
|
|
|
90
118
|
## some
|
|
91
119
|
|
|
120
|
+
Returns `true` if the callback returns `true` for at least one element.
|
|
121
|
+
|
|
92
122
|
```js
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const isSomeButtonVisible = await someButtons.some((button) => {
|
|
99
|
-
return await someButton.isDisplayed()
|
|
100
|
-
})
|
|
101
|
-
})()
|
|
123
|
+
const buttons = $$('button');
|
|
124
|
+
|
|
125
|
+
const isSomeVisible = await buttons.some(async (button) => {
|
|
126
|
+
return await button.isDisplayed();
|
|
127
|
+
});
|
|
102
128
|
```
|
|
103
129
|
|
|
104
130
|
## every
|
|
105
131
|
|
|
132
|
+
Returns `true` if the callback returns `true` for every element.
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
const buttons = $$('button');
|
|
136
|
+
|
|
137
|
+
const allVisible = await buttons.every(async (button) => {
|
|
138
|
+
return await button.isDisplayed();
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## find
|
|
143
|
+
|
|
144
|
+
Finds the first element matching the callback condition.
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
const buttons = $$('button');
|
|
148
|
+
|
|
149
|
+
const submitBtn = await buttons.find(async (button) => {
|
|
150
|
+
return (await button.getText()) === 'Submit';
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await submitBtn.click();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## filter
|
|
157
|
+
|
|
158
|
+
Returns a new elements collection with elements matching the callback condition.
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
const buttons = $$('button');
|
|
162
|
+
|
|
163
|
+
const enabledButtons = buttons.filter(async (button) => {
|
|
164
|
+
return await button.isEnabled();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const count = await enabledButtons.count();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## getEngineElements
|
|
171
|
+
|
|
172
|
+
Returns the underlying native engine elements (Playwright `Locator[]` / Selenium `WebElement[]`).
|
|
173
|
+
|
|
106
174
|
```js
|
|
107
|
-
|
|
108
|
-
const {$$} = seleniumWD
|
|
109
|
-
const someButtons = $$('button');
|
|
110
|
-
|
|
111
|
-
;(async () => {
|
|
112
|
-
const isEveryButtonVisible = await someButtons.every((button) => {
|
|
113
|
-
return await someButton.isDisplayed()
|
|
114
|
-
})
|
|
115
|
-
})()
|
|
175
|
+
const nativeElements = await $$('button').getEngineElements();
|
|
116
176
|
```
|
package/docs/init.md
CHANGED
|
@@ -1,27 +1,81 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Engine setup
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Promod does not ship its own test runner or browser driver. It wraps [Playwright](https://www.npmjs.com/package/playwright) and [Selenium WebDriver](https://www.npmjs.com/package/selenium-webdriver) with a unified API.
|
|
4
|
+
|
|
5
|
+
- [Playwright setup](#playwright-setup)
|
|
6
|
+
- [Selenium WebDriver setup](#selenium-webdriver-setup)
|
|
7
|
+
- [Engine switcher](#engine-switcher)
|
|
8
|
+
- [Browser config translation](./config.md) — define settings once, translate to engine-specific config
|
|
9
|
+
|
|
10
|
+
## Playwright setup
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
const { chromium } = require('playwright');
|
|
14
|
+
const { playwrightWD } = require('promod');
|
|
15
|
+
const { browser, $, $$ } = playwrightWD;
|
|
16
|
+
|
|
17
|
+
async function setup() {
|
|
18
|
+
const launched = await chromium.launch({ headless: false });
|
|
19
|
+
browser.setClient({ driver: launched });
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`setClient` accepts:
|
|
24
|
+
|
|
25
|
+
| Parameter | Type | Description |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `driver` | `Browser` (Playwright) | Launched browser instance |
|
|
28
|
+
| `lauchNewInstance` | `() => Promise<Browser>` | Factory to create new browser instances for `runNewBrowser()` |
|
|
29
|
+
| `baseConfig` | `object` | Default context config (viewport, userAgent, isMobile) |
|
|
30
|
+
|
|
31
|
+
## Selenium WebDriver setup
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const { Browser, Builder } = require('selenium-webdriver');
|
|
35
|
+
require('chromedriver');
|
|
36
|
+
const { seleniumWD } = require('promod');
|
|
37
|
+
const { browser, $, $$ } = seleniumWD;
|
|
38
|
+
|
|
39
|
+
async function setup() {
|
|
40
|
+
const driver = await new Builder().forBrowser(Browser.CHROME).build();
|
|
41
|
+
browser.setClient({
|
|
42
|
+
driver,
|
|
43
|
+
lauchNewInstance: () => new Builder().forBrowser(Browser.CHROME).build(),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`setClient` accepts:
|
|
49
|
+
|
|
50
|
+
| Parameter | Type | Description |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| `driver` | `ThenableWebDriver` | Selenium WebDriver instance |
|
|
53
|
+
| `lauchNewInstance` | `() => Promise<ThenableWebDriver>` | Factory for `runNewBrowser()` |
|
|
54
|
+
|
|
55
|
+
## Engine switcher
|
|
56
|
+
|
|
57
|
+
A common pattern is to select the engine via an environment variable:
|
|
4
58
|
|
|
5
59
|
```js
|
|
6
60
|
const { chromium } = require('playwright');
|
|
7
61
|
const { Browser, Builder } = require('selenium-webdriver');
|
|
8
|
-
const {
|
|
62
|
+
const { playwrightWD, seleniumWD } = require('promod');
|
|
63
|
+
|
|
64
|
+
const { ENGINE } = process.env; // 'pw' or 'swd'
|
|
9
65
|
|
|
10
66
|
async function getEngine() {
|
|
11
67
|
if (ENGINE === 'pw') {
|
|
12
|
-
const
|
|
13
|
-
playwrightWD.browser.setClient({ driver:
|
|
14
|
-
|
|
15
|
-
return playwrightWD;
|
|
68
|
+
const launched = await chromium.launch({ headless: false });
|
|
69
|
+
playwrightWD.browser.setClient({ driver: launched });
|
|
70
|
+
return playwrightWD;
|
|
16
71
|
} else {
|
|
17
72
|
require('chromedriver');
|
|
18
|
-
const
|
|
73
|
+
const driver = await new Builder().forBrowser(Browser.CHROME).build();
|
|
19
74
|
seleniumWD.browser.setClient({
|
|
20
|
-
driver
|
|
21
|
-
lauchNewInstance:
|
|
75
|
+
driver,
|
|
76
|
+
lauchNewInstance: () => new Builder().forBrowser(Browser.CHROME).build(),
|
|
22
77
|
});
|
|
23
|
-
|
|
24
|
-
return seleniumWD
|
|
78
|
+
return seleniumWD;
|
|
25
79
|
}
|
|
26
80
|
}
|
|
27
81
|
|
package/oxlintrc.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxc/json-schema/npm/oxlint/configuration_schema.json",
|
|
3
|
+
"plugins": ["unicorn", "promise"],
|
|
4
|
+
"ignorePatterns": ["built", "playground.*"],
|
|
5
|
+
"rules": {
|
|
6
|
+
"no-console": "error",
|
|
7
|
+
"unicorn/no-null": "off",
|
|
8
|
+
"unicorn/explicit-length-check": "off",
|
|
9
|
+
"unicorn/prevent-abbreviations": "off",
|
|
10
|
+
"unicorn/prefer-node-protocol": "off",
|
|
11
|
+
"unicorn/import-style": "off",
|
|
12
|
+
"unicorn/no-this-assignment": "off",
|
|
13
|
+
"unicorn/no-array-for-each": "off",
|
|
14
|
+
"unicorn/no-array-reduce": "off",
|
|
15
|
+
"unicorn/filename-case": "off",
|
|
16
|
+
"unicorn/prefer-module": "off",
|
|
17
|
+
"unicorn/prefer-spread": "off",
|
|
18
|
+
"unicorn/consistent-destructuring": "off"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "promod",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Library for automation testing",
|
|
5
5
|
"bin": "./bin/promod_cli",
|
|
6
6
|
"main": "./built/cjs/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"test:swd": "ENGINE=swd mocha $(find specs -name '*.spec.*') --require ts-node/register --timeout 500000",
|
|
17
17
|
"test:units": "mocha $(find units -name '*.test.*') --require ts-node/register --timeout 500000",
|
|
18
18
|
"test:debug": "mocha ./specs/async.child.methods.spec.ts --require ts-node/register --timeout 300000",
|
|
19
|
-
"lint": "
|
|
19
|
+
"lint": "oxlint -c oxlintrc.json --tsconfig tsconfig.json .",
|
|
20
20
|
"tsc:cjs": "tsc -p tsconfig.json",
|
|
21
21
|
"tsc:esm": "tsc -p tsconfig.esm.json",
|
|
22
22
|
"tsc": "rm -rf ./built && npm run tsc:cjs && npm run tsc:esm"
|
|
@@ -35,11 +35,12 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/Simple-Automation-Testing/promod#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@types/selenium-webdriver": "^4.35.
|
|
38
|
+
"@types/selenium-webdriver": "^4.35.5",
|
|
39
|
+
"playwright-core": "^1.58.2",
|
|
39
40
|
"sat-compare": "^0.1.0",
|
|
40
|
-
"sat-utils": "^3.0
|
|
41
|
-
"sat-wait": "^0.1.
|
|
42
|
-
"
|
|
41
|
+
"sat-utils": "^3.2.0",
|
|
42
|
+
"sat-wait": "^0.1.6",
|
|
43
|
+
"selenium-webdriver": "^4.40.0"
|
|
43
44
|
},
|
|
44
45
|
"keywords": [
|
|
45
46
|
"promod",
|
|
@@ -52,18 +53,14 @@
|
|
|
52
53
|
"playwright mod"
|
|
53
54
|
],
|
|
54
55
|
"devDependencies": {
|
|
55
|
-
"@types/mocha": "^10.0.
|
|
56
|
-
"@typescript-eslint/eslint-plugin": "^8.7.0",
|
|
57
|
-
"@typescript-eslint/parser": "^8.7.0",
|
|
56
|
+
"@types/mocha": "^10.0.10",
|
|
58
57
|
"assertior": "^0.0.28",
|
|
59
|
-
"chromedriver": "^
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"prettier": "^3.3.3",
|
|
65
|
-
"selenium-webdriver": "^4.31.0",
|
|
58
|
+
"chromedriver": "^144.0.1",
|
|
59
|
+
"mocha": "^11.7.5",
|
|
60
|
+
"oxlint": "^1.43.0",
|
|
61
|
+
"playwright": "^1.58.2",
|
|
62
|
+
"prettier": "^3.8.1",
|
|
66
63
|
"ts-node": "^10.9.2",
|
|
67
|
-
"typescript": "^5.
|
|
64
|
+
"typescript": "^5.9.3"
|
|
68
65
|
}
|
|
69
|
-
}
|
|
66
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,19 +1,119 @@
|
|
|
1
|
+
# promod
|
|
2
|
+
|
|
1
3
|
<p align="center">
|
|
2
|
-
<
|
|
3
|
-
<img style="width:100%;" src="./docs/promod.png"/>
|
|
4
|
+
<img src="./docs/promod.png" alt="promod" width="200"/>
|
|
4
5
|
</p>
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
Browser automation library with a unified API over [Playwright](https://playwright.dev/) and [Selenium WebDriver](https://www.selenium.dev/documentation/webdriver/).
|
|
8
|
+
|
|
9
|
+
Promod provides a **protractor-like** lazy element interface — elements are not resolved until an action is performed on them.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install promod
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Promod requires a browser engine as a peer dependency:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# For Playwright
|
|
21
|
+
npm install playwright
|
|
22
|
+
|
|
23
|
+
# For Selenium WebDriver
|
|
24
|
+
npm install selenium-webdriver chromedriver
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
### Playwright
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const { chromium } = require('playwright');
|
|
33
|
+
const { playwrightWD } = require('promod');
|
|
34
|
+
const { browser, $, $$ } = playwrightWD;
|
|
35
|
+
|
|
36
|
+
async function main() {
|
|
37
|
+
const launched = await chromium.launch({ headless: false });
|
|
38
|
+
browser.setClient({ driver: launched });
|
|
39
|
+
|
|
40
|
+
await browser.get('https://example.com');
|
|
41
|
+
|
|
42
|
+
const heading = $('h1');
|
|
43
|
+
console.log(await heading.getText());
|
|
44
|
+
|
|
45
|
+
await browser.quitAll();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
main();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Selenium WebDriver
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const { Browser, Builder } = require('selenium-webdriver');
|
|
55
|
+
require('chromedriver');
|
|
56
|
+
const { seleniumWD } = require('promod');
|
|
57
|
+
const { browser, $, $$ } = seleniumWD;
|
|
58
|
+
|
|
59
|
+
async function main() {
|
|
60
|
+
const driver = await new Builder().forBrowser(Browser.CHROME).build();
|
|
61
|
+
browser.setClient({
|
|
62
|
+
driver,
|
|
63
|
+
lauchNewInstance: () => new Builder().forBrowser(Browser.CHROME).build(),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await browser.get('https://example.com');
|
|
67
|
+
|
|
68
|
+
const heading = $('h1');
|
|
69
|
+
console.log(await heading.getText());
|
|
70
|
+
|
|
71
|
+
await browser.quit();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
main();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## ESM / CommonJS
|
|
78
|
+
|
|
79
|
+
Promod ships dual builds. Bundlers and Node `import` will use ESM; `require()` will use CommonJS.
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
// ESM
|
|
83
|
+
import { playwrightWD, seleniumWD } from 'promod';
|
|
84
|
+
|
|
85
|
+
// CommonJS
|
|
86
|
+
const { playwrightWD, seleniumWD } = require('promod');
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Selector strategies
|
|
90
|
+
|
|
91
|
+
All examples work identically with both `playwrightWD` and `seleniumWD`.
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
// CSS (default)
|
|
95
|
+
const el = $('.my-class #id a[href*="link"]');
|
|
96
|
+
|
|
97
|
+
// XPath
|
|
98
|
+
const el = $('xpath=.//div[@data-test="id"]/span');
|
|
99
|
+
|
|
100
|
+
// JavaScript function
|
|
101
|
+
const el = $(() => document.querySelector('div > span'));
|
|
102
|
+
|
|
103
|
+
// Custom selector (query + text filter)
|
|
104
|
+
const el = $({ query: 'button', text: 'Submit' });
|
|
105
|
+
const el = $({ query: 'button', rg: 'Sub.*' }); // regex filter
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## API
|
|
109
|
+
|
|
110
|
+
| Topic | Link |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Engine setup | [docs/init.md](./docs/init.md) |
|
|
113
|
+
| Browser (client) | [docs/client.md](./docs/client.md) |
|
|
114
|
+
| Element (`$`) | [docs/element.md](./docs/element.md) |
|
|
115
|
+
| Elements (`$$`) | [docs/elements.md](./docs/elements.md) |
|
|
14
116
|
|
|
15
|
-
##
|
|
117
|
+
## License
|
|
16
118
|
|
|
17
|
-
|
|
18
|
-
- [x] Add documentation - done
|
|
19
|
-
- [ ] Add logger - in progress
|
|
119
|
+
MIT
|
package/tsconfig.esm.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"module": "
|
|
3
|
+
"module": "ESNext",
|
|
4
4
|
"target": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
5
6
|
"sourceMap": true,
|
|
6
7
|
"outDir": "built/esm",
|
|
7
8
|
"declaration": true,
|
|
8
9
|
"experimentalDecorators": true,
|
|
9
|
-
"allowJs": true
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"strictPropertyInitialization": false,
|
|
13
|
+
"strictNullChecks": false
|
|
10
14
|
},
|
|
11
15
|
"include": [
|
|
12
16
|
"lib"
|
package/tsconfig.json
CHANGED