browser-commander 0.3.0 → 0.4.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/CHANGELOG.md +22 -0
- package/README.md +15 -0
- package/package.json +1 -1
- package/src/browser/launcher.js +7 -2
- package/tests/unit/browser/launcher.test.js +126 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5af2479: Add support for custom Chrome args in launchBrowser
|
|
8
|
+
|
|
9
|
+
Adds a new `args` option to the `launchBrowser` function that allows passing custom Chrome arguments to append to the default `CHROME_ARGS`. This is useful for headless server environments (Docker, CI/CD) that require additional flags like `--no-sandbox`, `--disable-setuid-sandbox`, or `--disable-dev-shm-usage`.
|
|
10
|
+
|
|
11
|
+
Usage example:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { launchBrowser } from 'browser-commander';
|
|
15
|
+
|
|
16
|
+
const { browser, page } = await launchBrowser({
|
|
17
|
+
engine: 'puppeteer',
|
|
18
|
+
headless: true,
|
|
19
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Fixes #11
|
|
24
|
+
|
|
3
25
|
## 0.3.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -191,6 +191,21 @@ commander.pageTrigger({
|
|
|
191
191
|
|
|
192
192
|
## API Reference
|
|
193
193
|
|
|
194
|
+
### launchBrowser(options)
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
const { browser, page } = await launchBrowser({
|
|
198
|
+
engine: 'playwright', // 'playwright' or 'puppeteer'
|
|
199
|
+
headless: false, // Run in headless mode
|
|
200
|
+
userDataDir: '~/.hh-apply/playwright-data', // Browser profile directory
|
|
201
|
+
slowMo: 150, // Slow down operations (ms)
|
|
202
|
+
verbose: false, // Enable debug logging
|
|
203
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'], // Custom Chrome args to append
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The `args` option allows passing custom Chrome arguments, which is useful for headless server environments (Docker, CI/CD) that require flags like `--no-sandbox`.
|
|
208
|
+
|
|
194
209
|
### makeBrowserCommander(options)
|
|
195
210
|
|
|
196
211
|
```javascript
|
package/package.json
CHANGED
package/src/browser/launcher.js
CHANGED
|
@@ -11,6 +11,7 @@ import { disableTranslateInPreferences } from '../core/preferences.js';
|
|
|
11
11
|
* @param {boolean} options.headless - Run in headless mode (default: false)
|
|
12
12
|
* @param {number} options.slowMo - Slow down operations by ms (default: 150 for Playwright, 0 for Puppeteer)
|
|
13
13
|
* @param {boolean} options.verbose - Enable verbose logging (default: false)
|
|
14
|
+
* @param {string[]} options.args - Custom Chrome arguments to append to the default CHROME_ARGS
|
|
14
15
|
* @returns {Promise<Object>} - Object with browser and page
|
|
15
16
|
*/
|
|
16
17
|
export async function launchBrowser(options = {}) {
|
|
@@ -20,8 +21,12 @@ export async function launchBrowser(options = {}) {
|
|
|
20
21
|
headless = false,
|
|
21
22
|
slowMo = engine === 'playwright' ? 150 : 0,
|
|
22
23
|
verbose = false,
|
|
24
|
+
args = [],
|
|
23
25
|
} = options;
|
|
24
26
|
|
|
27
|
+
// Combine default CHROME_ARGS with custom args
|
|
28
|
+
const chromeArgs = [...CHROME_ARGS, ...args];
|
|
29
|
+
|
|
25
30
|
if (!['playwright', 'puppeteer'].includes(engine)) {
|
|
26
31
|
throw new Error(
|
|
27
32
|
`Invalid engine: ${engine}. Expected 'playwright' or 'puppeteer'`
|
|
@@ -50,7 +55,7 @@ export async function launchBrowser(options = {}) {
|
|
|
50
55
|
slowMo,
|
|
51
56
|
chromiumSandbox: true,
|
|
52
57
|
viewport: null,
|
|
53
|
-
args:
|
|
58
|
+
args: chromeArgs,
|
|
54
59
|
ignoreDefaultArgs: ['--enable-automation'],
|
|
55
60
|
});
|
|
56
61
|
page = browser.pages()[0];
|
|
@@ -59,7 +64,7 @@ export async function launchBrowser(options = {}) {
|
|
|
59
64
|
browser = await puppeteer.default.launch({
|
|
60
65
|
headless,
|
|
61
66
|
defaultViewport: null,
|
|
62
|
-
args: ['--start-maximized', ...
|
|
67
|
+
args: ['--start-maximized', ...chromeArgs],
|
|
63
68
|
userDataDir,
|
|
64
69
|
});
|
|
65
70
|
const pages = await browser.pages();
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
|
|
4
|
+
describe('launcher', () => {
|
|
5
|
+
describe('launchBrowser args option', () => {
|
|
6
|
+
let originalEnv;
|
|
7
|
+
let mockChromium;
|
|
8
|
+
let mockPuppeteer;
|
|
9
|
+
let launchBrowser;
|
|
10
|
+
let capturedPlaywrightArgs;
|
|
11
|
+
let capturedPuppeteerArgs;
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
// Save original environment
|
|
15
|
+
originalEnv = { ...process.env };
|
|
16
|
+
|
|
17
|
+
// Reset captured args
|
|
18
|
+
capturedPlaywrightArgs = null;
|
|
19
|
+
capturedPuppeteerArgs = null;
|
|
20
|
+
|
|
21
|
+
// Create mock browser context for Playwright
|
|
22
|
+
const mockBrowserContext = {
|
|
23
|
+
pages: () => [
|
|
24
|
+
{
|
|
25
|
+
bringToFront: async () => {},
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
close: async () => {},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Create mock browser for Puppeteer
|
|
32
|
+
const mockBrowser = {
|
|
33
|
+
pages: async () => [
|
|
34
|
+
{
|
|
35
|
+
bringToFront: async () => {},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
close: async () => {},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Mock Playwright's chromium
|
|
42
|
+
mockChromium = {
|
|
43
|
+
launchPersistentContext: async (userDataDir, options) => {
|
|
44
|
+
capturedPlaywrightArgs = options.args;
|
|
45
|
+
return mockBrowserContext;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Mock Puppeteer
|
|
50
|
+
mockPuppeteer = {
|
|
51
|
+
default: {
|
|
52
|
+
launch: async (options) => {
|
|
53
|
+
capturedPuppeteerArgs = options.args;
|
|
54
|
+
return mockBrowser;
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Use mock.module to mock the dynamic imports
|
|
60
|
+
// Since we can't easily mock dynamic imports in Node.js test runner,
|
|
61
|
+
// we'll test the CHROME_ARGS constant usage directly
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
// Restore original environment
|
|
66
|
+
process.env = originalEnv;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should export CHROME_ARGS constant', async () => {
|
|
70
|
+
const { CHROME_ARGS } = await import('../../../src/core/constants.js');
|
|
71
|
+
assert.ok(Array.isArray(CHROME_ARGS));
|
|
72
|
+
assert.ok(CHROME_ARGS.length > 0);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should include expected default Chrome args', async () => {
|
|
76
|
+
const { CHROME_ARGS } = await import('../../../src/core/constants.js');
|
|
77
|
+
assert.ok(CHROME_ARGS.includes('--disable-session-crashed-bubble'));
|
|
78
|
+
assert.ok(CHROME_ARGS.includes('--no-first-run'));
|
|
79
|
+
assert.ok(CHROME_ARGS.includes('--no-default-browser-check'));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('launchBrowser function should accept args option', async () => {
|
|
83
|
+
// We can verify the function signature by checking that it
|
|
84
|
+
// destructures args from options without throwing
|
|
85
|
+
const { launchBrowser } =
|
|
86
|
+
await import('../../../src/browser/launcher.js');
|
|
87
|
+
assert.ok(typeof launchBrowser === 'function');
|
|
88
|
+
|
|
89
|
+
// The function should accept options object with args array
|
|
90
|
+
// We can't fully test the launch without actual browsers,
|
|
91
|
+
// but we can verify the function exists and is callable
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('launchBrowser should throw for invalid engine', async () => {
|
|
95
|
+
const { launchBrowser } =
|
|
96
|
+
await import('../../../src/browser/launcher.js');
|
|
97
|
+
|
|
98
|
+
await assert.rejects(
|
|
99
|
+
() => launchBrowser({ engine: 'invalid-engine' }),
|
|
100
|
+
(error) => {
|
|
101
|
+
assert.ok(error.message.includes('Invalid engine'));
|
|
102
|
+
assert.ok(error.message.includes('invalid-engine'));
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('launchBrowser should accept args in options', async () => {
|
|
109
|
+
const { launchBrowser } =
|
|
110
|
+
await import('../../../src/browser/launcher.js');
|
|
111
|
+
|
|
112
|
+
// Verify the function signature accepts args
|
|
113
|
+
// This test validates that the args parameter is correctly destructured
|
|
114
|
+
// by attempting to call with an invalid engine (which fails before browser launch)
|
|
115
|
+
// but proves args is accepted without error during options parsing
|
|
116
|
+
const customArgs = ['--no-sandbox', '--disable-setuid-sandbox'];
|
|
117
|
+
|
|
118
|
+
await assert.rejects(
|
|
119
|
+
() => launchBrowser({ engine: 'invalid', args: customArgs }),
|
|
120
|
+
/Invalid engine/
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// If we got here, the args option was accepted without error
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|