UNPKG

5.24 kBJavaScriptView Raw
1// Licensed to the Software Freedom Conservancy (SFC) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The SFC licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18/**
19 * @fileoverview Defines a WebDriver client for Safari.
20 */
21
22'use strict';
23
24const command = require('./lib/command');
25const error = require('./lib/error');
26const http = require('./http');
27const io = require('./io');
28const portprober = require('./net/portprober');
29const promise = require('./lib/promise');
30const remote = require('./remote');
31const Symbols = require('./lib/symbols');
32const webdriver = require('./lib/webdriver');
33const {Browser, Capabilities, Capability} = require('./lib/capabilities');
34
35
36/**
37 * _Synchronously_ attempts to locate the IE driver executable on the current
38 * system.
39 *
40 * @return {?string} the located executable, or `null`.
41 */
42function locateSynchronously() {
43 return process.platform === 'darwin'
44 ? io.findInPath('safaridriver', true) : null;
45}
46
47
48/**
49 * @return {string} .
50 * @throws {Error}
51 */
52function findSafariDriver() {
53 let exe = locateSynchronously();
54 if (!exe) {
55 throw Error(
56 `The safaridriver executable could not be found on the current PATH.
57 Please ensure you are using Safari 10.0 or above.`);
58 }
59 return exe;
60}
61
62
63/**
64 * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
65 * a [safaridriver] server in a child process.
66 *
67 * [safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
68 */
69class ServiceBuilder extends remote.DriverService.Builder {
70 /**
71 * @param {string=} opt_exe Path to the server executable to use. If omitted,
72 * the builder will attempt to locate the safaridriver on the system PATH.
73 */
74 constructor(opt_exe) {
75 super(opt_exe || findSafariDriver());
76 this.setLoopback(true); // Required.
77 }
78}
79
80
81const OPTIONS_CAPABILITY_KEY = 'safari.options';
82const TECHNOLOGY_PREVIEW_OPTIONS_KEY = 'technologyPreview';
83
84/**
85 * Configuration options specific to the {@link Driver SafariDriver}.
86 */
87class Options extends Capabilities {
88 /**
89 * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
90 * capabilities to initialize this instance from.
91 */
92 constructor(other = undefined) {
93 super(other);
94
95 /** @private {!Object} */
96 this.options_ = this.get(OPTIONS_CAPABILITY_KEY) || {};
97
98 this.set(OPTIONS_CAPABILITY_KEY, this.options_);
99 this.setBrowserName(Browser.SAFARI);
100 }
101
102 /**
103 * Instruct the SafariDriver to use the Safari Technology Preview if true.
104 * Otherwise, use the release version of Safari. Defaults to using the release version of Safari.
105 *
106 * @param {boolean} useTechnologyPreview
107 * @return {!Options} A self reference.
108 */
109 setTechnologyPreview(useTechnologyPreview) {
110 this.options_[TECHNOLOGY_PREVIEW_OPTIONS_KEY] = !!useTechnologyPreview;
111 return this;
112 }
113}
114
115/**
116 * @param {(Capabilities|Object<string, *>)=} o The options object
117 * @return {boolean}
118 */
119function useTechnologyPreview(o) {
120 if (o instanceof Capabilities) {
121 let options = o.get(OPTIONS_CAPABILITY_KEY);
122 return !!(options && options[TECHNOLOGY_PREVIEW_OPTIONS_KEY]);
123 }
124
125 if (o && typeof o === 'object') {
126 return !!o[TECHNOLOGY_PREVIEW_OPTIONS_KEY];
127 }
128
129 return false;
130}
131
132
133const SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE =
134 '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver';
135
136
137/**
138 * A WebDriver client for Safari. This class should never be instantiated
139 * directly; instead, use the {@linkplain ./builder.Builder Builder}:
140 *
141 * var driver = new Builder()
142 * .forBrowser('safari')
143 * .build();
144 *
145 */
146class Driver extends webdriver.WebDriver {
147 /**
148 * Creates a new Safari session.
149 *
150 * @param {(Options|Capabilities)=} options The configuration options.
151 * @return {!Driver} A new driver instance.
152 */
153 static createSession(options) {
154 let caps = options || new Options();
155
156 let exe;
157 if (useTechnologyPreview(caps.get(OPTIONS_CAPABILITY_KEY))) {
158 exe = SAFARIDRIVER_TECHNOLOGY_PREVIEW_EXE;
159 }
160
161 let service = new ServiceBuilder(exe).build();
162 let executor = new http.Executor(
163 service.start().then(url => new http.HttpClient(url)));
164
165 return /** @type {!Driver} */(super.createSession(
166 executor, caps, () => service.kill()));
167 }
168}
169
170
171// Public API
172
173
174exports.Driver = Driver;
175exports.Options = Options;
176exports.ServiceBuilder = ServiceBuilder;
177exports.locateSynchronously = locateSynchronously;