browser-commander 0.8.1 → 0.9.1
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/CHANGELOG.md +14 -0
- package/README.md +47 -0
- package/eslint.config.js +3 -3
- package/examples/browser-commander-tests.example.js +30 -0
- package/package.json +11 -9
- package/scripts/clean-npm-config.mjs +39 -0
- package/scripts/npm-registry.mjs +31 -0
- package/scripts/publish-to-npm.mjs +12 -13
- package/scripts/run-tests.mjs +192 -0
- package/scripts/setup-npm.mjs +1 -1
- package/src/bindings.js +2 -0
- package/src/browser/navigation.js +2 -3
- package/src/core/dialog-manager.js +1 -1
- package/src/core/engine-adapter.js +46 -40
- package/src/core/navigation-manager.js +1 -1
- package/src/core/network-tracker.js +1 -2
- package/src/core/page-session.js +5 -5
- package/src/core/page-trigger-manager.js +4 -2
- package/src/elements/selectors.js +3 -3
- package/src/high-level/universal-logic.js +0 -1
- package/src/index.js +4 -1
- package/src/interactions/click.js +1 -1
- 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/scripts/npm-release-helpers.test.js +138 -0
- package/tests/unit/tests/index.test.js +368 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- cbd4fe1: Remove CI warning noise from workflow actions, release logging, and lint output.
|
|
8
|
+
|
|
9
|
+
## 0.9.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 21c63ac: Add the `browser-commander/tests` export with `test-anywhere`-based browser
|
|
14
|
+
test helpers for Playwright and Puppeteer, duration-aware ordering, balanced
|
|
15
|
+
shard planning, retries, timeouts, and failure artifacts.
|
|
16
|
+
|
|
3
17
|
## 0.8.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -87,6 +87,53 @@ await commander.destroy();
|
|
|
87
87
|
await browser.close();
|
|
88
88
|
```
|
|
89
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
|
+
|
|
90
137
|
## URL Condition Helpers
|
|
91
138
|
|
|
92
139
|
The `makeUrlCondition` helper makes it easy to create URL matching conditions:
|
package/eslint.config.js
CHANGED
|
@@ -88,13 +88,13 @@ export default [
|
|
|
88
88
|
// Comments and documentation
|
|
89
89
|
'spaced-comment': ['error', 'always', { markers: ['/'] }],
|
|
90
90
|
|
|
91
|
-
// Complexity rules -
|
|
92
|
-
complexity: ['warn',
|
|
91
|
+
// Complexity rules - tuned for browser-automation orchestration code
|
|
92
|
+
complexity: ['warn', 30], // Cyclomatic complexity guardrail for unusually branchy functions
|
|
93
93
|
'max-depth': ['warn', 5], // Maximum nesting depth - slightly more lenient than strict 4
|
|
94
94
|
'max-lines-per-function': [
|
|
95
95
|
'warn',
|
|
96
96
|
{
|
|
97
|
-
max:
|
|
97
|
+
max: 300, // Allows orchestration functions while still catching very large functions
|
|
98
98
|
skipBlankLines: true,
|
|
99
99
|
skipComments: true,
|
|
100
100
|
},
|
|
@@ -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/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-commander",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
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
|
-
"test": "node
|
|
12
|
-
"test:unit": "node
|
|
13
|
-
"test:coverage": "node
|
|
14
|
-
"test:e2e": "RUN_E2E=true
|
|
15
|
-
"test:e2e:playwright": "RUN_E2E=true
|
|
16
|
-
"test:e2e:puppeteer": "RUN_E2E=true
|
|
12
|
+
"test": "node scripts/run-tests.mjs --reporter spec tests/unit",
|
|
13
|
+
"test:unit": "node scripts/run-tests.mjs --reporter spec tests/unit",
|
|
14
|
+
"test:coverage": "node scripts/run-tests.mjs --coverage tests/unit",
|
|
15
|
+
"test:e2e": "node scripts/run-tests.mjs --env RUN_E2E=true tests/e2e",
|
|
16
|
+
"test:e2e:playwright": "node scripts/run-tests.mjs --env RUN_E2E=true tests/e2e/playwright.e2e.test.js",
|
|
17
|
+
"test:e2e:puppeteer": "node scripts/run-tests.mjs --env RUN_E2E=true tests/e2e/puppeteer.e2e.test.js",
|
|
17
18
|
"test:all": "npm run test:unit && npm run test:e2e",
|
|
18
19
|
"lint": "eslint .",
|
|
19
20
|
"lint:fix": "eslint . --fix",
|
|
@@ -62,7 +63,8 @@
|
|
|
62
63
|
}
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
|
-
"log-lazy": "^1.0.4"
|
|
66
|
+
"log-lazy": "^1.0.4",
|
|
67
|
+
"test-anywhere": "^0.9.1"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|
|
68
70
|
"@changesets/cli": "^2.29.7",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
|
|
6
|
+
export function removeDeprecatedAlwaysAuth(configPath) {
|
|
7
|
+
if (!configPath || !existsSync(configPath)) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const config = readFileSync(configPath, 'utf8');
|
|
12
|
+
const lines = config.split(/\r?\n/);
|
|
13
|
+
const filteredLines = lines.filter(
|
|
14
|
+
(line) => !/^\s*always-auth\s*=/.test(line)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
if (filteredLines.length === lines.length) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
writeFileSync(configPath, filteredLines.join('\n'));
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function main() {
|
|
26
|
+
const removed = removeDeprecatedAlwaysAuth(process.env.NPM_CONFIG_USERCONFIG);
|
|
27
|
+
if (removed) {
|
|
28
|
+
console.log('Removed deprecated always-auth from npm user config.');
|
|
29
|
+
} else {
|
|
30
|
+
console.log('No deprecated npm always-auth config found.');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
process.argv[1] &&
|
|
36
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
37
|
+
) {
|
|
38
|
+
main();
|
|
39
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function formatRegistryPackagePath(packageName) {
|
|
2
|
+
return encodeURIComponent(packageName);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export async function isVersionPublished(
|
|
6
|
+
packageName,
|
|
7
|
+
version,
|
|
8
|
+
fetchFn = fetch
|
|
9
|
+
) {
|
|
10
|
+
const packagePath = formatRegistryPackagePath(packageName);
|
|
11
|
+
const versionPath = encodeURIComponent(version);
|
|
12
|
+
const response = await fetchFn(
|
|
13
|
+
`https://registry.npmjs.org/${packagePath}/${versionPath}`,
|
|
14
|
+
{
|
|
15
|
+
headers: { accept: 'application/json' },
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
if (response.status === 404) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Failed to check npm registry for ${packageName}@${version}: ${response.status} ${response.statusText}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const metadata = await response.json();
|
|
30
|
+
return metadata?.version === version;
|
|
31
|
+
}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import { readFileSync, appendFileSync } from 'fs';
|
|
15
15
|
|
|
16
|
+
import { isVersionPublished } from './npm-registry.mjs';
|
|
17
|
+
|
|
16
18
|
const PACKAGE_NAME = 'browser-commander';
|
|
17
19
|
|
|
18
20
|
// Load use-m dynamically
|
|
@@ -74,26 +76,23 @@ async function main() {
|
|
|
74
76
|
console.log(
|
|
75
77
|
`Checking if version ${currentVersion} is already published...`
|
|
76
78
|
);
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Exit code 0 means version exists, non-zero means version not found
|
|
84
|
-
if (checkResult.code === 0) {
|
|
79
|
+
const versionIsPublished = await isVersionPublished(
|
|
80
|
+
PACKAGE_NAME,
|
|
81
|
+
currentVersion
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (versionIsPublished) {
|
|
85
85
|
console.log(`Version ${currentVersion} is already published to npm`);
|
|
86
86
|
setOutput('published', 'true');
|
|
87
87
|
setOutput('published_version', currentVersion);
|
|
88
88
|
setOutput('already_published', 'true');
|
|
89
89
|
return;
|
|
90
|
-
} else {
|
|
91
|
-
// Version not found on npm (E404), proceed with publish
|
|
92
|
-
console.log(
|
|
93
|
-
`Version ${currentVersion} not found on npm, proceeding with publish...`
|
|
94
|
-
);
|
|
95
90
|
}
|
|
96
91
|
|
|
92
|
+
console.log(
|
|
93
|
+
`Version ${currentVersion} not found on npm, proceeding with publish...`
|
|
94
|
+
);
|
|
95
|
+
|
|
97
96
|
// Publish to npm using OIDC trusted publishing with retry logic
|
|
98
97
|
for (let i = 1; i <= MAX_RETRIES; i++) {
|
|
99
98
|
console.log(`Publish attempt ${i} of ${MAX_RETRIES}...`);
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { resolve, relative, sep } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
const TEST_FILE_PATTERN = /\.test\.[cm]?js$/u;
|
|
7
|
+
|
|
8
|
+
function readOptionValue(argv, index, optionName) {
|
|
9
|
+
const value = argv[index + 1];
|
|
10
|
+
|
|
11
|
+
if (!value || value.startsWith('--')) {
|
|
12
|
+
throw new Error(`${optionName} requires a value`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function parseEnvAssignment(assignment) {
|
|
19
|
+
const separatorIndex = assignment.indexOf('=');
|
|
20
|
+
|
|
21
|
+
if (separatorIndex <= 0) {
|
|
22
|
+
throw new Error(`Invalid environment override: ${assignment}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
name: assignment.slice(0, separatorIndex),
|
|
27
|
+
value: assignment.slice(separatorIndex + 1),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function parseTestRunnerArgs(argv) {
|
|
32
|
+
const options = {
|
|
33
|
+
coverage: false,
|
|
34
|
+
env: {},
|
|
35
|
+
reporter: null,
|
|
36
|
+
targets: [],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
40
|
+
const arg = argv[index];
|
|
41
|
+
|
|
42
|
+
if (arg === '--coverage') {
|
|
43
|
+
options.coverage = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (arg === '--reporter') {
|
|
48
|
+
options.reporter = readOptionValue(argv, index, '--reporter');
|
|
49
|
+
index += 1;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (arg === '--env') {
|
|
54
|
+
const { name, value } = parseEnvAssignment(
|
|
55
|
+
readOptionValue(argv, index, '--env')
|
|
56
|
+
);
|
|
57
|
+
options.env[name] = value;
|
|
58
|
+
index += 1;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (arg.startsWith('--env=')) {
|
|
63
|
+
const { name, value } = parseEnvAssignment(arg.slice('--env='.length));
|
|
64
|
+
options.env[name] = value;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
options.targets.push(arg);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (options.targets.length === 0) {
|
|
72
|
+
throw new Error('At least one test file or directory is required');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return options;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeForSort(filePath) {
|
|
79
|
+
return filePath.split(sep).join('/');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isTestFile(filePath) {
|
|
83
|
+
return TEST_FILE_PATTERN.test(filePath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function listFilesRecursively(directory) {
|
|
87
|
+
const entries = readdirSync(directory, { withFileTypes: true });
|
|
88
|
+
const files = [];
|
|
89
|
+
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
const entryPath = resolve(directory, entry.name);
|
|
92
|
+
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
files.push(...listFilesRecursively(entryPath));
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (entry.isFile() && isTestFile(entryPath)) {
|
|
99
|
+
files.push(entryPath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return files;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function resolveTestFiles(targets, cwd = process.cwd()) {
|
|
107
|
+
const files = [];
|
|
108
|
+
|
|
109
|
+
for (const target of targets) {
|
|
110
|
+
const absoluteTarget = resolve(cwd, target);
|
|
111
|
+
|
|
112
|
+
if (!existsSync(absoluteTarget)) {
|
|
113
|
+
throw new Error(`Test target does not exist: ${target}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const targetStats = statSync(absoluteTarget);
|
|
117
|
+
|
|
118
|
+
if (targetStats.isDirectory()) {
|
|
119
|
+
files.push(...listFilesRecursively(absoluteTarget));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (targetStats.isFile() && isTestFile(absoluteTarget)) {
|
|
124
|
+
files.push(absoluteTarget);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const uniqueFiles = [...new Set(files)];
|
|
129
|
+
uniqueFiles.sort((left, right) =>
|
|
130
|
+
normalizeForSort(left).localeCompare(normalizeForSort(right))
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
if (uniqueFiles.length === 0) {
|
|
134
|
+
throw new Error(`No test files found in: ${targets.join(', ')}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return uniqueFiles.map((file) => relative(cwd, file));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function buildNodeTestArgs(options, testFiles) {
|
|
141
|
+
const args = ['--test'];
|
|
142
|
+
|
|
143
|
+
if (options.coverage) {
|
|
144
|
+
args.push('--experimental-test-coverage');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (options.reporter) {
|
|
148
|
+
args.push('--test-reporter', options.reporter);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
args.push(...testFiles);
|
|
152
|
+
return args;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function runNodeTests(options, testFiles) {
|
|
156
|
+
const result = spawnSync(
|
|
157
|
+
process.execPath,
|
|
158
|
+
buildNodeTestArgs(options, testFiles),
|
|
159
|
+
{
|
|
160
|
+
env: { ...process.env, ...options.env },
|
|
161
|
+
stdio: 'inherit',
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
if (result.error) {
|
|
166
|
+
throw result.error;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (result.signal) {
|
|
170
|
+
throw new Error(`Node test runner terminated by signal ${result.signal}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result.status ?? 1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function main(argv = process.argv.slice(2)) {
|
|
177
|
+
const options = parseTestRunnerArgs(argv);
|
|
178
|
+
const testFiles = resolveTestFiles(options.targets);
|
|
179
|
+
return runNodeTests(options, testFiles);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (
|
|
183
|
+
process.argv[1] &&
|
|
184
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
185
|
+
) {
|
|
186
|
+
try {
|
|
187
|
+
process.exitCode = main();
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error(error.message);
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
package/scripts/setup-npm.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Update npm for OIDC trusted publishing
|
|
5
5
|
* npm trusted publishing requires npm >= 11.5.1
|
|
6
|
-
*
|
|
6
|
+
* Keep the runner npm version current enough for OIDC publishing
|
|
7
7
|
*
|
|
8
8
|
* Uses link-foundation libraries:
|
|
9
9
|
* - use-m: Dynamic package loading without package.json dependencies
|
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,
|
|
@@ -25,7 +25,7 @@ export async function defaultNavigationVerification(options = {}) {
|
|
|
25
25
|
const { page, expectedUrl, startUrl } = options;
|
|
26
26
|
|
|
27
27
|
try {
|
|
28
|
-
const actualUrl = page.url();
|
|
28
|
+
const actualUrl = await Promise.resolve(page.url());
|
|
29
29
|
|
|
30
30
|
// If expected URL is provided, verify it matches
|
|
31
31
|
if (expectedUrl) {
|
|
@@ -232,7 +232,7 @@ export async function goto(options = {}) {
|
|
|
232
232
|
waitUntil = 'domcontentloaded',
|
|
233
233
|
waitForStableUrlBefore = true,
|
|
234
234
|
waitForStableUrlAfter = true,
|
|
235
|
-
waitForNetworkIdle = true,
|
|
235
|
+
waitForNetworkIdle: _waitForNetworkIdle = true,
|
|
236
236
|
stableChecks = 3,
|
|
237
237
|
checkInterval = 1000,
|
|
238
238
|
timeout = 240000,
|
|
@@ -395,7 +395,6 @@ export async function waitForNavigation(options = {}) {
|
|
|
395
395
|
*/
|
|
396
396
|
export async function waitForPageReady(options = {}) {
|
|
397
397
|
const {
|
|
398
|
-
page,
|
|
399
398
|
navigationManager,
|
|
400
399
|
networkTracker,
|
|
401
400
|
log,
|