browser-commander 0.8.0 → 0.9.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/.prettierignore +1 -0
- package/CHANGELOG.md +14 -0
- package/README.md +75 -0
- package/eslint.config.js +1 -0
- package/examples/browser-commander-tests.example.js +30 -0
- package/jsdoc.json +11 -0
- package/package.json +7 -3
- package/src/bindings.js +2 -0
- package/src/browser/navigation.js +1 -1
- package/src/index.js +4 -1
- package/src/interactions/click.js +3 -3
- package/src/interactions/fill.js +2 -2
- package/src/tests/index.js +709 -0
- package/tests/unit/bindings.test.js +8 -0
- package/tests/unit/factory.test.js +5 -0
- package/tests/unit/tests/index.test.js +368 -0
package/.prettierignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 21c63ac: Add the `browser-commander/tests` export with `test-anywhere`-based browser
|
|
8
|
+
test helpers for Playwright and Puppeteer, duration-aware ordering, balanced
|
|
9
|
+
shard planning, retries, timeouts, and failure artifacts.
|
|
10
|
+
|
|
11
|
+
## 0.8.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- ffc59e6: Add generated JSDoc API documentation support for the JavaScript package.
|
|
16
|
+
|
|
3
17
|
## 0.8.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -18,6 +18,16 @@ npm install playwright
|
|
|
18
18
|
npm install puppeteer
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## Documentation
|
|
22
|
+
|
|
23
|
+
Generate the JavaScript API reference locally with:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm run docs:api
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The repository Documentation workflow also combines this JSDoc output with Rust `cargo doc` output for GitHub Pages publishing from `main`.
|
|
30
|
+
|
|
21
31
|
## Core Concept: Page State Machine
|
|
22
32
|
|
|
23
33
|
Browser Commander manages the browser as a state machine with two states:
|
|
@@ -77,6 +87,53 @@ await commander.destroy();
|
|
|
77
87
|
await browser.close();
|
|
78
88
|
```
|
|
79
89
|
|
|
90
|
+
## Browser Commander Tests
|
|
91
|
+
|
|
92
|
+
`browser-commander/tests` adds browser fixtures and scheduling helpers on top of
|
|
93
|
+
[`test-anywhere`](https://github.com/link-foundation/test-anywhere). It keeps
|
|
94
|
+
tests portable across Node.js, Bun, and Deno while running the same browser
|
|
95
|
+
scenario against Playwright and Puppeteer.
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import { assert, browserTest } from 'browser-commander/tests';
|
|
99
|
+
|
|
100
|
+
browserTest(
|
|
101
|
+
'loads example.com',
|
|
102
|
+
async ({ commander, engine }) => {
|
|
103
|
+
await commander.goto({
|
|
104
|
+
url: 'https://example.com',
|
|
105
|
+
waitForNetworkIdle: false,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const heading = await commander.textContent({ selector: 'h1' });
|
|
109
|
+
assert.ok(heading.includes('Example Domain'), `${engine} should work`);
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
engines: ['playwright', 'puppeteer'],
|
|
113
|
+
launchOptions: { headless: true },
|
|
114
|
+
retries: 1,
|
|
115
|
+
timeoutMs: 60000,
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The test helpers provide:
|
|
121
|
+
|
|
122
|
+
- `browserTest()` and `defineBrowserTests()` for Playwright/Puppeteer matrices.
|
|
123
|
+
- Automatic fixture cleanup with `commander.destroy()` and `browser.close()`.
|
|
124
|
+
- `retries`, per-test `timeoutMs`, and failure artifacts under
|
|
125
|
+
`test-results/browser-commander` by default.
|
|
126
|
+
- Historical duration tracking in `tests/.browser-commander-test-timings.json`
|
|
127
|
+
when a `tests` directory exists.
|
|
128
|
+
- Longest-first ordering and balanced shard planning. Set
|
|
129
|
+
`BROWSER_COMMANDER_TEST_SHARD=1/3` to select a shard.
|
|
130
|
+
- Re-exported `test-anywhere` APIs such as `test`, `describe`, `it`, `assert`,
|
|
131
|
+
`expect`, and lifecycle hooks.
|
|
132
|
+
|
|
133
|
+
See
|
|
134
|
+
[`examples/browser-commander-tests.example.js`](examples/browser-commander-tests.example.js)
|
|
135
|
+
for a runnable example.
|
|
136
|
+
|
|
80
137
|
## URL Condition Helpers
|
|
81
138
|
|
|
82
139
|
The `makeUrlCondition` helper makes it easy to create URL matching conditions:
|
|
@@ -290,6 +347,24 @@ await commander.fillTextArea({
|
|
|
290
347
|
});
|
|
291
348
|
```
|
|
292
349
|
|
|
350
|
+
### Keyboard Interactions
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
import { pressKey, typeText, keyDown, keyUp } from 'browser-commander';
|
|
354
|
+
|
|
355
|
+
// Press a single key
|
|
356
|
+
await pressKey({ page, engine: 'playwright', key: 'Escape' });
|
|
357
|
+
await pressKey({ page, engine: 'playwright', key: 'Enter' });
|
|
358
|
+
await pressKey({ page, engine: 'playwright', key: 'Tab' });
|
|
359
|
+
|
|
360
|
+
// Type text
|
|
361
|
+
await typeText({ page, engine: 'playwright', text: 'Hello World' });
|
|
362
|
+
|
|
363
|
+
// Hold and release modifier keys
|
|
364
|
+
await keyDown({ page, engine: 'playwright', key: 'Control' });
|
|
365
|
+
await keyUp({ page, engine: 'playwright', key: 'Control' });
|
|
366
|
+
```
|
|
367
|
+
|
|
293
368
|
### commander.destroy()
|
|
294
369
|
|
|
295
370
|
```javascript
|
package/eslint.config.js
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { assert, browserTest } from '../src/tests/index.js';
|
|
2
|
+
|
|
3
|
+
const engines = process.env.BROWSER_COMMANDER_TEST_ENGINE
|
|
4
|
+
? process.env.BROWSER_COMMANDER_TEST_ENGINE.split(',')
|
|
5
|
+
: undefined;
|
|
6
|
+
|
|
7
|
+
browserTest(
|
|
8
|
+
'loads example.com',
|
|
9
|
+
async ({ commander, engine, testInfo }) => {
|
|
10
|
+
await commander.goto({
|
|
11
|
+
url: process.env.TEST_URL || 'https://example.com',
|
|
12
|
+
waitForNetworkIdle: false,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const heading = await commander.textContent({ selector: 'h1' });
|
|
16
|
+
assert.ok(
|
|
17
|
+
heading.includes('Example Domain'),
|
|
18
|
+
`${testInfo.name} should read the heading with ${engine}`
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
engines,
|
|
23
|
+
launchOptions: {
|
|
24
|
+
headless: process.env.HEADLESS !== 'false',
|
|
25
|
+
},
|
|
26
|
+
retries: process.env.CI ? 1 : 0,
|
|
27
|
+
timeoutMs: 60000,
|
|
28
|
+
artifactsDir: 'test-results/browser-commander-example',
|
|
29
|
+
}
|
|
30
|
+
);
|
package/jsdoc.json
ADDED
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-commander",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Universal browser automation library that supports both Playwright and Puppeteer with a unified API",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": "./src/index.js"
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./tests": "./src/tests/index.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"test": "node --test --test-reporter spec tests/unit/",
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
"lint:fix": "eslint . --fix",
|
|
20
21
|
"format": "prettier --write .",
|
|
21
22
|
"format:check": "prettier --check .",
|
|
23
|
+
"docs:api": "jsdoc -c jsdoc.json",
|
|
22
24
|
"check:duplication": "jscpd .",
|
|
23
25
|
"check": "npm run lint && npm run format:check && npm run check:duplication",
|
|
24
26
|
"prepare": "husky || true",
|
|
@@ -61,7 +63,8 @@
|
|
|
61
63
|
}
|
|
62
64
|
},
|
|
63
65
|
"dependencies": {
|
|
64
|
-
"log-lazy": "^1.0.4"
|
|
66
|
+
"log-lazy": "^1.0.4",
|
|
67
|
+
"test-anywhere": "^0.9.1"
|
|
65
68
|
},
|
|
66
69
|
"devDependencies": {
|
|
67
70
|
"@changesets/cli": "^2.29.7",
|
|
@@ -69,6 +72,7 @@
|
|
|
69
72
|
"eslint-config-prettier": "^10.1.8",
|
|
70
73
|
"eslint-plugin-prettier": "^5.5.4",
|
|
71
74
|
"husky": "^9.1.7",
|
|
75
|
+
"jsdoc": "^4.0.4",
|
|
72
76
|
"jscpd": "^4.0.5",
|
|
73
77
|
"lint-staged": "^16.2.6",
|
|
74
78
|
"playwright": "^1.56.1",
|
package/src/bindings.js
CHANGED
|
@@ -283,7 +283,9 @@ export function createBoundFunctions(options = {}) {
|
|
|
283
283
|
// Main API functions
|
|
284
284
|
wait: waitBound,
|
|
285
285
|
emulateMedia: emulateMediaBound,
|
|
286
|
+
fill: fillTextAreaWrapped,
|
|
286
287
|
fillTextArea: fillTextAreaWrapped,
|
|
288
|
+
click: clickButtonWrapped,
|
|
287
289
|
clickButton: clickButtonWrapped,
|
|
288
290
|
evaluate: evaluateBound,
|
|
289
291
|
safeEvaluate: safeEvaluateBound,
|
|
@@ -220,7 +220,7 @@ export async function waitForUrlStabilization(options = {}) {
|
|
|
220
220
|
* @param {boolean} options.verify - Whether to verify the navigation (default: true)
|
|
221
221
|
* @param {Function} options.verifyFn - Custom verification function (optional)
|
|
222
222
|
* @param {number} options.verificationTimeout - Verification timeout in ms (default: TIMING.VERIFICATION_TIMEOUT)
|
|
223
|
-
* @returns {Promise<
|
|
223
|
+
* @returns {Promise<Object>} Navigation result.
|
|
224
224
|
*/
|
|
225
225
|
export async function goto(options = {}) {
|
|
226
226
|
const {
|
package/src/index.js
CHANGED
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
// Export the factory function
|
|
14
|
-
export {
|
|
14
|
+
export {
|
|
15
|
+
makeBrowserCommander,
|
|
16
|
+
makeBrowserCommander as createCommander,
|
|
17
|
+
} from './factory.js';
|
|
15
18
|
|
|
16
19
|
// Re-export all public APIs from exports module
|
|
17
20
|
export * from './exports.js';
|
|
@@ -173,7 +173,7 @@ export async function verifyClick(options = {}) {
|
|
|
173
173
|
* @param {boolean} options.verify - Whether to verify the click operation (default: true)
|
|
174
174
|
* @param {Function} options.verifyFn - Custom verification function (optional)
|
|
175
175
|
* @param {Object} options.adapter - Engine adapter (optional, will be created if not provided)
|
|
176
|
-
* @returns {Promise<
|
|
176
|
+
* @returns {Promise<Object>} Click result.
|
|
177
177
|
*/
|
|
178
178
|
export async function clickElement(options = {}) {
|
|
179
179
|
const {
|
|
@@ -352,7 +352,7 @@ async function prepareElement(options = {}) {
|
|
|
352
352
|
* @param {boolean} options.noAutoScroll - Prevent Playwright's automatic scrolling
|
|
353
353
|
* @param {boolean} options.verify - Whether to verify the click operation
|
|
354
354
|
* @param {Function} options.verifyFn - Custom verification function (optional)
|
|
355
|
-
* @returns {Promise<
|
|
355
|
+
* @returns {Promise<Object>} Click result.
|
|
356
356
|
*/
|
|
357
357
|
async function executeClick(options = {}) {
|
|
358
358
|
const {
|
|
@@ -567,7 +567,7 @@ async function handleNavigationAfterClick(options = {}) {
|
|
|
567
567
|
* @param {number} options.timeout - Timeout in ms (default: TIMING.DEFAULT_TIMEOUT)
|
|
568
568
|
* @param {boolean} options.verify - Whether to verify the click operation (default: true)
|
|
569
569
|
* @param {Function} options.verifyFn - Custom verification function (optional)
|
|
570
|
-
* @returns {Promise<
|
|
570
|
+
* @returns {Promise<Object>} Click result.
|
|
571
571
|
* - clicked: true if click was performed
|
|
572
572
|
* - navigated: true if click caused navigation
|
|
573
573
|
* - verified: true if click was verified (navigation counts as verification)
|
package/src/interactions/fill.js
CHANGED
|
@@ -146,7 +146,7 @@ export async function checkIfElementEmpty(options = {}) {
|
|
|
146
146
|
* @param {number} options.verificationTimeout - Verification timeout in ms (default: TIMING.VERIFICATION_TIMEOUT)
|
|
147
147
|
* @param {Function} options.log - Logger instance (optional)
|
|
148
148
|
* @param {Object} options.adapter - Engine adapter (optional, will be created if not provided)
|
|
149
|
-
* @returns {Promise<
|
|
149
|
+
* @returns {Promise<Object>} Fill result.
|
|
150
150
|
*/
|
|
151
151
|
export async function performFill(options = {}) {
|
|
152
152
|
const {
|
|
@@ -240,7 +240,7 @@ export async function performFill(options = {}) {
|
|
|
240
240
|
* @param {boolean} options.verify - Whether to verify the fill operation (default: true)
|
|
241
241
|
* @param {Function} options.verifyFn - Custom verification function (optional, uses defaultFillVerification if not provided)
|
|
242
242
|
* @param {number} options.verificationTimeout - Verification timeout in ms (default: TIMING.VERIFICATION_TIMEOUT)
|
|
243
|
-
* @returns {Promise<
|
|
243
|
+
* @returns {Promise<Object>} Fill result.
|
|
244
244
|
* - filled: true if fill operation was attempted
|
|
245
245
|
* - verified: true if fill was verified successfully (only meaningful if filled is true)
|
|
246
246
|
* - skipped: true if element already had content and checkEmpty was true
|