UrgentcareCLI 0.1.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (318) hide show
  1. checksums.yaml +4 -4
  2. data/lib/UrgentCare/CLI.rb +57 -22
  3. data/lib/UrgentCare/Office.rb +1 -5
  4. data/lib/UrgentCare/Scraper.rb +71 -0
  5. data/lib/UrgentCare/version.rb +2 -2
  6. data/lib/UrgentCare.rb +2 -1
  7. metadata +27 -321
  8. data/.gitignore +0 -11
  9. data/.rspec +0 -3
  10. data/.travis.yml +0 -5
  11. data/CODE_OF_CONDUCT.md +0 -74
  12. data/Gemfile +0 -12
  13. data/Gemfile.lock +0 -84
  14. data/LICENSE.txt +0 -21
  15. data/Notes +0 -41
  16. data/README.md +0 -41
  17. data/Rakefile +0 -8
  18. data/UrgentCare.gemspec +0 -39
  19. data/background.jpg +0 -0
  20. data/data.txt +0 -4
  21. data/lib/Urgentcare/Scraper.rb +0 -78
  22. data/node_modules/.bin/rimraf +0 -1
  23. data/node_modules/.package-lock.json +0 -250
  24. data/node_modules/balanced-match/.github/FUNDING.yml +0 -2
  25. data/node_modules/balanced-match/LICENSE.md +0 -21
  26. data/node_modules/balanced-match/README.md +0 -97
  27. data/node_modules/balanced-match/index.js +0 -62
  28. data/node_modules/balanced-match/package.json +0 -48
  29. data/node_modules/brace-expansion/LICENSE +0 -21
  30. data/node_modules/brace-expansion/README.md +0 -129
  31. data/node_modules/brace-expansion/index.js +0 -201
  32. data/node_modules/brace-expansion/package.json +0 -47
  33. data/node_modules/concat-map/.travis.yml +0 -4
  34. data/node_modules/concat-map/LICENSE +0 -18
  35. data/node_modules/concat-map/README.markdown +0 -62
  36. data/node_modules/concat-map/example/map.js +0 -6
  37. data/node_modules/concat-map/index.js +0 -13
  38. data/node_modules/concat-map/package.json +0 -43
  39. data/node_modules/concat-map/test/map.js +0 -39
  40. data/node_modules/core-util-is/LICENSE +0 -19
  41. data/node_modules/core-util-is/README.md +0 -3
  42. data/node_modules/core-util-is/float.patch +0 -604
  43. data/node_modules/core-util-is/lib/util.js +0 -107
  44. data/node_modules/core-util-is/package.json +0 -32
  45. data/node_modules/core-util-is/test.js +0 -68
  46. data/node_modules/fs.realpath/LICENSE +0 -43
  47. data/node_modules/fs.realpath/README.md +0 -33
  48. data/node_modules/fs.realpath/index.js +0 -66
  49. data/node_modules/fs.realpath/old.js +0 -303
  50. data/node_modules/fs.realpath/package.json +0 -26
  51. data/node_modules/glob/LICENSE +0 -21
  52. data/node_modules/glob/README.md +0 -375
  53. data/node_modules/glob/changelog.md +0 -67
  54. data/node_modules/glob/common.js +0 -234
  55. data/node_modules/glob/glob.js +0 -788
  56. data/node_modules/glob/package.json +0 -51
  57. data/node_modules/glob/sync.js +0 -484
  58. data/node_modules/immediate/LICENSE.txt +0 -20
  59. data/node_modules/immediate/README.md +0 -93
  60. data/node_modules/immediate/dist/immediate.js +0 -75
  61. data/node_modules/immediate/dist/immediate.min.js +0 -1
  62. data/node_modules/immediate/lib/browser.js +0 -69
  63. data/node_modules/immediate/lib/index.js +0 -73
  64. data/node_modules/immediate/package.json +0 -42
  65. data/node_modules/inflight/LICENSE +0 -15
  66. data/node_modules/inflight/README.md +0 -37
  67. data/node_modules/inflight/inflight.js +0 -54
  68. data/node_modules/inflight/package.json +0 -29
  69. data/node_modules/inherits/LICENSE +0 -16
  70. data/node_modules/inherits/README.md +0 -42
  71. data/node_modules/inherits/inherits.js +0 -9
  72. data/node_modules/inherits/inherits_browser.js +0 -27
  73. data/node_modules/inherits/package.json +0 -29
  74. data/node_modules/isarray/.npmignore +0 -1
  75. data/node_modules/isarray/.travis.yml +0 -4
  76. data/node_modules/isarray/Makefile +0 -6
  77. data/node_modules/isarray/README.md +0 -60
  78. data/node_modules/isarray/component.json +0 -19
  79. data/node_modules/isarray/index.js +0 -5
  80. data/node_modules/isarray/package.json +0 -45
  81. data/node_modules/isarray/test.js +0 -20
  82. data/node_modules/jszip/.codeclimate.yml +0 -16
  83. data/node_modules/jszip/.editorconfig +0 -8
  84. data/node_modules/jszip/.jshintignore +0 -1
  85. data/node_modules/jszip/.jshintrc +0 -21
  86. data/node_modules/jszip/.travis.yml +0 -17
  87. data/node_modules/jszip/CHANGES.md +0 -163
  88. data/node_modules/jszip/LICENSE.markdown +0 -651
  89. data/node_modules/jszip/README.markdown +0 -35
  90. data/node_modules/jszip/dist/jszip.js +0 -30
  91. data/node_modules/jszip/dist/jszip.min.js +0 -13
  92. data/node_modules/jszip/index.d.ts +0 -270
  93. data/node_modules/jszip/lib/base64.js +0 -106
  94. data/node_modules/jszip/lib/compressedObject.js +0 -74
  95. data/node_modules/jszip/lib/compressions.js +0 -14
  96. data/node_modules/jszip/lib/crc32.js +0 -77
  97. data/node_modules/jszip/lib/defaults.js +0 -11
  98. data/node_modules/jszip/lib/external.js +0 -19
  99. data/node_modules/jszip/lib/flate.js +0 -85
  100. data/node_modules/jszip/lib/generate/ZipFileWorker.js +0 -540
  101. data/node_modules/jszip/lib/generate/index.js +0 -57
  102. data/node_modules/jszip/lib/index.js +0 -52
  103. data/node_modules/jszip/lib/license_header.js +0 -11
  104. data/node_modules/jszip/lib/load.js +0 -81
  105. data/node_modules/jszip/lib/nodejs/NodejsStreamInputAdapter.js +0 -74
  106. data/node_modules/jszip/lib/nodejs/NodejsStreamOutputAdapter.js +0 -42
  107. data/node_modules/jszip/lib/nodejsUtils.js +0 -57
  108. data/node_modules/jszip/lib/object.js +0 -389
  109. data/node_modules/jszip/lib/readable-stream-browser.js +0 -9
  110. data/node_modules/jszip/lib/reader/ArrayReader.js +0 -57
  111. data/node_modules/jszip/lib/reader/DataReader.js +0 -116
  112. data/node_modules/jszip/lib/reader/NodeBufferReader.js +0 -19
  113. data/node_modules/jszip/lib/reader/StringReader.js +0 -38
  114. data/node_modules/jszip/lib/reader/Uint8ArrayReader.js +0 -22
  115. data/node_modules/jszip/lib/reader/readerFor.js +0 -28
  116. data/node_modules/jszip/lib/signature.js +0 -7
  117. data/node_modules/jszip/lib/stream/ConvertWorker.js +0 -26
  118. data/node_modules/jszip/lib/stream/Crc32Probe.js +0 -24
  119. data/node_modules/jszip/lib/stream/DataLengthProbe.js +0 -29
  120. data/node_modules/jszip/lib/stream/DataWorker.js +0 -116
  121. data/node_modules/jszip/lib/stream/GenericWorker.js +0 -263
  122. data/node_modules/jszip/lib/stream/StreamHelper.js +0 -212
  123. data/node_modules/jszip/lib/support.js +0 -38
  124. data/node_modules/jszip/lib/utf8.js +0 -275
  125. data/node_modules/jszip/lib/utils.js +0 -476
  126. data/node_modules/jszip/lib/zipEntries.js +0 -262
  127. data/node_modules/jszip/lib/zipEntry.js +0 -294
  128. data/node_modules/jszip/lib/zipObject.js +0 -133
  129. data/node_modules/jszip/package.json +0 -63
  130. data/node_modules/jszip/vendor/FileSaver.js +0 -247
  131. data/node_modules/lie/README.md +0 -62
  132. data/node_modules/lie/dist/lie.js +0 -350
  133. data/node_modules/lie/dist/lie.min.js +0 -1
  134. data/node_modules/lie/dist/lie.polyfill.js +0 -358
  135. data/node_modules/lie/dist/lie.polyfill.min.js +0 -1
  136. data/node_modules/lie/lib/browser.js +0 -273
  137. data/node_modules/lie/lib/index.js +0 -298
  138. data/node_modules/lie/license.md +0 -7
  139. data/node_modules/lie/lie.d.ts +0 -244
  140. data/node_modules/lie/package.json +0 -69
  141. data/node_modules/lie/polyfill.js +0 -4
  142. data/node_modules/minimatch/LICENSE +0 -15
  143. data/node_modules/minimatch/README.md +0 -209
  144. data/node_modules/minimatch/minimatch.js +0 -923
  145. data/node_modules/minimatch/package.json +0 -30
  146. data/node_modules/once/LICENSE +0 -15
  147. data/node_modules/once/README.md +0 -79
  148. data/node_modules/once/once.js +0 -42
  149. data/node_modules/once/package.json +0 -33
  150. data/node_modules/pako/CHANGELOG.md +0 -164
  151. data/node_modules/pako/LICENSE +0 -21
  152. data/node_modules/pako/README.md +0 -191
  153. data/node_modules/pako/dist/pako.js +0 -6818
  154. data/node_modules/pako/dist/pako.min.js +0 -1
  155. data/node_modules/pako/dist/pako_deflate.js +0 -3997
  156. data/node_modules/pako/dist/pako_deflate.min.js +0 -1
  157. data/node_modules/pako/dist/pako_inflate.js +0 -3300
  158. data/node_modules/pako/dist/pako_inflate.min.js +0 -1
  159. data/node_modules/pako/index.js +0 -14
  160. data/node_modules/pako/lib/deflate.js +0 -400
  161. data/node_modules/pako/lib/inflate.js +0 -423
  162. data/node_modules/pako/lib/utils/common.js +0 -105
  163. data/node_modules/pako/lib/utils/strings.js +0 -187
  164. data/node_modules/pako/lib/zlib/README +0 -59
  165. data/node_modules/pako/lib/zlib/adler32.js +0 -51
  166. data/node_modules/pako/lib/zlib/constants.js +0 -68
  167. data/node_modules/pako/lib/zlib/crc32.js +0 -59
  168. data/node_modules/pako/lib/zlib/deflate.js +0 -1874
  169. data/node_modules/pako/lib/zlib/gzheader.js +0 -58
  170. data/node_modules/pako/lib/zlib/inffast.js +0 -345
  171. data/node_modules/pako/lib/zlib/inflate.js +0 -1556
  172. data/node_modules/pako/lib/zlib/inftrees.js +0 -343
  173. data/node_modules/pako/lib/zlib/messages.js +0 -32
  174. data/node_modules/pako/lib/zlib/trees.js +0 -1222
  175. data/node_modules/pako/lib/zlib/zstream.js +0 -47
  176. data/node_modules/pako/package.json +0 -44
  177. data/node_modules/path-is-absolute/index.js +0 -20
  178. data/node_modules/path-is-absolute/license +0 -21
  179. data/node_modules/path-is-absolute/package.json +0 -43
  180. data/node_modules/path-is-absolute/readme.md +0 -59
  181. data/node_modules/process-nextick-args/index.js +0 -45
  182. data/node_modules/process-nextick-args/license.md +0 -19
  183. data/node_modules/process-nextick-args/package.json +0 -25
  184. data/node_modules/process-nextick-args/readme.md +0 -18
  185. data/node_modules/readable-stream/.travis.yml +0 -34
  186. data/node_modules/readable-stream/CONTRIBUTING.md +0 -38
  187. data/node_modules/readable-stream/GOVERNANCE.md +0 -136
  188. data/node_modules/readable-stream/LICENSE +0 -47
  189. data/node_modules/readable-stream/README.md +0 -58
  190. data/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md +0 -60
  191. data/node_modules/readable-stream/duplex-browser.js +0 -1
  192. data/node_modules/readable-stream/duplex.js +0 -1
  193. data/node_modules/readable-stream/lib/_stream_duplex.js +0 -131
  194. data/node_modules/readable-stream/lib/_stream_passthrough.js +0 -47
  195. data/node_modules/readable-stream/lib/_stream_readable.js +0 -1019
  196. data/node_modules/readable-stream/lib/_stream_transform.js +0 -214
  197. data/node_modules/readable-stream/lib/_stream_writable.js +0 -687
  198. data/node_modules/readable-stream/lib/internal/streams/BufferList.js +0 -79
  199. data/node_modules/readable-stream/lib/internal/streams/destroy.js +0 -74
  200. data/node_modules/readable-stream/lib/internal/streams/stream-browser.js +0 -1
  201. data/node_modules/readable-stream/lib/internal/streams/stream.js +0 -1
  202. data/node_modules/readable-stream/package.json +0 -52
  203. data/node_modules/readable-stream/passthrough.js +0 -1
  204. data/node_modules/readable-stream/readable-browser.js +0 -7
  205. data/node_modules/readable-stream/readable.js +0 -19
  206. data/node_modules/readable-stream/transform.js +0 -1
  207. data/node_modules/readable-stream/writable-browser.js +0 -1
  208. data/node_modules/readable-stream/writable.js +0 -8
  209. data/node_modules/rimraf/LICENSE +0 -15
  210. data/node_modules/rimraf/README.md +0 -101
  211. data/node_modules/rimraf/bin.js +0 -50
  212. data/node_modules/rimraf/package.json +0 -29
  213. data/node_modules/rimraf/rimraf.js +0 -372
  214. data/node_modules/safe-buffer/LICENSE +0 -21
  215. data/node_modules/safe-buffer/README.md +0 -584
  216. data/node_modules/safe-buffer/index.d.ts +0 -187
  217. data/node_modules/safe-buffer/index.js +0 -62
  218. data/node_modules/safe-buffer/package.json +0 -37
  219. data/node_modules/selenium-webdriver/CHANGES.md +0 -1114
  220. data/node_modules/selenium-webdriver/LICENSE +0 -202
  221. data/node_modules/selenium-webdriver/NOTICE +0 -2
  222. data/node_modules/selenium-webdriver/README.md +0 -229
  223. data/node_modules/selenium-webdriver/chrome.js +0 -295
  224. data/node_modules/selenium-webdriver/chromium.js +0 -829
  225. data/node_modules/selenium-webdriver/devtools/CDPConnection.js +0 -35
  226. data/node_modules/selenium-webdriver/edge.js +0 -224
  227. data/node_modules/selenium-webdriver/example/chrome_android.js +0 -45
  228. data/node_modules/selenium-webdriver/example/chrome_mobile_emulation.js +0 -46
  229. data/node_modules/selenium-webdriver/example/firefox_channels.js +0 -84
  230. data/node_modules/selenium-webdriver/example/google_search.js +0 -50
  231. data/node_modules/selenium-webdriver/example/google_search_test.js +0 -70
  232. data/node_modules/selenium-webdriver/example/headless.js +0 -63
  233. data/node_modules/selenium-webdriver/example/logging.js +0 -64
  234. data/node_modules/selenium-webdriver/firefox.js +0 -789
  235. data/node_modules/selenium-webdriver/http/index.js +0 -324
  236. data/node_modules/selenium-webdriver/http/util.js +0 -172
  237. data/node_modules/selenium-webdriver/ie.js +0 -503
  238. data/node_modules/selenium-webdriver/index.js +0 -825
  239. data/node_modules/selenium-webdriver/io/exec.js +0 -162
  240. data/node_modules/selenium-webdriver/io/index.js +0 -348
  241. data/node_modules/selenium-webdriver/io/zip.js +0 -223
  242. data/node_modules/selenium-webdriver/lib/atoms/find-elements.js +0 -123
  243. data/node_modules/selenium-webdriver/lib/atoms/get-attribute.js +0 -101
  244. data/node_modules/selenium-webdriver/lib/atoms/is-displayed.js +0 -101
  245. data/node_modules/selenium-webdriver/lib/atoms/mutation-listener.js +0 -55
  246. data/node_modules/selenium-webdriver/lib/by.js +0 -415
  247. data/node_modules/selenium-webdriver/lib/capabilities.js +0 -553
  248. data/node_modules/selenium-webdriver/lib/command.js +0 -206
  249. data/node_modules/selenium-webdriver/lib/error.js +0 -605
  250. data/node_modules/selenium-webdriver/lib/http.js +0 -704
  251. data/node_modules/selenium-webdriver/lib/input.js +0 -946
  252. data/node_modules/selenium-webdriver/lib/logging.js +0 -661
  253. data/node_modules/selenium-webdriver/lib/promise.js +0 -285
  254. data/node_modules/selenium-webdriver/lib/proxy.js +0 -212
  255. data/node_modules/selenium-webdriver/lib/session.js +0 -77
  256. data/node_modules/selenium-webdriver/lib/symbols.js +0 -37
  257. data/node_modules/selenium-webdriver/lib/until.js +0 -429
  258. data/node_modules/selenium-webdriver/lib/webdriver.js +0 -2919
  259. data/node_modules/selenium-webdriver/net/index.js +0 -107
  260. data/node_modules/selenium-webdriver/net/portprober.js +0 -75
  261. data/node_modules/selenium-webdriver/opera.js +0 -406
  262. data/node_modules/selenium-webdriver/package.json +0 -54
  263. data/node_modules/selenium-webdriver/proxy.js +0 -32
  264. data/node_modules/selenium-webdriver/remote/index.js +0 -624
  265. data/node_modules/selenium-webdriver/safari.js +0 -168
  266. data/node_modules/selenium-webdriver/testing/index.js +0 -504
  267. data/node_modules/set-immediate-shim/index.js +0 -7
  268. data/node_modules/set-immediate-shim/package.json +0 -34
  269. data/node_modules/set-immediate-shim/readme.md +0 -31
  270. data/node_modules/string_decoder/.travis.yml +0 -50
  271. data/node_modules/string_decoder/LICENSE +0 -48
  272. data/node_modules/string_decoder/README.md +0 -47
  273. data/node_modules/string_decoder/lib/string_decoder.js +0 -296
  274. data/node_modules/string_decoder/package.json +0 -31
  275. data/node_modules/tmp/CHANGELOG.md +0 -288
  276. data/node_modules/tmp/LICENSE +0 -21
  277. data/node_modules/tmp/README.md +0 -365
  278. data/node_modules/tmp/lib/tmp.js +0 -780
  279. data/node_modules/tmp/node_modules/.bin/rimraf +0 -1
  280. data/node_modules/tmp/node_modules/rimraf/CHANGELOG.md +0 -65
  281. data/node_modules/tmp/node_modules/rimraf/LICENSE +0 -15
  282. data/node_modules/tmp/node_modules/rimraf/README.md +0 -101
  283. data/node_modules/tmp/node_modules/rimraf/bin.js +0 -68
  284. data/node_modules/tmp/node_modules/rimraf/package.json +0 -32
  285. data/node_modules/tmp/node_modules/rimraf/rimraf.js +0 -360
  286. data/node_modules/tmp/package.json +0 -58
  287. data/node_modules/util-deprecate/History.md +0 -16
  288. data/node_modules/util-deprecate/LICENSE +0 -24
  289. data/node_modules/util-deprecate/README.md +0 -53
  290. data/node_modules/util-deprecate/browser.js +0 -67
  291. data/node_modules/util-deprecate/node.js +0 -6
  292. data/node_modules/util-deprecate/package.json +0 -27
  293. data/node_modules/wrappy/LICENSE +0 -15
  294. data/node_modules/wrappy/README.md +0 -36
  295. data/node_modules/wrappy/package.json +0 -29
  296. data/node_modules/wrappy/wrappy.js +0 -33
  297. data/node_modules/ws/LICENSE +0 -21
  298. data/node_modules/ws/README.md +0 -496
  299. data/node_modules/ws/browser.js +0 -8
  300. data/node_modules/ws/index.js +0 -10
  301. data/node_modules/ws/lib/buffer-util.js +0 -129
  302. data/node_modules/ws/lib/constants.js +0 -10
  303. data/node_modules/ws/lib/event-target.js +0 -184
  304. data/node_modules/ws/lib/extension.js +0 -223
  305. data/node_modules/ws/lib/limiter.js +0 -55
  306. data/node_modules/ws/lib/permessage-deflate.js +0 -517
  307. data/node_modules/ws/lib/receiver.js +0 -507
  308. data/node_modules/ws/lib/sender.js +0 -405
  309. data/node_modules/ws/lib/stream.js +0 -165
  310. data/node_modules/ws/lib/validation.js +0 -104
  311. data/node_modules/ws/lib/websocket-server.js +0 -418
  312. data/node_modules/ws/lib/websocket.js +0 -942
  313. data/node_modules/ws/package.json +0 -56
  314. data/package-lock.json +0 -458
  315. data/package.json +0 -5
  316. data/selenium.log +0 -1
  317. data/spec.md +0 -6
  318. data/test.data +0 -2110
