safaridriver 2.0.0 → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 OpenJS Foundation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  The Safaridriver utility is used to launch an HTTP server that implements the [WebDriver](https://w3c.github.io/webdriver/) REST API. When launched, Safaridriver allows for automated testing of web content using the version of Safari that is installed with macOS.
6
6
 
7
+ __Requirements:__ Node.js 22.19.0 or newer. See [Compatibility](https://github.com/webdriverio/driver#compatibility).
8
+
7
9
  ## Install
8
10
 
9
11
  To install the package, run:
@@ -27,6 +29,8 @@ safaridriver.start()
27
29
  safaridriver.stop()
28
30
  ```
29
31
 
32
+ `start()` returns the [`ChildProcess`](https://nodejs.org/api/child_process.html#class-childprocess). Read its `stdout` and `stderr`, or pass `spawnOpts: { stdio: 'ignore' }`: an unread pipe fills up and then blocks the driver.
33
+
30
34
  ## Options
31
35
 
32
36
  ### `port`
@@ -66,6 +70,13 @@ Enables diagnostic logging for all sessions hosted by this safaridriver instance
66
70
  __Type:__ `boolean`<br />
67
71
  __Default:__ `false`
68
72
 
73
+ ### `spawnOpts`
74
+
75
+ Options for the Safaridriver process, passed to [`child_process.spawn`](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options).
76
+
77
+ __Type:__ `SpawnOptions`<br />
78
+ __Default:__ `undefined`
79
+
69
80
  ----
70
81
 
71
82
  For more information on WebdriverIO see the [homepage](https://webdriver.io).
@@ -1,3 +1,50 @@
1
- declare const start: (options: never) => Promise<import("node:child_process").ChildProcess>;
2
- declare const stop: () => Promise<void>;
3
- //# sourceMappingURL=index.d.ts.map
1
+ import { type ChildProcess, type SpawnOptions } from 'node:child_process';
2
+ export declare const DEFAULT_PATH = "/usr/bin/safaridriver";
3
+ export declare const DEFAULT_STP_PATH = "/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver";
4
+ export declare const DEFAULT_PORT = 4444;
5
+ export interface SafaridriverOptions {
6
+ /**
7
+ * Specifies the port on which the HTTP server should listen for incoming connections.
8
+ * If the port is already in use or otherwise unavailable, Safaridriver will exit
9
+ * immediately with a non-zero return code.
10
+ * @default 4444
11
+ */
12
+ port?: number;
13
+ /**
14
+ * Path to Safaridriver binary.
15
+ * @default /usr/bin/safaridriver
16
+ */
17
+ path?: string;
18
+ /**
19
+ * Applies configuration changes so that subsequent WebDriver sessions will run without
20
+ * further authentication. This includes checking "Enable Remote Automation" in Safari's
21
+ * `Develop` menu. The user must authenticate via password for the changes to be applied.
22
+ *
23
+ * When this option is specified, safaridriver exits immediately without starting up the
24
+ * REST API service. If the changes were successful or already applied, safaridriver exits 0;
25
+ * otherwise, safaridriver exits >0 and prints an error message to stderr.
26
+ * @default false
27
+ */
28
+ enable?: boolean;
29
+ /**
30
+ * Enables diagnostic logging for all sessions hosted by this safaridriver instance.
31
+ * @default false
32
+ */
33
+ diagnose?: boolean;
34
+ /**
35
+ * If enabled, it starts the Safaridriver binary from the Safari Technology Preview app.
36
+ */
37
+ useTechnologyPreview?: boolean;
38
+ /**
39
+ * Options for `child_process.spawn`. Pass `{ stdio: 'ignore' }` if you don't read the
40
+ * driver output: an unread pipe fills up and then blocks the driver.
41
+ */
42
+ spawnOpts?: SpawnOptions;
43
+ }
44
+ export declare const start: (options?: SafaridriverOptions) => ChildProcess;
45
+ export declare const stop: () => void;
46
+ declare const _default: {
47
+ start: typeof start;
48
+ stop: typeof stop;
49
+ };
50
+ export default _default;
package/dist/cjs/index.js CHANGED
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
- const start = exports.start = async function (options) {
3
- const driver = await import('../index.js');
4
- return driver.start(options);
5
- };
6
- const stop = exports.stop = async function () {
7
- const driver = await import('../index.js');
8
- return driver.stop();
9
- };
10
- module.exports = { start, stop };
2
+ /**
3
+ * Node.js 22.12+ can require() the ESM build synchronously, so CommonJS gets
4
+ * every export of it. dist/cjs/package.json makes this file CommonJS.
5
+ */
6
+ // oxlint-disable-next-line typescript/no-require-imports
7
+ module.exports = require('../index.js');
11
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cjs/index.ts"],"names":[],"mappings":";AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,GAAG,KAAK,WAAW,OAAc;IACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAC1C,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC,CAAA;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,KAAK;IAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAC1C,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;AACxB,CAAC,CAAA;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cjs/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;AACH,yDAAyD;AACzD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import cp from 'node:child_process';
1
+ import { type ChildProcess, type SpawnOptions } from 'node:child_process';
2
2
  export declare const DEFAULT_PATH = "/usr/bin/safaridriver";
3
3
  export declare const DEFAULT_STP_PATH = "/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver";
4
4
  export declare const DEFAULT_PORT = 4444;
@@ -35,12 +35,17 @@ export interface SafaridriverOptions {
35
35
  * If enabled, it starts the Safaridriver binary from the Safari Technology Preview app.
36
36
  */
37
37
  useTechnologyPreview?: boolean;
38
+ /**
39
+ * Options for `child_process.spawn`. Pass `{ stdio: 'ignore' }` if you don't read the
40
+ * driver output: an unread pipe fills up and then blocks the driver.
41
+ */
42
+ spawnOpts?: SpawnOptions;
38
43
  }
39
- export declare const start: (options?: SafaridriverOptions) => cp.ChildProcess;
44
+ export declare const start: (options?: SafaridriverOptions) => ChildProcess;
40
45
  export declare const stop: () => void;
41
46
  declare const _default: {
42
- start: (options?: SafaridriverOptions) => cp.ChildProcess;
43
- stop: () => void;
47
+ start: typeof start;
48
+ stop: typeof stop;
44
49
  };
45
50
  export default _default;
46
51
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,MAAM,oBAAoB,CAAA;AAE1D,eAAO,MAAM,YAAY,0BAA0B,CAAA;AACnD,eAAO,MAAM,gBAAgB,4EAA4E,CAAA;AACzG,eAAO,MAAM,YAAY,OAAO,CAAA;AAEhC,MAAM,WAAW,mBAAmB;IAChC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;CACjC;AAID,eAAO,MAAM,KAAK,GAAI,UAAS,mBAAwB,oBAgCtD,CAAA;AAED,eAAO,MAAM,IAAI,YAKhB,CAAA;;sBAvC8B,mBAAmB;;;AAyClD,wBAA8B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAW,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAE7E,eAAO,MAAM,YAAY,0BAA0B,CAAA;AACnD,eAAO,MAAM,gBAAgB,4EAA4E,CAAA;AACzG,eAAO,MAAM,YAAY,OAAO,CAAA;AAEhC,MAAM,WAAW,mBAAmB;IAChC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,CAAA;CAC3B;AAID,eAAO,MAAM,KAAK,aAAa,mBAAmB,iBA6CjD,CAAA;AAED,eAAO,MAAM,IAAI,YAKhB,CAAA"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export const DEFAULT_PATH = '/usr/bin/safaridriver';
4
4
  export const DEFAULT_STP_PATH = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver';
5
5
  export const DEFAULT_PORT = 4444;
6
6
  let instance;
7
- let instanceOptions;
7
+ let instancePort;
8
8
  export const start = (options = {}) => {
9
9
  const port = typeof options.port === 'number' ? options.port : DEFAULT_PORT;
10
10
  const args = [`--port=${port}`];
@@ -23,11 +23,24 @@ export const start = (options = {}) => {
23
23
  args.push('--diagnose');
24
24
  }
25
25
  if (instance) {
26
- throw new Error(`There is already a Safaridriver instance running on port ${instanceOptions.port}!`);
26
+ throw new Error(`There is already a Safaridriver instance running on port ${instancePort}!`);
27
27
  }
28
- instanceOptions = options;
29
- instance = cp.execFile(driverPath, args);
30
- return instance;
28
+ // spawn, not execFile: execFile buffers the output and kills the driver after 1 MB of it
29
+ const child = cp.spawn(driverPath, args, options.spawnOpts ?? {});
30
+ instance = child;
31
+ instancePort = port;
32
+ // `exit` when the driver ran (e.g. `--enable` exits at once), `close` when it failed to start
33
+ const forget = () => {
34
+ if (instance === child) {
35
+ instance = undefined;
36
+ }
37
+ };
38
+ child.once('exit', forget);
39
+ child.once('close', forget);
40
+ // execFile listened for `error` itself; without a listener, a missing binary would crash the
41
+ // caller. Callers still get the error through their own listeners.
42
+ child.on('error', forget);
43
+ return child;
31
44
  };
32
45
  export const stop = () => {
33
46
  if (instance) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,EAAyB,MAAM,oBAAoB,CAAA;AAE1D,MAAM,CAAC,MAAM,YAAY,GAAG,uBAAuB,CAAA;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,yEAAyE,CAAA;AACzG,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;AAqChC,IAAI,QAAkC,CAAA;AACtC,IAAI,eAAoC,CAAA;AACxC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,UAA+B,EAAE,EAAE,EAAE;IACvD,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAA;IAC3E,MAAM,IAAI,GAAa,CAAC,UAAU,IAAI,EAAE,CAAC,CAAA;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,IAAI,CAC/B,OAAO,CAAC,oBAAoB;QACxB,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,YAAY,CACrB,CAAA;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;IACtF,IAAI,OAAO,CAAC,oBAAoB,IAAI,CAAC,cAAc,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACX,2DAA2D;YAC3D,wEAAwE,CAC3E,CAAA;IACL,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC3B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4DAA4D,eAAe,CAAC,IAAI,GAAG,CAAC,CAAA;IACxG,CAAC;IAED,eAAe,GAAG,OAAO,CAAA;IACzB,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IACxC,OAAO,QAAQ,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE;IACrB,IAAI,QAAQ,EAAE,CAAC;QACX,QAAQ,CAAC,IAAI,EAAE,CAAA;QACf,QAAQ,GAAG,SAAS,CAAA;IACxB,CAAC;AACL,CAAC,CAAA;AAED,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,EAA4C,MAAM,oBAAoB,CAAA;AAE7E,MAAM,CAAC,MAAM,YAAY,GAAG,uBAAuB,CAAA;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,yEAAyE,CAAA;AACzG,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;AA0ChC,IAAI,QAAkC,CAAA;AACtC,IAAI,YAAgC,CAAA;AACpC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAAO,GAAwB,EAAE,EAAE,EAAE;IACvD,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAA;IAC3E,MAAM,IAAI,GAAa,CAAC,UAAU,IAAI,EAAE,CAAC,CAAA;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,IAAI,CAC/B,OAAO,CAAC,oBAAoB;QACxB,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,YAAY,CACrB,CAAA;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;IACtF,IAAI,OAAO,CAAC,oBAAoB,IAAI,CAAC,cAAc,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACX,2DAA2D;YAC3D,wEAAwE,CAC3E,CAAA;IACL,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC3B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4DAA4D,YAAY,GAAG,CAAC,CAAA;IAChG,CAAC;IAED,yFAAyF;IACzF,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAA;IACjE,QAAQ,GAAG,KAAK,CAAA;IAChB,YAAY,GAAG,IAAI,CAAA;IACnB,8FAA8F;IAC9F,MAAM,MAAM,GAAG,GAAG,EAAE;QAChB,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACrB,QAAQ,GAAG,SAAS,CAAA;QACxB,CAAC;IACL,CAAC,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC3B,6FAA6F;IAC7F,mEAAmE;IACnE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACzB,OAAO,KAAK,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE;IACrB,IAAI,QAAQ,EAAE,CAAC;QACX,QAAQ,CAAC,IAAI,EAAE,CAAA;QACf,QAAQ,GAAG,SAAS,CAAA;IACxB,CAAC;AACL,CAAC,CAAA;AAED,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safaridriver",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "author": "Christian Bromann <mail@bromann.dev>",
5
5
  "license": "MIT",
6
6
  "description": "An NPM wrapper for handling the Safaridriver binary.",
@@ -21,30 +21,33 @@
21
21
  "url": "https://github.com/webdriverio/driver/issues"
22
22
  },
23
23
  "engines": {
24
- "node": ">=18.0.0"
24
+ "node": ">=22.19.0"
25
25
  },
26
26
  "main": "./dist/cjs/index.js",
27
27
  "type": "module",
28
28
  "module": "./dist/index.js",
29
29
  "exports": {
30
- ".": [
31
- {
30
+ ".": {
31
+ "import": {
32
32
  "types": "./dist/index.d.ts",
33
- "import": "./dist/index.js",
34
- "require": "./dist/cjs/index.js"
33
+ "default": "./dist/index.js"
35
34
  },
36
- "./dist/cjs/index.js"
37
- ]
35
+ "require": {
36
+ "types": "./dist/cjs/index.d.ts",
37
+ "default": "./dist/cjs/index.js"
38
+ }
39
+ }
38
40
  },
39
- "types": "./dist/index.d.ts",
40
- "typeScriptVersion": "3.8.3",
41
+ "types": "./dist/cjs/index.d.ts",
41
42
  "scripts": {
42
43
  "build": "tsc -b . && node ../../scripts/copy-cjs-pkg.mjs",
43
- "clean": "rimraf ./dist",
44
+ "clean": "rimraf ./dist ./tsconfig.tsbuildinfo",
44
45
  "test": "run-s test:*",
45
46
  "test:lint": "oxlint .",
46
- "test:unit": "vitest run",
47
+ "test:typecheck": "tsc -p tsconfig.test.json",
48
+ "test:unit": "vitest run --coverage",
47
49
  "test:interop": "node ./tests/interop/cjs.test.js",
50
+ "check:pack": "node ../../scripts/check-pack.mjs && publint && attw --pack . --ignore-rules false-export-default",
48
51
  "watch": "pnpm run build -- --watch"
49
52
  }
50
53
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Node.js 22.12+ can require() the ESM build synchronously, so CommonJS gets
3
+ * every export of it. dist/cjs/package.json makes this file CommonJS.
4
+ */
5
+ // oxlint-disable-next-line typescript/no-require-imports
6
+ module.exports = require('../index.js')
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
package/src/index.ts ADDED
@@ -0,0 +1,104 @@
1
+ import fs from 'node:fs'
2
+ import cp, { type ChildProcess, type SpawnOptions } from 'node:child_process'
3
+
4
+ export const DEFAULT_PATH = '/usr/bin/safaridriver'
5
+ export const DEFAULT_STP_PATH = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
6
+ export const DEFAULT_PORT = 4444
7
+
8
+ export interface SafaridriverOptions {
9
+ /**
10
+ * Specifies the port on which the HTTP server should listen for incoming connections.
11
+ * If the port is already in use or otherwise unavailable, Safaridriver will exit
12
+ * immediately with a non-zero return code.
13
+ * @default 4444
14
+ */
15
+ port?: number
16
+ /**
17
+ * Path to Safaridriver binary.
18
+ * @default /usr/bin/safaridriver
19
+ */
20
+ path?: string
21
+ /**
22
+ * Applies configuration changes so that subsequent WebDriver sessions will run without
23
+ * further authentication. This includes checking "Enable Remote Automation" in Safari's
24
+ * `Develop` menu. The user must authenticate via password for the changes to be applied.
25
+ *
26
+ * When this option is specified, safaridriver exits immediately without starting up the
27
+ * REST API service. If the changes were successful or already applied, safaridriver exits 0;
28
+ * otherwise, safaridriver exits >0 and prints an error message to stderr.
29
+ * @default false
30
+ */
31
+ enable?: boolean
32
+ /**
33
+ * Enables diagnostic logging for all sessions hosted by this safaridriver instance.
34
+ * @default false
35
+ */
36
+ diagnose?: boolean
37
+ /**
38
+ * If enabled, it starts the Safaridriver binary from the Safari Technology Preview app.
39
+ */
40
+ useTechnologyPreview?: boolean
41
+ /**
42
+ * Options for `child_process.spawn`. Pass `{ stdio: 'ignore' }` if you don't read the
43
+ * driver output: an unread pipe fills up and then blocks the driver.
44
+ */
45
+ spawnOpts?: SpawnOptions
46
+ }
47
+
48
+ let instance: ChildProcess | undefined
49
+ let instancePort: number | undefined
50
+ export const start = (options: SafaridriverOptions = {}) => {
51
+ const port = typeof options.port === 'number' ? options.port : DEFAULT_PORT
52
+ const args: string[] = [`--port=${port}`]
53
+ const driverPath = options.path || (
54
+ options.useTechnologyPreview
55
+ ? DEFAULT_STP_PATH
56
+ : DEFAULT_PATH
57
+ )
58
+
59
+ const isSTPInstalled = options.useTechnologyPreview && fs.existsSync(DEFAULT_STP_PATH)
60
+ if (options.useTechnologyPreview && !isSTPInstalled) {
61
+ throw new Error(
62
+ 'Safari Technology Preview is not installed! Please go to ' +
63
+ 'https://developer.apple.com/safari/technology-preview/ and install it.'
64
+ )
65
+ }
66
+
67
+ if (options.enable) {
68
+ args.push('--enable')
69
+ }
70
+
71
+ if (options.diagnose) {
72
+ args.push('--diagnose')
73
+ }
74
+
75
+ if (instance) {
76
+ throw new Error(`There is already a Safaridriver instance running on port ${instancePort}!`)
77
+ }
78
+
79
+ // spawn, not execFile: execFile buffers the output and kills the driver after 1 MB of it
80
+ const child = cp.spawn(driverPath, args, options.spawnOpts ?? {})
81
+ instance = child
82
+ instancePort = port
83
+ // `exit` when the driver ran (e.g. `--enable` exits at once), `close` when it failed to start
84
+ const forget = () => {
85
+ if (instance === child) {
86
+ instance = undefined
87
+ }
88
+ }
89
+ child.once('exit', forget)
90
+ child.once('close', forget)
91
+ // execFile listened for `error` itself; without a listener, a missing binary would crash the
92
+ // caller. Callers still get the error through their own listeners.
93
+ child.on('error', forget)
94
+ return child
95
+ }
96
+
97
+ export const stop = () => {
98
+ if (instance) {
99
+ instance.kill()
100
+ instance = undefined
101
+ }
102
+ }
103
+
104
+ export default { start, stop }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cjs/index.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,KAAK,YAA4C,KAAK,uDAG3D,CAAA;AAED,QAAA,MAAM,IAAI,qBAGT,CAAA"}