@@ -1,789 +0,0 @@
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 the {@linkplain Driver WebDriver} client for Firefox.
20
- * Before using this module, you must download the latest
21
- * [geckodriver release] and ensure it can be found on your system [PATH].
22
- *
23
- * Each FirefoxDriver instance will be created with an anonymous profile,
24
- * ensuring browser historys do not share session data (cookies, history, cache,
25
- * offline storage, etc.)
26
- *
27
- * __Customizing the Firefox Profile__
28
- *
29
- * The profile used for each WebDriver session may be configured using the
30
- * {@linkplain Options} class. For example, you may install an extension, like
31
- * Firebug:
32
- *
33
- * const {Builder} = require('selenium-webdriver');
34
- * const firefox = require('selenium-webdriver/firefox');
35
- *
36
- * let options = new firefox.Options()
37
- * .addExtensions('/path/to/firebug.xpi')
38
- * .setPreference('extensions.firebug.showChromeErrors', true);
39
- *
40
- * let driver = new Builder()
41
- * .forBrowser('firefox')
42
- * .setFirefoxOptions(options)
43
- * .build();
44
- *
45
- * The {@linkplain Options} class may also be used to configure WebDriver based
46
- * on a pre-existing browser profile:
47
- *
48
- * let profile = '/usr/local/home/bob/.mozilla/firefox/3fgog75h.testing';
49
- * let options = new firefox.Options().setProfile(profile);
50
- *
51
- * The FirefoxDriver will _never_ modify a pre-existing profile; instead it will
52
- * create a copy for it to modify. By extension, there are certain browser
53
- * preferences that are required for WebDriver to function properly and they
54
- * will always be overwritten.
55
- *
56
- * __Using a Custom Firefox Binary__
57
- *
58
- * On Windows and MacOS, the FirefoxDriver will search for Firefox in its
59
- * default installation location:
60
- *
61
- * - Windows: C:\Program Files and C:\Program Files (x86).
62
- * - MacOS: /Applications/Firefox.app
63
- *
64
- * For Linux, Firefox will always be located on the PATH: `$(where firefox)`.
65
- *
66
- * Several methods are provided for starting Firefox with a custom executable.
67
- * First, on Windows and MacOS, you may configure WebDriver to check the default
68
- * install location for a non-release channel. If the requested channel cannot
69
- * be found in its default location, WebDriver will fallback to searching your
70
- * PATH. _Note:_ on Linux, Firefox is _always_ located on your path, regardless
71
- * of the requested channel.
72
- *
73
- * const {Builder} = require('selenium-webdriver');
74
- * const firefox = require('selenium-webdriver/firefox');
75
- *
76
- * let options = new firefox.Options().setBinary(firefox.Channel.NIGHTLY);
77
- * let driver = new Builder()
78
- * .forBrowser('firefox')
79
- * .setFirefoxOptions(options)
80
- * .build();
81
- *
82
- * On all platforms, you may configure WebDriver to use a Firefox specific
83
- * executable:
84
- *
85
- * let options = new firefox.Options()
86
- * .setBinary('/my/firefox/install/dir/firefox-bin');
87
- *
88
- * __Remote Testing__
89
- *
90
- * You may customize the Firefox binary and profile when running against a
91
- * remote Selenium server. Your custom profile will be packaged as a zip and
92
- * transferred to the remote host for use. The profile will be transferred
93
- * _once for each new session_. The performance impact should be minimal if
94
- * you've only configured a few extra browser preferences. If you have a large
95
- * profile with several extensions, you should consider installing it on the
96
- * remote host and defining its path via the {@link Options} class. Custom
97
- * binaries are never copied to remote machines and must be referenced by
98
- * installation path.
99
- *
100
- * const {Builder} = require('selenium-webdriver');
101
- * const firefox = require('selenium-webdriver/firefox');
102
- *
103
- * let options = new firefox.Options()
104
- * .setProfile('/profile/path/on/remote/host')
105
- * .setBinary('/install/dir/on/remote/host/firefox-bin');
106
- *
107
- * let driver = new Builder()
108
- * .forBrowser('firefox')
109
- * .usingServer('http://127.0.0.1:4444/wd/hub')
110
- * .setFirefoxOptions(options)
111
- * .build();
112
- *
113
- * [geckodriver release]: https://github.com/mozilla/geckodriver/releases/
114
- * [PATH]: http://en.wikipedia.org/wiki/PATH_%28variable%29
115
- */
116
-
117
- 'use strict'
118
-
119
- const path = require('path')
120
- const Symbols = require('./lib/symbols')
121
- const command = require('./lib/command')
122
- const http = require('./http')
123
- const io = require('./io')
124
- const remote = require('./remote')
125
- const webdriver = require('./lib/webdriver')
126
- const zip = require('./io/zip')
127
- const cdp = require('./devtools/CDPConnection')
128
- const { Browser, Capabilities } = require('./lib/capabilities')
129
- const { Zip } = require('./io/zip')
130
-
131
- /**
132
- * Thrown when there an add-on is malformed.
133
- * @final
134
- */
135
- class AddonFormatError extends Error {
136
- /** @param {string} msg The error message. */
137
- constructor(msg) {
138
- super(msg)
139
- /** @override */
140
- this.name = this.constructor.name
141
- }
142
- }
143
-
144
- /**
145
- * Installs an extension to the given directory.
146
- * @param {string} extension Path to the xpi extension file to install.
147
- * @param {string} dir Path to the directory to install the extension in.
148
- * @return {!Promise<string>} A promise for the add-on ID once
149
- * installed.
150
- */
151
- async function installExtension(extension, dir) {
152
- const ext = extension.slice(-4)
153
- if (ext !== '.xpi' && ext !== '.zip') {
154
- throw Error('File name does not end in ".zip" or ".xpi": ' + ext)
155
- }
156
-
157
- let archive = await zip.load(extension)
158
- if (!archive.has('manifest.json')) {
159
- throw new AddonFormatError(`Couldn't find manifest.json in ${extension}`)
160
- }
161
-
162
- let buf = await archive.getFile('manifest.json')
163
- let parsedJSON = JSON.parse(buf.toString('utf8'))
164
-
165
- let { browser_specific_settings } =
166
- /** @type {{browser_specific_settings:{gecko:{id:string}}}} */
167
- parsedJSON
168
-
169
- if (browser_specific_settings && browser_specific_settings.gecko) {
170
- /* browser_specific_settings is an alternative to applications
171
- * It is meant to facilitate cross-browser plugins since Firefox48
172
- * see https://bugzilla.mozilla.org/show_bug.cgi?id=1262005
173
- */
174
- parsedJSON.applications = browser_specific_settings
175
- }
176
-
177
- let { applications } =
178
- /** @type {{applications:{gecko:{id:string}}}} */
179
- parsedJSON
180
- if (!(applications && applications.gecko && applications.gecko.id)) {
181
- throw new AddonFormatError(`Could not find add-on ID for ${extension}`)
182
- }
183
-
184
- await io.copy(extension, `${path.join(dir, applications.gecko.id)}.xpi`)
185
- return applications.gecko.id
186
- }
187
-
188
- class Profile {
189
- constructor() {
190
- /** @private {?string} */
191
- this.template_ = null
192
-
193
- /** @private {!Array<string>} */
194
- this.extensions_ = []
195
- }
196
-
197
- addExtensions(/** !Array<string> */ paths) {
198
- this.extensions_ = this.extensions_.concat(...paths)
199
- }
200
-
201
- /**
202
- * @return {(!Promise<string>|undefined)} a promise for a base64 encoded
203
- * profile, or undefined if there's no data to include.
204
- */
205
- [Symbols.serialize]() {
206
- if (this.template_ || this.extensions_.length) {
207
- return buildProfile(this.template_, this.extensions_)
208
- }
209
- return undefined
210
- }
211
- }
212
-
213
- /**
214
- * @param {?string} template path to an existing profile to use as a template.
215
- * @param {!Array<string>} extensions paths to extensions to install in the new
216
- * profile.
217
- * @return {!Promise<string>} a promise for the base64 encoded profile.
218
- */
219
- async function buildProfile(template, extensions) {
220
- let dir = template
221
-
222
- if (extensions.length) {
223
- dir = await io.tmpDir()
224
- if (template) {
225
- await io.copyDir(
226
- /** @type {string} */(template),
227
- dir,
228
- /(parent\.lock|lock|\.parentlock)/
229
- )
230
- }
231
-
232
- const extensionsDir = path.join(dir, 'extensions')
233
- await io.mkdir(extensionsDir)
234
-
235
- for (let i = 0; i < extensions.length; i++) {
236
- await installExtension(extensions[i], extensionsDir)
237
- }
238
- }
239
-
240
- let zip = new Zip()
241
- return zip
242
- .addDir(dir)
243
- .then(() => zip.toBuffer())
244
- .then((buf) => buf.toString('base64'))
245
- }
246
-
247
- /**
248
- * Configuration options for the FirefoxDriver.
249
- */
250
- class Options extends Capabilities {
251
- /**
252
- * @param {(Capabilities|Map<string, ?>|Object)=} other Another set of
253
- * capabilities to initialize this instance from.
254
- */
255
- constructor(other) {
256
- super(other)
257
- this.setBrowserName(Browser.FIREFOX)
258
- }
259
-
260
- /**
261
- * @return {!Object}
262
- * @private
263
- */
264
- firefoxOptions_() {
265
- let options = this.get('moz:firefoxOptions')
266
- if (!options) {
267
- options = {}
268
- this.set('moz:firefoxOptions', options)
269
- }
270
- return options
271
- }
272
-
273
- /**
274
- * @return {!Profile}
275
- * @private
276
- */
277
- profile_() {
278
- let options = this.firefoxOptions_()
279
- if (!options.profile) {
280
- options.profile = new Profile()
281
- }
282
- return options.profile
283
- }
284
-
285
- /**
286
- * Specify additional command line arguments that should be used when starting
287
- * the Firefox browser.
288
- *
289
- * @param {...(string|!Array<string>)} args The arguments to include.
290
- * @return {!Options} A self reference.
291
- */
292
- addArguments(...args) {
293
- if (args.length) {
294
- let options = this.firefoxOptions_()
295
- options.args = options.args ? options.args.concat(...args) : args
296
- }
297
- return this
298
- }
299
-
300
- /**
301
- * Configures the geckodriver to start Firefox in headless mode.
302
- *
303
- * @return {!Options} A self reference.
304
- */
305
- headless() {
306
- return this.addArguments('-headless')
307
- }
308
-
309
- /**
310
- * Sets the initial window size when running in
311
- * {@linkplain #headless headless} mode.
312
- *
313
- * @param {{width: number, height: number}} size The desired window size.
314
- * @return {!Options} A self reference.
315
- * @throws {TypeError} if width or height is unspecified, not a number, or
316
- * less than or equal to 0.
317
- */
318
- windowSize({ width, height }) {
319
- function checkArg(arg) {
320
- if (typeof arg !== 'number' || arg <= 0) {
321
- throw TypeError('Arguments must be {width, height} with numbers > 0')
322
- }
323
- }
324
- checkArg(width)
325
- checkArg(height)
326
- return this.addArguments(`--width=${width}`, `--height=${height}`)
327
- }
328
-
329
- /**
330
- * Add extensions that should be installed when starting Firefox.
331
- *
332
- * @param {...string} paths The paths to the extension XPI files to install.
333
- * @return {!Options} A self reference.
334
- */
335
- addExtensions(...paths) {
336
- this.profile_().addExtensions(paths)
337
- return this
338
- }
339
-
340
- /**
341
- * @param {string} key the preference key.
342
- * @param {(string|number|boolean)} value the preference value.
343
- * @return {!Options} A self reference.
344
- * @throws {TypeError} if either the key or value has an invalid type.
345
- */
346
- setPreference(key, value) {
347
- if (typeof key !== 'string') {
348
- throw TypeError(`key must be a string, but got ${typeof key}`)
349
- }
350
- if (
351
- typeof value !== 'string' &&
352
- typeof value !== 'number' &&
353
- typeof value !== 'boolean'
354
- ) {
355
- throw TypeError(
356
- `value must be a string, number, or boolean, but got ${typeof value}`
357
- )
358
- }
359
- let options = this.firefoxOptions_()
360
- options.prefs = options.prefs || {}
361
- options.prefs[key] = value
362
- return this
363
- }
364
-
365
- /**
366
- * Sets the path to an existing profile to use as a template for new browser
367
- * sessions. This profile will be copied for each new session - changes will
368
- * not be applied to the profile itself.
369
- *
370
- * @param {string} profile The profile to use.
371
- * @return {!Options} A self reference.
372
- * @throws {TypeError} if profile is not a string.
373
- */
374
- setProfile(profile) {
375
- if (typeof profile !== 'string') {
376
- throw TypeError(`profile must be a string, but got ${typeof profile}`)
377
- }
378
- this.profile_().template_ = profile
379
- return this
380
- }
381
-
382
- /**
383
- * Sets the binary to use. The binary may be specified as the path to a
384
- * Firefox executable or a desired release {@link Channel}.
385
- *
386
- * @param {(string|!Channel)} binary The binary to use.
387
- * @return {!Options} A self reference.
388
- * @throws {TypeError} If `binary` is an invalid type.
389
- */
390
- setBinary(binary) {
391
- if (binary instanceof Channel || typeof binary === 'string') {
392
- this.firefoxOptions_().binary = binary
393
- return this
394
- }
395
- throw TypeError('binary must be a string path or Channel object')
396
- }
397
- }
398
-
399
- /**
400
- * Enum of available command contexts.
401
- *
402
- * Command contexts are specific to Marionette, and may be used with the
403
- * {@link #context=} method. Contexts allow you to direct all subsequent
404
- * commands to either "content" (default) or "chrome". The latter gives
405
- * you elevated security permissions.
406
- *
407
- * @enum {string}
408
- */
409
- const Context = {
410
- CONTENT: 'content',
411
- CHROME: 'chrome',
412
- }
413
-
414
- const GECKO_DRIVER_EXE =
415
- process.platform === 'win32' ? 'geckodriver.exe' : 'geckodriver'
416
-
417
- /**
418
- * _Synchronously_ attempts to locate the geckodriver executable on the current
419
- * system.
420
- *
421
- * @return {?string} the located executable, or `null`.
422
- */
423
- function locateSynchronously() {
424
- return io.findInPath(GECKO_DRIVER_EXE, true)
425
- }
426
-
427
- /**
428
- * @return {string} .
429
- * @throws {Error}
430
- */
431
- function findGeckoDriver() {
432
- let exe = locateSynchronously()
433
- if (!exe) {
434
- throw Error(
435
- 'The ' +
436
- GECKO_DRIVER_EXE +
437
- ' executable could not be found on the current ' +
438
- 'PATH. Please download the latest version from ' +
439
- 'https://github.com/mozilla/geckodriver/releases/ ' +
440
- 'and ensure it can be found on your PATH.'
441
- )
442
- }
443
- return exe
444
- }
445
-
446
- /**
447
- * @param {string} file Path to the file to find, relative to the program files
448
- * root.
449
- * @return {!Promise<?string>} A promise for the located executable.
450
- * The promise will resolve to {@code null} if Firefox was not found.
451
- */
452
- function findInProgramFiles(file) {
453
- let files = [
454
- process.env['PROGRAMFILES'] || 'C:\\Program Files',
455
- process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)',
456
- ].map((prefix) => path.join(prefix, file))
457
- return io.exists(files[0]).then(function (exists) {
458
- return exists
459
- ? files[0]
460
- : io.exists(files[1]).then(function (exists) {
461
- return exists ? files[1] : null
462
- })
463
- })
464
- }
465
-
466
- /** @enum {string} */
467
- const ExtensionCommand = {
468
- GET_CONTEXT: 'getContext',
469
- SET_CONTEXT: 'setContext',
470
- INSTALL_ADDON: 'install addon',
471
- UNINSTALL_ADDON: 'uninstall addon',
472
- }
473
-
474
- /**
475
- * Creates a command executor with support for Marionette's custom commands.
476
- * @param {!Promise<string>} serverUrl The server's URL.
477
- * @return {!command.Executor} The new command executor.
478
- */
479
- function createExecutor(serverUrl) {
480
- let client = serverUrl.then((url) => new http.HttpClient(url))
481
- let executor = new http.Executor(client)
482
- configureExecutor(executor)
483
- return executor
484
- }
485
-
486
- /**
487
- * Configures the given executor with Firefox-specific commands.
488
- * @param {!http.Executor} executor the executor to configure.
489
- */
490
- function configureExecutor(executor) {
491
- executor.defineCommand(
492
- ExtensionCommand.GET_CONTEXT,
493
- 'GET',
494
- '/session/:sessionId/moz/context'
495
- )
496
-
497
- executor.defineCommand(
498
- ExtensionCommand.SET_CONTEXT,
499
- 'POST',
500
- '/session/:sessionId/moz/context'
501
- )
502
-
503
- executor.defineCommand(
504
- ExtensionCommand.INSTALL_ADDON,
505
- 'POST',
506
- '/session/:sessionId/moz/addon/install'
507
- )
508
-
509
- executor.defineCommand(
510
- ExtensionCommand.UNINSTALL_ADDON,
511
- 'POST',
512
- '/session/:sessionId/moz/addon/uninstall'
513
- )
514
- }
515
-
516
- /**
517
- * Creates {@link selenium-webdriver/remote.DriverService} instances that manage
518
- * a [geckodriver](https://github.com/mozilla/geckodriver) server in a child
519
- * process.
520
- */
521
- class ServiceBuilder extends remote.DriverService.Builder {
522
- /**
523
- * @param {string=} opt_exe Path to the server executable to use. If omitted,
524
- * the builder will attempt to locate the geckodriver on the system PATH.
525
- */
526
- constructor(opt_exe) {
527
- super(opt_exe || findGeckoDriver())
528
- this.setLoopback(true) // Required.
529
- }
530
-
531
- /**
532
- * Enables verbose logging.
533
- *
534
- * @param {boolean=} opt_trace Whether to enable trace-level logging. By
535
- * default, only debug logging is enabled.
536
- * @return {!ServiceBuilder} A self reference.
537
- */
538
- enableVerboseLogging(opt_trace) {
539
- return this.addArguments(opt_trace ? '-vv' : '-v')
540
- }
541
- }
542
-
543
- /**
544
- * A WebDriver client for Firefox.
545
- */
546
- class Driver extends webdriver.WebDriver {
547
- /**
548
- * Creates a new Firefox session.
549
- *
550
- * @param {(Options|Capabilities|Object)=} opt_config The
551
- * configuration options for this driver, specified as either an
552
- * {@link Options} or {@link Capabilities}, or as a raw hash object.
553
- * @param {(http.Executor|remote.DriverService)=} opt_executor Either a
554
- * pre-configured command executor to use for communicating with an
555
- * externally managed remote end (which is assumed to already be running),
556
- * or the `DriverService` to use to start the geckodriver in a child
557
- * process.
558
- *
559
- * If an executor is provided, care should e taken not to use reuse it with
560
- * other clients as its internal command mappings will be updated to support
561
- * Firefox-specific commands.
562
- *
563
- * _This parameter may only be used with Mozilla's GeckoDriver._
564
- *
565
- * @throws {Error} If a custom command executor is provided and the driver is
566
- * configured to use the legacy FirefoxDriver from the Selenium project.
567
- * @return {!Driver} A new driver instance.
568
- */
569
- static createSession(opt_config, opt_executor) {
570
- let caps =
571
- opt_config instanceof Capabilities ? opt_config : new Options(opt_config)
572
-
573
- let executor
574
- let onQuit
575
-
576
- if (opt_executor instanceof http.Executor) {
577
- executor = opt_executor
578
- configureExecutor(executor)
579
- } else if (opt_executor instanceof remote.DriverService) {
580
- executor = createExecutor(opt_executor.start())
581
- onQuit = () => opt_executor.kill()
582
- } else {
583
- let service = new ServiceBuilder().build()
584
- executor = createExecutor(service.start())
585
- onQuit = () => service.kill()
586
- }
587
-
588
- return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))
589
- }
590
-
591
- /**
592
- * This function is a no-op as file detectors are not supported by this
593
- * implementation.
594
- * @override
595
- */
596
- setFileDetector() { }
597
-
598
- /**
599
- * Get the context that is currently in effect.
600
- *
601
- * @return {!Promise<Context>} Current context.
602
- */
603
- getContext() {
604
- return this.execute(new command.Command(ExtensionCommand.GET_CONTEXT))
605
- }
606
-
607
- /**
608
- * Changes target context for commands between chrome- and content.
609
- *
610
- * Changing the current context has a stateful impact on all subsequent
611
- * commands. The {@link Context.CONTENT} context has normal web
612
- * platform document permissions, as if you would evaluate arbitrary
613
- * JavaScript. The {@link Context.CHROME} context gets elevated
614
- * permissions that lets you manipulate the browser chrome itself,
615
- * with full access to the XUL toolkit.
616
- *
617
- * Use your powers wisely.
618
- *
619
- * @param {!Promise<void>} ctx The context to switch to.
620
- */
621
- setContext(ctx) {
622
- return this.execute(
623
- new command.Command(ExtensionCommand.SET_CONTEXT).setParameter(
624
- 'context',
625
- ctx
626
- )
627
- )
628
- }
629
-
630
- /**
631
- * Installs a new addon with the current session. This function will return an
632
- * ID that may later be used to {@linkplain #uninstallAddon uninstall} the
633
- * addon.
634
- *
635
- *
636
- * @param {string} path Path on the local filesystem to the web extension to
637
- * install.
638
- * @param {boolean} temporary Flag indicating whether the extension should be
639
- * installed temporarily - gets removed on restart
640
- * @return {!Promise<string>} A promise that will resolve to an ID for the
641
- * newly installed addon.
642
- * @see #uninstallAddon
643
- */
644
- async installAddon(path, temporary = false) {
645
- let buf = await io.read(path)
646
- return this.execute(
647
- new command.Command(ExtensionCommand.INSTALL_ADDON)
648
- .setParameter('addon', buf.toString('base64'))
649
- .setParameter('temporary', temporary)
650
- )
651
- }
652
-
653
- /**
654
- * Uninstalls an addon from the current browser session's profile.
655
- *
656
- * @param {(string|!Promise<string>)} id ID of the addon to uninstall.
657
- * @return {!Promise} A promise that will resolve when the operation has
658
- * completed.
659
- * @see #installAddon
660
- */
661
- async uninstallAddon(id) {
662
- id = await Promise.resolve(id)
663
- return this.execute(
664
- new command.Command(ExtensionCommand.UNINSTALL_ADDON).setParameter(
665
- 'id',
666
- id
667
- )
668
- )
669
- }
670
- }
671
-
672
- /**
673
- * Provides methods for locating the executable for a Firefox release channel
674
- * on Windows and MacOS. For other systems (i.e. Linux), Firefox will always
675
- * be located on the system PATH.
676
- *
677
- * @final
678
- */
679
- class Channel {
680
- /**
681
- * @param {string} darwin The path to check when running on MacOS.
682
- * @param {string} win32 The path to check when running on Windows.
683
- */
684
- constructor(darwin, win32) {
685
- /** @private @const */ this.darwin_ = darwin
686
- /** @private @const */ this.win32_ = win32
687
- /** @private {Promise<string>} */
688
- this.found_ = null
689
- }
690
-
691
- /**
692
- * Attempts to locate the Firefox executable for this release channel. This
693
- * will first check the default installation location for the channel before
694
- * checking the user's PATH. The returned promise will be rejected if Firefox
695
- * can not be found.
696
- *
697
- * @return {!Promise<string>} A promise for the location of the located
698
- * Firefox executable.
699
- */
700
- locate() {
701
- if (this.found_) {
702
- return this.found_
703
- }
704
-
705
- let found
706
- switch (process.platform) {
707
- case 'darwin':
708
- found = io
709
- .exists(this.darwin_)
710
- .then((exists) => (exists ? this.darwin_ : io.findInPath('firefox')))
711
- break
712
-
713
- case 'win32':
714
- found = findInProgramFiles(this.win32_).then(
715
- (found) => found || io.findInPath('firefox.exe')
716
- )
717
- break
718
-
719
- default:
720
- found = Promise.resolve(io.findInPath('firefox'))
721
- break
722
- }
723
-
724
- this.found_ = found.then((found) => {
725
- if (found) {
726
- // TODO: verify version info.
727
- return found
728
- }
729
- throw Error('Could not locate Firefox on the current system')
730
- })
731
- return this.found_
732
- }
733
-
734
- /** @return {!Promise<string>} */
735
- [Symbols.serialize]() {
736
- return this.locate()
737
- }
738
- }
739
-
740
- /**
741
- * Firefox's developer channel.
742
- * @const
743
- * @see <https://www.mozilla.org/en-US/firefox/channel/desktop/#aurora>
744
- */
745
- Channel.AURORA = new Channel(
746
- '/Applications/FirefoxDeveloperEdition.app/Contents/MacOS/firefox-bin',
747
- 'Firefox Developer Edition\\firefox.exe'
748
- )
749
-
750
- /**
751
- * Firefox's beta channel. Note this is provided mainly for convenience as
752
- * the beta channel has the same installation location as the main release
753
- * channel.
754
- * @const
755
- * @see <https://www.mozilla.org/en-US/firefox/channel/desktop/#beta>
756
- */
757
- Channel.BETA = new Channel(
758
- '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
759
- 'Mozilla Firefox\\firefox.exe'
760
- )
761
-
762
- /**
763
- * Firefox's release channel.
764
- * @const
765
- * @see <https://www.mozilla.org/en-US/firefox/desktop/>
766
- */
767
- Channel.RELEASE = new Channel(
768
- '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
769
- 'Mozilla Firefox\\firefox.exe'
770
- )
771
-
772
- /**
773
- * Firefox's nightly release channel.
774
- * @const
775
- * @see <https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly>
776
- */
777
- Channel.NIGHTLY = new Channel(
778
- '/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin',
779
- 'Nightly\\firefox.exe'
780
- )
781
-
782
- // PUBLIC API
783
-
784
- exports.Channel = Channel
785
- exports.Context = Context
786
- exports.Driver = Driver
787
- exports.Options = Options
788
- exports.ServiceBuilder = ServiceBuilder
789
- exports.locateSynchronously = locateSynchronously