selenium-webdriver 3.5.0 → 4.0.0-alpha.4

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.
Files changed (366) hide show
  1. package/CHANGES.md +246 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE +1 -1
  4. package/README.md +40 -40
  5. package/chrome.js +118 -134
  6. package/edge.js +43 -117
  7. package/example/chrome_android.js +8 -9
  8. package/example/chrome_mobile_emulation.js +8 -9
  9. package/example/firefox_channels.js +23 -19
  10. package/example/google_search.js +3 -3
  11. package/example/google_search_test.js +38 -27
  12. package/example/{chrome_headless.js → headless.js} +15 -7
  13. package/example/logging.js +40 -7
  14. package/firefox.js +789 -0
  15. package/http/index.js +62 -9
  16. package/http/util.js +11 -6
  17. package/ie.js +83 -97
  18. package/index.js +198 -114
  19. package/io/exec.js +29 -15
  20. package/io/index.js +1 -1
  21. package/io/zip.js +1 -1
  22. package/lib/actions.js +68 -63
  23. package/lib/atoms/get-attribute.js +86 -0
  24. package/lib/atoms/is-displayed.js +76 -76
  25. package/lib/by.js +7 -4
  26. package/lib/capabilities.js +310 -210
  27. package/lib/command.js +27 -51
  28. package/lib/error.js +100 -41
  29. package/lib/http.js +161 -120
  30. package/lib/input.js +1044 -8
  31. package/lib/logging.js +1 -5
  32. package/lib/promise.js +222 -3331
  33. package/lib/proxy.js +134 -39
  34. package/lib/session.js +2 -2
  35. package/lib/symbols.js +0 -0
  36. package/lib/until.js +1 -1
  37. package/lib/webdriver.js +717 -953
  38. package/net/index.js +21 -25
  39. package/net/portprober.js +51 -68
  40. package/package.json +17 -12
  41. package/proxy.js +0 -0
  42. package/remote/index.js +63 -44
  43. package/safari.js +41 -128
  44. package/testing/index.js +386 -315
  45. package/.npmignore +0 -2
  46. package/example/async_await_test.js +0 -68
  47. package/example/google_search_generator.js +0 -50
  48. package/example/parallel_flows.js +0 -54
  49. package/firefox/binary.js +0 -344
  50. package/firefox/extension.js +0 -224
  51. package/firefox/index.js +0 -626
  52. package/firefox/profile.js +0 -394
  53. package/lib/README +0 -5
  54. package/lib/atoms/getAttribute.js +0 -9
  55. package/lib/devmode.js +0 -34
  56. package/lib/events.js +0 -210
  57. package/lib/firefox/webdriver.json +0 -70
  58. package/lib/test/build.js +0 -151
  59. package/lib/test/data/ClickTest_testClicksASurroundingStrongTag.html +0 -11
  60. package/lib/test/data/Page.aspx +0 -17
  61. package/lib/test/data/Page.aspx.cs +0 -22
  62. package/lib/test/data/Redirect.aspx +0 -11
  63. package/lib/test/data/Redirect.aspx.cs +0 -9
  64. package/lib/test/data/Settings.StyleCop +0 -759
  65. package/lib/test/data/Web.Config +0 -59
  66. package/lib/test/data/actualXhtmlPage.xhtml +0 -14
  67. package/lib/test/data/ajaxy_page.html +0 -81
  68. package/lib/test/data/alerts.html +0 -85
  69. package/lib/test/data/banner.gif +0 -0
  70. package/lib/test/data/beach.jpg +0 -0
  71. package/lib/test/data/blank.html +0 -1
  72. package/lib/test/data/bodyTypingTest.html +0 -41
  73. package/lib/test/data/booleanAttributes.html +0 -19
  74. package/lib/test/data/child/childPage.html +0 -8
  75. package/lib/test/data/child/grandchild/grandchildPage.html +0 -8
  76. package/lib/test/data/clickEventPage.html +0 -26
  77. package/lib/test/data/click_frames.html +0 -10
  78. package/lib/test/data/click_jacker.html +0 -38
  79. package/lib/test/data/click_out_of_bounds.html +0 -23
  80. package/lib/test/data/click_out_of_bounds_overflow.html +0 -85
  81. package/lib/test/data/click_rtl.html +0 -19
  82. package/lib/test/data/click_source.html +0 -18
  83. package/lib/test/data/click_tests/click_iframe.html +0 -6
  84. package/lib/test/data/click_tests/click_in_iframe.html +0 -8
  85. package/lib/test/data/click_tests/disabled_element.html +0 -12
  86. package/lib/test/data/click_tests/disappearing_element.html +0 -62
  87. package/lib/test/data/click_tests/google_map.html +0 -15
  88. package/lib/test/data/click_tests/google_map.png +0 -0
  89. package/lib/test/data/click_tests/html5_submit_buttons.html +0 -16
  90. package/lib/test/data/click_tests/issue5237.html +0 -9
  91. package/lib/test/data/click_tests/issue5237_frame.html +0 -1
  92. package/lib/test/data/click_tests/issue5237_target.html +0 -10
  93. package/lib/test/data/click_tests/link_that_wraps.html +0 -11
  94. package/lib/test/data/click_tests/mapped_page1.html +0 -9
  95. package/lib/test/data/click_tests/mapped_page2.html +0 -9
  96. package/lib/test/data/click_tests/mapped_page3.html +0 -9
  97. package/lib/test/data/click_tests/overlapping_elements.html +0 -70
  98. package/lib/test/data/click_tests/partially_overlapping_elements.html +0 -124
  99. package/lib/test/data/click_tests/span_that_wraps.html +0 -11
  100. package/lib/test/data/click_tests/submitted_page.html +0 -9
  101. package/lib/test/data/click_tests/wrapped_overlapping_elements.html +0 -13
  102. package/lib/test/data/click_too_big.html +0 -10
  103. package/lib/test/data/click_too_big_in_frame.html +0 -11
  104. package/lib/test/data/clicks.html +0 -35
  105. package/lib/test/data/closeable_window.html +0 -8
  106. package/lib/test/data/cn-test.html +0 -156
  107. package/lib/test/data/colorPage.html +0 -20
  108. package/lib/test/data/cookies.html +0 -30
  109. package/lib/test/data/coordinates_tests/element_in_frame.html +0 -9
  110. package/lib/test/data/coordinates_tests/element_in_nested_frame.html +0 -9
  111. package/lib/test/data/coordinates_tests/page_with_element_out_of_view.html +0 -11
  112. package/lib/test/data/coordinates_tests/page_with_empty_element.html +0 -10
  113. package/lib/test/data/coordinates_tests/page_with_fixed_element.html +0 -12
  114. package/lib/test/data/coordinates_tests/page_with_hidden_element.html +0 -10
  115. package/lib/test/data/coordinates_tests/page_with_invisible_element.html +0 -10
  116. package/lib/test/data/coordinates_tests/page_with_transparent_element.html +0 -10
  117. package/lib/test/data/coordinates_tests/simple_page.html +0 -10
  118. package/lib/test/data/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  119. package/lib/test/data/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  120. package/lib/test/data/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  121. package/lib/test/data/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  122. package/lib/test/data/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  123. package/lib/test/data/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  124. package/lib/test/data/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  125. package/lib/test/data/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  126. package/lib/test/data/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  127. package/lib/test/data/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  128. package/lib/test/data/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  129. package/lib/test/data/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  130. package/lib/test/data/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  131. package/lib/test/data/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  132. package/lib/test/data/css/ui-lightness/jquery-ui-1.8.10.custom.css +0 -573
  133. package/lib/test/data/cssTransform.html +0 -61
  134. package/lib/test/data/cssTransform2.html +0 -20
  135. package/lib/test/data/document_write_in_onload.html +0 -13
  136. package/lib/test/data/dragAndDropInsideScrolledDiv.html +0 -67
  137. package/lib/test/data/dragAndDropTest.html +0 -102
  138. package/lib/test/data/dragDropOverflow.html +0 -104
  139. package/lib/test/data/draggableLists.html +0 -67
  140. package/lib/test/data/droppableItems.html +0 -65
  141. package/lib/test/data/dynamic.html +0 -39
  142. package/lib/test/data/dynamicallyModifiedPage.html +0 -42
  143. package/lib/test/data/errors.html +0 -15
  144. package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
  145. package/lib/test/data/firefox/sample.xpi +0 -0
  146. package/lib/test/data/firefox/webextension.xpi +0 -0
  147. package/lib/test/data/fixedFooterNoScroll.html +0 -13
  148. package/lib/test/data/fixedFooterNoScrollQuirksMode.html +0 -12
  149. package/lib/test/data/formPage.html +0 -175
  150. package/lib/test/data/formSelectionPage.html +0 -46
  151. package/lib/test/data/form_handling_js_submit.html +0 -30
  152. package/lib/test/data/framePage3.html +0 -7
  153. package/lib/test/data/frameScrollChild.html +0 -26
  154. package/lib/test/data/frameScrollPage.html +0 -14
  155. package/lib/test/data/frameScrollParent.html +0 -11
  156. package/lib/test/data/frameWithAnimals.html +0 -11
  157. package/lib/test/data/frame_switching_tests/bug4876.html +0 -9
  158. package/lib/test/data/frame_switching_tests/bug4876_iframe.html +0 -9
  159. package/lib/test/data/frame_switching_tests/deletingFrame.html +0 -29
  160. package/lib/test/data/frame_switching_tests/deletingFrame_iframe.html +0 -8
  161. package/lib/test/data/frame_switching_tests/deletingFrame_iframe2.html +0 -7
  162. package/lib/test/data/frameset.html +0 -14
  163. package/lib/test/data/framesetPage2.html +0 -7
  164. package/lib/test/data/framesetPage3.html +0 -4
  165. package/lib/test/data/globalscope.html +0 -15
  166. package/lib/test/data/hidden.html +0 -5
  167. package/lib/test/data/hidden_partially.html +0 -45
  168. package/lib/test/data/html5/blue.jpg +0 -0
  169. package/lib/test/data/html5/database.js +0 -84
  170. package/lib/test/data/html5/geolocation.js +0 -18
  171. package/lib/test/data/html5/green.jpg +0 -0
  172. package/lib/test/data/html5/red.jpg +0 -0
  173. package/lib/test/data/html5/status.html +0 -1
  174. package/lib/test/data/html5/test.appcache +0 -11
  175. package/lib/test/data/html5/yellow.jpg +0 -0
  176. package/lib/test/data/html5Page.html +0 -32
  177. package/lib/test/data/icon.gif +0 -0
  178. package/lib/test/data/idElements.html +0 -2
  179. package/lib/test/data/iframeAtBottom.html +0 -15
  180. package/lib/test/data/iframeWithAlert.html +0 -1
  181. package/lib/test/data/iframeWithIframe.html +0 -1
  182. package/lib/test/data/iframes.html +0 -11
  183. package/lib/test/data/injectableContent.html +0 -22
  184. package/lib/test/data/javascriptEnhancedForm.html +0 -30
  185. package/lib/test/data/javascriptPage.html +0 -285
  186. package/lib/test/data/jquery-1.3.2.js +0 -4376
  187. package/lib/test/data/js/jquery-1.4.4.min.js +0 -167
  188. package/lib/test/data/js/jquery-ui-1.8.10.custom.min.js +0 -782
  189. package/lib/test/data/js/skins/lightgray/content.inline.min.css +0 -1
  190. package/lib/test/data/js/skins/lightgray/content.min.css +0 -1
  191. package/lib/test/data/js/skins/lightgray/fonts/readme.md +0 -1
  192. package/lib/test/data/js/skins/lightgray/fonts/tinymce-small.dev.svg +0 -175
  193. package/lib/test/data/js/skins/lightgray/fonts/tinymce-small.eot +0 -0
  194. package/lib/test/data/js/skins/lightgray/fonts/tinymce-small.svg +0 -62
  195. package/lib/test/data/js/skins/lightgray/fonts/tinymce-small.ttf +0 -0
  196. package/lib/test/data/js/skins/lightgray/fonts/tinymce-small.woff +0 -0
  197. package/lib/test/data/js/skins/lightgray/fonts/tinymce.dev.svg +0 -153
  198. package/lib/test/data/js/skins/lightgray/fonts/tinymce.eot +0 -0
  199. package/lib/test/data/js/skins/lightgray/fonts/tinymce.svg +0 -63
  200. package/lib/test/data/js/skins/lightgray/fonts/tinymce.ttf +0 -0
  201. package/lib/test/data/js/skins/lightgray/fonts/tinymce.woff +0 -0
  202. package/lib/test/data/js/skins/lightgray/img/anchor.gif +0 -0
  203. package/lib/test/data/js/skins/lightgray/img/loader.gif +0 -0
  204. package/lib/test/data/js/skins/lightgray/img/object.gif +0 -0
  205. package/lib/test/data/js/skins/lightgray/img/trans.gif +0 -0
  206. package/lib/test/data/js/skins/lightgray/skin.ie7.min.css +0 -1
  207. package/lib/test/data/js/skins/lightgray/skin.min.css +0 -1
  208. package/lib/test/data/js/themes/modern/theme.min.js +0 -1
  209. package/lib/test/data/js/tinymce.min.js +0 -10
  210. package/lib/test/data/key_logger.html +0 -34
  211. package/lib/test/data/key_tests/remove_on_keypress.html +0 -36
  212. package/lib/test/data/keyboard_shortcut.html +0 -36
  213. package/lib/test/data/linked_image.html +0 -16
  214. package/lib/test/data/locators_tests/boolean_attribute_selected.html +0 -13
  215. package/lib/test/data/locators_tests/boolean_attribute_selected_html4.html +0 -13
  216. package/lib/test/data/longContentPage.html +0 -55
  217. package/lib/test/data/macbeth.html +0 -5255
  218. package/lib/test/data/map.png +0 -0
  219. package/lib/test/data/map_visibility.html +0 -8
  220. package/lib/test/data/markerTransparent.png +0 -0
  221. package/lib/test/data/messages.html +0 -15
  222. package/lib/test/data/meta-redirect.html +0 -11
  223. package/lib/test/data/missedJsReference.html +0 -11
  224. package/lib/test/data/modal_dialogs/modal_1.html +0 -21
  225. package/lib/test/data/modal_dialogs/modal_2.html +0 -21
  226. package/lib/test/data/modal_dialogs/modal_3.html +0 -15
  227. package/lib/test/data/modal_dialogs/modalindex.html +0 -21
  228. package/lib/test/data/mouseOver.html +0 -17
  229. package/lib/test/data/mousePositionTracker.html +0 -33
  230. package/lib/test/data/nestedElements.html +0 -164
  231. package/lib/test/data/overflow/x_auto_y_auto.html +0 -30
  232. package/lib/test/data/overflow/x_auto_y_hidden.html +0 -30
  233. package/lib/test/data/overflow/x_auto_y_scroll.html +0 -30
  234. package/lib/test/data/overflow/x_hidden_y_auto.html +0 -30
  235. package/lib/test/data/overflow/x_hidden_y_hidden.html +0 -30
  236. package/lib/test/data/overflow/x_hidden_y_scroll.html +0 -30
  237. package/lib/test/data/overflow/x_scroll_y_auto.html +0 -30
  238. package/lib/test/data/overflow/x_scroll_y_hidden.html +0 -30
  239. package/lib/test/data/overflow/x_scroll_y_scroll.html +0 -30
  240. package/lib/test/data/overflow-body.html +0 -15
  241. package/lib/test/data/pageWithOnBeforeUnloadMessage.html +0 -20
  242. package/lib/test/data/pageWithOnLoad.html +0 -6
  243. package/lib/test/data/pageWithOnUnload.html +0 -6
  244. package/lib/test/data/page_with_link_to_slow_loading_page.html +0 -6
  245. package/lib/test/data/plain.txt +0 -1
  246. package/lib/test/data/proxy/page1.html +0 -20
  247. package/lib/test/data/proxy/page2.html +0 -24
  248. package/lib/test/data/proxy/page3.html +0 -5
  249. package/lib/test/data/readOnlyPage.html +0 -24
  250. package/lib/test/data/rectangles.html +0 -40
  251. package/lib/test/data/resultPage.html +0 -25
  252. package/lib/test/data/rich_text.html +0 -161
  253. package/lib/test/data/safari/frames_benchmark.html +0 -31
  254. package/lib/test/data/screen/screen.css +0 -19
  255. package/lib/test/data/screen/screen.html +0 -72
  256. package/lib/test/data/screen/screen.js +0 -7
  257. package/lib/test/data/screen/screen_frame1.html +0 -72
  258. package/lib/test/data/screen/screen_frame2.html +0 -72
  259. package/lib/test/data/screen/screen_frames.html +0 -11
  260. package/lib/test/data/screen/screen_iframes.html +0 -12
  261. package/lib/test/data/screen/screen_too_long.html +0 -68
  262. package/lib/test/data/screen/screen_x_long.html +0 -72
  263. package/lib/test/data/screen/screen_x_too_long.html +0 -72
  264. package/lib/test/data/screen/screen_y_long.html +0 -72
  265. package/lib/test/data/screen/screen_y_too_long.html +0 -72
  266. package/lib/test/data/scroll.html +0 -27
  267. package/lib/test/data/scroll2.html +0 -21
  268. package/lib/test/data/scroll3.html +0 -8
  269. package/lib/test/data/scroll4.html +0 -7
  270. package/lib/test/data/scroll5.html +0 -18
  271. package/lib/test/data/scrolling_tests/frame_with_height_above_200.html +0 -26
  272. package/lib/test/data/scrolling_tests/frame_with_height_above_2000.html +0 -26
  273. package/lib/test/data/scrolling_tests/frame_with_nested_scrolling_frame.html +0 -11
  274. package/lib/test/data/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html +0 -12
  275. package/lib/test/data/scrolling_tests/frame_with_small_height.html +0 -10
  276. package/lib/test/data/scrolling_tests/page_with_double_overflow_auto.html +0 -19
  277. package/lib/test/data/scrolling_tests/page_with_frame_out_of_view.html +0 -12
  278. package/lib/test/data/scrolling_tests/page_with_nested_scrolling_frames.html +0 -11
  279. package/lib/test/data/scrolling_tests/page_with_nested_scrolling_frames_out_of_view.html +0 -12
  280. package/lib/test/data/scrolling_tests/page_with_non_scrolling_frame.html +0 -11
  281. package/lib/test/data/scrolling_tests/page_with_scrolling_frame.html +0 -11
  282. package/lib/test/data/scrolling_tests/page_with_scrolling_frame_out_of_view.html +0 -12
  283. package/lib/test/data/scrolling_tests/page_with_tall_frame.html +0 -11
  284. package/lib/test/data/scrolling_tests/page_with_y_overflow_auto.html +0 -14
  285. package/lib/test/data/scrolling_tests/target_page.html +0 -9
  286. package/lib/test/data/selectPage.html +0 -58
  287. package/lib/test/data/selectableItems.html +0 -65
  288. package/lib/test/data/sessionCookie.html +0 -21
  289. package/lib/test/data/sessionCookieDest.html +0 -34
  290. package/lib/test/data/simple.xml +0 -5
  291. package/lib/test/data/simpleTest.html +0 -98
  292. package/lib/test/data/single_text_input.html +0 -12
  293. package/lib/test/data/slowLoadingAlert.html +0 -10
  294. package/lib/test/data/slowLoadingResourcePage.html +0 -12
  295. package/lib/test/data/slow_loading_iframes.html +0 -14
  296. package/lib/test/data/styledPage.html +0 -28
  297. package/lib/test/data/svgPiechart.xhtml +0 -81
  298. package/lib/test/data/svgTest.svg +0 -4
  299. package/lib/test/data/tables.html +0 -36
  300. package/lib/test/data/tinymce.html +0 -10
  301. package/lib/test/data/transformable.xml +0 -11
  302. package/lib/test/data/transformable.xsl +0 -37
  303. package/lib/test/data/transparentUpload.html +0 -70
  304. package/lib/test/data/underscore.html +0 -9
  305. package/lib/test/data/unicode_ltr.html +0 -8
  306. package/lib/test/data/upload.html +0 -45
  307. package/lib/test/data/userDefinedProperty.html +0 -8
  308. package/lib/test/data/veryLargeCanvas.html +0 -81
  309. package/lib/test/data/visibility-css.html +0 -21
  310. package/lib/test/data/win32frameset.html +0 -8
  311. package/lib/test/data/window_switching_tests/page_with_frame.html +0 -12
  312. package/lib/test/data/window_switching_tests/simple_page.html +0 -9
  313. package/lib/test/data/xhtmlFormPage.xhtml +0 -17
  314. package/lib/test/data/xhtmlTest.html +0 -76
  315. package/lib/test/fileserver.js +0 -321
  316. package/lib/test/httpserver.js +0 -120
  317. package/lib/test/index.js +0 -270
  318. package/lib/test/promise.js +0 -79
  319. package/lib/test/resources.js +0 -44
  320. package/opera.js +0 -405
  321. package/phantomjs.js +0 -282
  322. package/test/actions_test.js +0 -52
  323. package/test/chrome/options_test.js +0 -227
  324. package/test/chrome/service_test.js +0 -45
  325. package/test/cookie_test.js +0 -214
  326. package/test/element_finding_test.js +0 -426
  327. package/test/execute_script_test.js +0 -350
  328. package/test/fingerprint_test.js +0 -62
  329. package/test/firefox/extension_test.js +0 -120
  330. package/test/firefox/firefox_test.js +0 -261
  331. package/test/firefox/profile_test.js +0 -140
  332. package/test/http/http_test.js +0 -223
  333. package/test/http/util_test.js +0 -178
  334. package/test/io/io_test.js +0 -360
  335. package/test/io/zip_test.js +0 -128
  336. package/test/lib/by_test.js +0 -160
  337. package/test/lib/capabilities_test.js +0 -111
  338. package/test/lib/error_test.js +0 -305
  339. package/test/lib/events_test.js +0 -177
  340. package/test/lib/http_test.js +0 -696
  341. package/test/lib/logging_test.js +0 -272
  342. package/test/lib/promise_aplus_test.js +0 -78
  343. package/test/lib/promise_error_test.js +0 -884
  344. package/test/lib/promise_flow_test.js +0 -2288
  345. package/test/lib/promise_generator_test.js +0 -310
  346. package/test/lib/promise_test.js +0 -1109
  347. package/test/lib/testutil.js +0 -90
  348. package/test/lib/until_test.js +0 -478
  349. package/test/lib/webdriver_test.js +0 -2311
  350. package/test/logging_test.js +0 -167
  351. package/test/net/index_test.js +0 -60
  352. package/test/net/portprober_test.js +0 -128
  353. package/test/page_loading_test.js +0 -166
  354. package/test/phantomjs/execute_phantomjs_test.js +0 -59
  355. package/test/proxy_test.js +0 -180
  356. package/test/rect_test.js +0 -60
  357. package/test/remote_test.js +0 -117
  358. package/test/safari_test.js +0 -108
  359. package/test/session_test.js +0 -99
  360. package/test/stale_element_test.js +0 -63
  361. package/test/tag_name_test.js +0 -36
  362. package/test/testing/assert_test.js +0 -373
  363. package/test/testing/index_test.js +0 -224
  364. package/test/upload_test.js +0 -86
  365. package/test/window_test.js +0 -161
  366. package/testing/assert.js +0 -378
package/testing/index.js CHANGED
@@ -16,52 +16,8 @@
16
16
  // under the License.
17
17
 
18
18
  /**
19
- * @fileoverview Provides wrappers around the following global functions from
20
- * [Mocha's BDD interface](https://github.com/mochajs/mocha):
21
- *
22
- * - after
23
- * - afterEach
24
- * - before
25
- * - beforeEach
26
- * - it
27
- * - it.only
28
- * - it.skip
29
- * - xit
30
- *
31
- * Each of the wrapped functions support generator functions. If the generator
32
- * {@linkplain ../lib/promise.consume yields a promise}, the test will wait
33
- * for that promise to resolve before invoking the next iteration of the
34
- * generator:
35
- *
36
- * test.it('generators', function*() {
37
- * let x = yield Promise.resolve(1);
38
- * assert.equal(x, 1);
39
- * });
40
- *
41
- * The provided wrappers leverage the {@link webdriver.promise.ControlFlow}
42
- * to simplify writing asynchronous tests:
43
- *
44
- * var {Builder, By, until} = require('selenium-webdriver');
45
- * var test = require('selenium-webdriver/testing');
46
- *
47
- * test.describe('Google Search', function() {
48
- * var driver;
49
- *
50
- * test.before(function() {
51
- * driver = new Builder().forBrowser('firefox').build();
52
- * });
53
- *
54
- * test.after(function() {
55
- * driver.quit();
56
- * });
57
- *
58
- * test.it('should append query to title', function() {
59
- * driver.get('http://www.google.com/ncr');
60
- * driver.findElement(By.name('q')).sendKeys('webdriver');
61
- * driver.findElement(By.name('btnG')).click();
62
- * driver.wait(until.titleIs('webdriver - Google Search'), 1000);
63
- * });
64
- * });
19
+ * @fileoverview Provides extensions for
20
+ * [Jasmine](https://jasmine.github.io) and [Mocha](https://mochajs.org).
65
21
  *
66
22
  * You may conditionally suppress a test function using the exported
67
23
  * "ignore" function. If the provided predicate returns true, the attached
@@ -76,352 +32,467 @@
76
32
 
77
33
  'use strict';
78
34
 
79
- const promise = require('..').promise;
80
- const flow = (function() {
81
- const initial = process.env['SELENIUM_PROMISE_MANAGER'];
82
- try {
83
- process.env['SELENIUM_PROMISE_MANAGER'] = '1';
84
- return promise.controlFlow();
85
- } finally {
86
- if (initial === undefined) {
87
- delete process.env['SELENIUM_PROMISE_MANAGER'];
88
- } else {
89
- process.env['SELENIUM_PROMISE_MANAGER'] = initial;
90
- }
91
- }
92
- })();
35
+ const {isatty} = require('tty');
36
+
37
+ const chrome = require('../chrome');
38
+ const edge = require('../edge');
39
+ const firefox = require('../firefox');
40
+ const ie = require('../ie');
41
+ const remote = require('../remote');
42
+ const safari = require('../safari');
43
+ const {Browser} = require('../lib/capabilities');
44
+ const {Builder} = require('../index');
93
45
 
94
46
 
95
47
  /**
96
- * Wraps a function so that all passed arguments are ignored.
97
- * @param {!Function} fn The function to wrap.
98
- * @return {!Function} The wrapped function.
48
+ * Describes a browser targetted by a {@linkplain suite test suite}.
49
+ * @record
99
50
  */
100
- function seal(fn) {
101
- return function() {
102
- fn();
103
- };
104
- }
105
-
51
+ function TargetBrowser() {}
106
52
 
107
53
  /**
108
- * Wraps a function on Mocha's BDD interface so it runs inside a
109
- * webdriver.promise.ControlFlow and waits for the flow to complete before
110
- * continuing.
111
- * @param {!Function} globalFn The function to wrap.
112
- * @return {!Function} The new function.
54
+ * The {@linkplain Browser name} of the targetted browser.
55
+ * @type {string}
113
56
  */
114
- function wrapped(globalFn) {
115
- return function() {
116
- if (arguments.length === 1) {
117
- return globalFn(wrapArgument(arguments[0]));
57
+ TargetBrowser.prototype.name;
118
58
 
119
- } else if (arguments.length === 2) {
120
- return globalFn(arguments[0], wrapArgument(arguments[1]));
59
+ /**
60
+ * The specific version of the targetted browser, if any.
61
+ * @type {(string|undefined)}
62
+ */
63
+ TargetBrowser.prototype.version;
121
64
 
122
- } else {
123
- throw Error('Invalid # arguments: ' + arguments.length);
124
- }
125
- };
126
- }
65
+ /**
66
+ * The specific {@linkplain ../lib/capabilities.Platform platform} for the
67
+ * targetted browser, if any.
68
+ * @type {(string|undefined)}.
69
+ */
70
+ TargetBrowser.prototype.platform;
127
71
 
128
72
 
129
- function wrapArgument(value) {
130
- if (typeof value === 'function') {
131
- return makeAsyncTestFn(value);
132
- }
133
- return value;
73
+ /** @suppress {checkTypes} */
74
+ function color(c, s) {
75
+ return isatty(process.stdout) ? `\u001b[${c}m${s}\u001b[0m` : s;
134
76
  }
77
+ function green(s) { return color(32, s); }
78
+ function cyan(s) { return color(36, s); }
79
+ function info(msg) { console.info(`${green('[INFO]')} ${msg}`); }
80
+ function warn(msg) { console.warn(`${cyan('[WARNING]')} ${msg}`); }
135
81
 
136
82
 
137
83
  /**
138
- * Make a wrapper to invoke caller's test function, fn. Run the test function
139
- * within a ControlFlow.
140
- *
141
- * Should preserve the semantics of Mocha's Runnable.prototype.run (See
142
- * https://github.com/mochajs/mocha/blob/master/lib/runnable.js#L192)
84
+ * Extracts the browsers for a test suite to target from the `SELENIUM_BROWSER`
85
+ * environment variable.
143
86
  *
144
- * @param {!Function} fn
145
- * @return {!Function}
87
+ * @return {!Array<!TargetBrowser>} the browsers to target.
146
88
  */
147
- function makeAsyncTestFn(fn) {
148
- const isAsync = fn.length > 0;
149
- const isGenerator = promise.isGenerator(fn);
150
- if (isAsync && isGenerator) {
151
- throw TypeError(
152
- 'generator-based tests must not take a callback; for async testing,'
153
- + ' return a promise (or yield on a promise)');
89
+ function getBrowsersToTestFromEnv() {
90
+ let browsers = process.env['SELENIUM_BROWSER'];
91
+ if (!browsers) {
92
+ return [];
154
93
  }
155
-
156
- var ret = /** @type {function(this: mocha.Context)}*/ (function(done) {
157
- const runTest = (resolve, reject) => {
158
- try {
159
- if (isAsync) {
160
- fn.call(this, err => err ? reject(err) : resolve());
161
- } else if (isGenerator) {
162
- resolve(promise.consume(fn, this));
163
- } else {
164
- resolve(fn.call(this));
165
- }
166
- } catch (ex) {
167
- reject(ex);
168
- }
169
- };
170
-
171
- if (!promise.USE_PROMISE_MANAGER) {
172
- new Promise(runTest).then(seal(done), done);
173
- return;
94
+ return browsers.split(',').map(spec => {
95
+ const parts = spec.split(/:/, 3);
96
+ let name = parts[0];
97
+ if (name === 'ie') {
98
+ name = Browser.IE;
99
+ } else if (name === 'edge') {
100
+ name = Browser.EDGE;
174
101
  }
175
-
176
- var runnable = this.runnable();
177
- var mochaCallback = runnable.callback;
178
- runnable.callback = function() {
179
- flow.reset();
180
- return mochaCallback.apply(this, arguments);
181
- };
182
-
183
- flow.execute(function controlFlowExecute() {
184
- return new promise.Promise(function(fulfill, reject) {
185
- return runTest(fulfill, reject);
186
- }, flow);
187
- }, runnable.fullTitle()).then(seal(done), done);
102
+ let version = parts[1];
103
+ let platform = parts[2];
104
+ return {name, version, platform};
188
105
  });
189
-
190
- ret.toString = function() {
191
- return fn.toString();
192
- };
193
-
194
- return ret;
195
106
  }
196
107
 
197
108
 
198
109
  /**
199
- * Ignores the test chained to this function if the provided predicate returns
200
- * true.
201
- * @param {function(): boolean} predicateFn A predicate to call to determine
202
- * if the test should be suppressed. This function MUST be synchronous.
203
- * @return {!Object} An object with wrapped versions of {@link #it()} and
204
- * {@link #describe()} that ignore tests as indicated by the predicate.
110
+ * @return {!Array<!TargetBrowser>} the browsers available for testing on this
111
+ * system.
205
112
  */
206
- function ignore(predicateFn) {
207
- var describe = wrap(exports.xdescribe, exports.describe);
208
- describe.only = wrap(exports.xdescribe, exports.describe.only);
209
-
210
- var it = wrap(exports.xit, exports.it);
211
- it.only = wrap(exports.xit, exports.it.only);
212
-
213
- return {
214
- describe: describe,
215
- it: it
216
- };
113
+ function getAvailableBrowsers() {
114
+ info(`Searching for WebDriver executables installed on the current system...`);
115
+
116
+ let targets = [
117
+ [chrome.locateSynchronously, Browser.CHROME],
118
+ [edge.locateSynchronously, Browser.EDGE],
119
+ [firefox.locateSynchronously, Browser.FIREFOX],
120
+ [ie.locateSynchronously, Browser.IE],
121
+ [safari.locateSynchronously, Browser.SAFARI],
122
+ ];
123
+
124
+ let availableBrowsers = [];
125
+ for (let pair of targets) {
126
+ const fn = pair[0];
127
+ const name = pair[1];
128
+ if (fn()) {
129
+ info(`... located ${name}`);
130
+ availableBrowsers.push({name});
131
+ }
132
+ }
217
133
 
218
- function wrap(onSkip, onRun) {
219
- return function(title, fn) {
220
- if (predicateFn()) {
221
- onSkip(title, fn);
222
- } else {
223
- onRun(title, fn);
224
- }
225
- };
134
+ if (availableBrowsers.length === 0) {
135
+ warn(`Unable to locate any WebDriver executables for testing`);
226
136
  }
137
+
138
+ return availableBrowsers;
227
139
  }
228
140
 
141
+ let wasInit;
142
+ let targetBrowsers;
143
+ let seleniumJar;
144
+ let seleniumUrl;
145
+ let seleniumServer;
229
146
 
230
147
  /**
231
- * @param {string} name
232
- * @return {!Function}
233
- * @throws {TypeError}
148
+ * Initializes this module by determining which browsers a
149
+ * {@linkplain ./index.suite test suite} should run against. The default
150
+ * behavior is to run tests against every browser with a WebDriver executables
151
+ * (chromedriver, firefoxdriver, etc.) are installed on the system by `PATH`.
152
+ *
153
+ * Specific browsers can be selected at runtime by setting the
154
+ * `SELENIUM_BROWSER` environment variable. This environment variable has the
155
+ * same semantics as with the WebDriver {@link ../index.Builder Builder},
156
+ * except you may use a comma-delimited list to run against multiple browsers:
157
+ *
158
+ * SELENIUM_BROWSER=chrome,firefox mocha --recursive tests/
159
+ *
160
+ * The `SELENIUM_REMOTE_URL` environment variable may be set to configure tests
161
+ * to run againt an externally managed (usually remote) Selenium server. When
162
+ * set, the WebDriver builder provided by each
163
+ * {@linkplain TestEnvironment#builder TestEnvironment} will automatically be
164
+ * configured to use this server instead of starting a browser drively locally.
165
+ *
166
+ * The `SELENIUM_SERVER_JAR` environment variable may be set to the path of a
167
+ * standalone Selenium server on the local machine that should be used for
168
+ * WebDriver sessions. When set, the WebDriver builder provided by each
169
+ * {@linkplain TestEnvironment} will automatically be configured to use the
170
+ * started server instead of using a browser driver directly. It should only be
171
+ * necessary to set the `SELENIUM_SERVER_JAR` when testing locally against
172
+ * browsers not natively supported by the WebDriver
173
+ * {@link ../index.Builder Builder}.
174
+ *
175
+ * When either of the `SELENIUM_REMOTE_URL` or `SELENIUM_SERVER_JAR` environment
176
+ * variables are set, the `SELENIUM_BROWSER` variable must also be set.
177
+ *
178
+ * @param {boolean=} force whether to force this module to re-initialize and
179
+ * scan `process.env` again to determine which browsers to run tests
180
+ * against.
234
181
  */
235
- function getMochaGlobal(name) {
236
- let fn = global[name];
237
- let type = typeof fn;
238
- if (type !== 'function') {
239
- throw TypeError(
240
- `Expected global.${name} to be a function, but is ${type}. `
241
- + 'This can happen if you try using this module when running '
242
- + 'with node directly instead of using the mocha executable');
182
+ function init(force = false) {
183
+ if (wasInit && !force) {
184
+ return;
243
185
  }
244
- return fn;
245
- }
186
+ wasInit = true;
246
187
 
188
+ // If force re-init, kill the current server if there is one.
189
+ if (seleniumServer) {
190
+ seleniumServer.kill();
191
+ seleniumServer = null;
192
+ }
247
193
 
248
- const WRAPPED = {
249
- after: null,
250
- afterEach: null,
251
- before: null,
252
- beforeEach: null,
253
- it: null,
254
- itOnly: null,
255
- xit: null
256
- };
194
+ seleniumJar = process.env['SELENIUM_SERVER_JAR'];
195
+ seleniumUrl = process.env['SELENIUM_REMOTE_URL'];
196
+ if (seleniumJar) {
197
+ info(`Using Selenium server jar: ${seleniumJar}`);
198
+ }
257
199
 
200
+ if (seleniumUrl) {
201
+ info(`Using Selenium remote end: ${seleniumUrl}`);
202
+ }
203
+
204
+ if (seleniumJar && seleniumUrl) {
205
+ throw Error(
206
+ 'Ambiguous test configuration: both SELENIUM_REMOTE_URL'
207
+ + ' && SELENIUM_SERVER_JAR environment variables are set');
208
+ }
258
209
 
259
- function wrapIt() {
260
- if (!WRAPPED.it) {
261
- let it = getMochaGlobal('it');
262
- WRAPPED.it = wrapped(it);
263
- WRAPPED.itOnly = wrapped(it.only);
210
+ const envBrowsers = getBrowsersToTestFromEnv();
211
+ if ((seleniumJar || seleniumUrl) && envBrowsers.length === 0) {
212
+ throw Error(
213
+ 'Ambiguous test configuration: when either the SELENIUM_REMOTE_URL or'
214
+ + ' SELENIUM_SERVER_JAR environment variable is set, the'
215
+ + ' SELENIUM_BROWSER variable must also be set.');
264
216
  }
217
+
218
+ targetBrowsers =
219
+ envBrowsers.length > 0 ? envBrowsers : getAvailableBrowsers();
220
+ info(`Running tests against [${targetBrowsers.map(b => b.name).join(', ')}]`);
221
+
222
+ after(function() {
223
+ if (seleniumServer) {
224
+ return seleniumServer.kill();
225
+ }
226
+ });
265
227
  }
266
228
 
267
229
 
268
230
 
269
- // PUBLIC API
231
+ const TARGET_MAP = /** !WeakMap<!Environment, !TargetBrowser> */new WeakMap;
232
+ const URL_MAP =
233
+ /** !WeakMap<!Environment, ?(string|remote.SeleniumServer)> */new WeakMap;
270
234
 
271
235
 
272
236
  /**
273
- * @return {!promise.ControlFlow} the control flow instance used by this module
274
- * to coordinate test actions.
237
+ * Defines the environment a {@linkplain suite test suite} is running against.
238
+ * @final
275
239
  */
276
- exports.controlFlow = function(){
277
- return flow;
278
- };
240
+ class Environment {
241
+
242
+ /**
243
+ * @param {!TargetBrowser} browser the browser targetted in this environment.
244
+ * @param {?(string|remote.SeleniumServer)=} url remote URL of an existing
245
+ * Selenium server to test against.
246
+ */
247
+ constructor(browser, url = undefined) {
248
+ browser =
249
+ /** @type {!TargetBrowser} */(Object.seal(Object.assign({}, browser)));
250
+
251
+ TARGET_MAP.set(this, browser);
252
+ URL_MAP.set(this, url || null);
253
+ }
279
254
 
255
+ /** @return {!TargetBrowser} the target browser for this test environment. */
256
+ get browser() {
257
+ return TARGET_MAP.get(this);
258
+ }
280
259
 
281
- /**
282
- * Registers a new test suite.
283
- * @param {string} name The suite name.
284
- * @param {function()=} opt_fn The suite function, or `undefined` to define
285
- * a pending test suite.
286
- */
287
- exports.describe = function(name, opt_fn) {
288
- let fn = getMochaGlobal('describe');
289
- return opt_fn ? fn(name, opt_fn) : fn(name);
290
- };
260
+ /**
261
+ * Returns a predicate function that will suppress tests in this environment
262
+ * if the {@linkplain #browser current browser} is in the list of
263
+ * `browsersToIgnore`.
264
+ *
265
+ * @param {...(string|!Browser)} browsersToIgnore the browsers that should
266
+ * be ignored.
267
+ * @return {function(): boolean} a new predicate function.
268
+ */
269
+ browsers(...browsersToIgnore) {
270
+ return () => browsersToIgnore.indexOf(this.browser.name) != -1;
271
+ }
291
272
 
273
+ /**
274
+ * @return {!Builder} a new WebDriver builder configured to target this
275
+ * environment's {@linkplain #browser browser}.
276
+ */
277
+ builder() {
278
+ const browser = this.browser;
279
+ const urlOrServer = URL_MAP.get(this);
280
+
281
+ const builder = new Builder();
282
+ builder.disableEnvironmentOverrides();
283
+
284
+ const realBuild = builder.build;
285
+ builder.build = function() {
286
+ builder.forBrowser(browser.name, browser.version, browser.platform);
287
+ if (typeof urlOrServer === 'string') {
288
+ builder.usingServer(urlOrServer);
289
+ } else if (urlOrServer) {
290
+ builder.usingServer(urlOrServer.address());
291
+ }
292
+ return realBuild.call(builder);
293
+ };
292
294
 
293
- /**
294
- * An alias for {@link #describe()} that marks the suite as exclusive,
295
- * suppressing all other test suites.
296
- * @param {string} name The suite name.
297
- * @param {function()=} opt_fn The suite function, or `undefined` to define
298
- * a pending test suite.
299
- */
300
- exports.describe.only = function(name, opt_fn) {
301
- let desc = getMochaGlobal('describe');
302
- return opt_fn ? desc.only(name, opt_fn) : desc.only(name);
303
- };
295
+ return builder;
296
+ }
297
+ }
304
298
 
305
299
 
306
300
  /**
307
- * Defines a suppressed test suite.
308
- * @param {string} name The suite name.
309
- * @param {function()=} opt_fn The suite function, or `undefined` to define
310
- * a pending test suite.
301
+ * Configuration options for a {@linkplain ./index.suite test suite}.
302
+ * @record
311
303
  */
312
- exports.describe.skip = function(name, opt_fn) {
313
- let fn = getMochaGlobal('describe');
314
- return opt_fn ? fn.skip(name, opt_fn) : fn.skip(name);
315
- };
316
-
304
+ function SuiteOptions() {}
317
305
 
318
306
  /**
319
- * Defines a suppressed test suite.
320
- * @param {string} name The suite name.
321
- * @param {function()=} opt_fn The suite function, or `undefined` to define
322
- * a pending test suite.
307
+ * The browsers to run the test suite against.
308
+ * @type {!Array<!(Browser|TargetBrowser)>}
323
309
  */
324
- exports.xdescribe = function(name, opt_fn) {
325
- let fn = getMochaGlobal('xdescribe');
326
- return opt_fn ? fn(name, opt_fn) : fn(name);
327
- };
310
+ SuiteOptions.prototype.browsers;
328
311
 
329
312
 
330
- /**
331
- * Register a function to call after the current suite finishes.
332
- * @param {function()} fn .
333
- */
334
- exports.after = function(fn) {
335
- if (!WRAPPED.after) {
336
- WRAPPED.after = wrapped(getMochaGlobal('after'));
337
- }
338
- WRAPPED.after(fn);
339
- };
313
+ let inSuite = false;
340
314
 
341
315
 
342
316
  /**
343
- * Register a function to call after each test in a suite.
344
- * @param {function()} fn .
317
+ * Defines a test suite by calling the provided function once for each of the
318
+ * target browsers. If a suite is not limited to a specific set of browsers in
319
+ * the provided {@linkplain ./index.SuiteOptions suite options}, the suite will
320
+ * be configured to run against each of the {@linkplain ./index.init runtime
321
+ * target browsers}.
322
+ *
323
+ * Sample usage:
324
+ *
325
+ * const {By, Key, until} = require('selenium-webdriver');
326
+ * const {suite} = require('selenium-webdriver/testing');
327
+ *
328
+ * suite(function(env) {
329
+ * describe('Google Search', function() {
330
+ * let driver;
331
+ *
332
+ * before(async function() {
333
+ * driver = await env.builder().build();
334
+ * });
335
+ *
336
+ * after(() => driver.quit());
337
+ *
338
+ * it('demo', async function() {
339
+ * await driver.get('http://www.google.com/ncr');
340
+ *
341
+ * let q = await driver.findElement(By.name('q'));
342
+ * await q.sendKeys('webdriver', Key.RETURN);
343
+ * await driver.wait(
344
+ * until.titleIs('webdriver - Google Search'), 1000);
345
+ * });
346
+ * });
347
+ * });
348
+ *
349
+ * By default, this example suite will run against every WebDriver-enabled
350
+ * browser on the current system. Alternatively, the `SELENIUM_BROWSER`
351
+ * environment variable may be used to run against a specific browser:
352
+ *
353
+ * SELENIUM_BROWSER=firefox mocha -t 120000 example_test.js
354
+ *
355
+ * @param {function(!Environment)} fn the function to call to build the test
356
+ * suite.
357
+ * @param {SuiteOptions=} options configuration options.
345
358
  */
346
- exports.afterEach = function(fn) {
347
- if (!WRAPPED.afterEach) {
348
- WRAPPED.afterEach = wrapped(getMochaGlobal('afterEach'));
359
+ function suite(fn, options = undefined) {
360
+ if (inSuite) {
361
+ throw Error('Calls to suite() may not be nested');
349
362
  }
350
- WRAPPED.afterEach(fn);
351
- };
363
+ try {
364
+ init();
365
+ inSuite = true;
366
+
367
+ const suiteBrowsers = new Map;
368
+ if (options && options.browsers) {
369
+ for (let browser of options.browsers) {
370
+ if (typeof browser === 'string') {
371
+ suiteBrowsers.set(browser, {name: browser});
372
+ } else {
373
+ suiteBrowsers.set(browser.name, browser);
374
+ }
375
+ }
376
+ }
377
+
378
+ for (let browser of targetBrowsers) {
379
+ if (suiteBrowsers.size > 0 && !suiteBrowsers.has(browser.name)) {
380
+ continue;
381
+ }
352
382
 
383
+ describe(`[${browser.name}]`, function() {
384
+ if (!seleniumUrl && seleniumJar && !seleniumServer) {
385
+ seleniumServer = new remote.SeleniumServer(seleniumJar);
353
386
 
354
- /**
355
- * Register a function to call before the current suite starts.
356
- * @param {function()} fn .
357
- */
358
- exports.before = function(fn) {
359
- if (!WRAPPED.before) {
360
- WRAPPED.before = wrapped(getMochaGlobal('before'));
361
- }
362
- WRAPPED.before(fn);
363
- };
387
+ const startTimeout = 65 * 1000;
388
+ function startSelenium() {
389
+ if (typeof this.timeout === 'function') {
390
+ this.timeout(startTimeout); // For mocha.
391
+ }
364
392
 
365
- /**
366
- * Register a function to call before each test in a suite.
367
- * @param {function()} fn .
368
- */
369
- exports.beforeEach = function(fn) {
370
- if (!WRAPPED.beforeEach) {
371
- WRAPPED.beforeEach = wrapped(getMochaGlobal('beforeEach'));
372
- }
373
- WRAPPED.beforeEach(fn);
374
- };
393
+ info(`Starting selenium server ${seleniumJar}`);
394
+ return seleniumServer.start(60 * 1000);
395
+ }
375
396
 
376
- /**
377
- * Add a test to the current suite.
378
- * @param {string} name The test name.
379
- * @param {function()=} opt_fn The test function, or `undefined` to define
380
- * a pending test case.
381
- */
382
- exports.it = function(name, opt_fn) {
383
- wrapIt();
384
- if (opt_fn) {
385
- WRAPPED.it(name, opt_fn);
386
- } else {
387
- WRAPPED.it(name);
397
+ const /** !Function */beforeHook = global.beforeAll || global.before;
398
+ beforeHook(startSelenium, startTimeout);
399
+ }
400
+
401
+ fn(new Environment(browser, seleniumUrl || seleniumServer));
402
+ });
403
+ }
404
+ } finally {
405
+ inSuite = false;
388
406
  }
389
- };
407
+ }
408
+
409
+
390
410
 
391
411
  /**
392
- * An alias for {@link #it()} that flags the test as the only one that should
393
- * be run within the current suite.
394
- * @param {string} name The test name.
395
- * @param {function()=} opt_fn The test function, or `undefined` to define
396
- * a pending test case.
412
+ * Returns an object with wrappers for the standard mocha/jasmine test
413
+ * functions: `describe` and `it`, which will redirect to `xdescribe` and `xit`,
414
+ * respectively, if provided predicate function returns false.
415
+ *
416
+ * Sample usage:
417
+ *
418
+ * const {Browser} = require('selenium-webdriver');
419
+ * const {suite, ignore} = require('selenium-webdriver/testing');
420
+ *
421
+ * suite(function(env) {
422
+ *
423
+ * // Skip tests the current environment targets Chrome.
424
+ * ignore(env.browsers(Browser.CHROME)).
425
+ * describe('something', async function() {
426
+ * let driver = await env.builder().build();
427
+ * // etc.
428
+ * });
429
+ * });
430
+ *
431
+ * @param {function(): boolean} predicateFn A predicate to call to determine
432
+ * if the test should be suppressed. This function MUST be synchronous.
433
+ * @return {{describe: !Function, it: !Function}} an object with wrapped
434
+ * versions of the `describe` and `it` wtest functions.
397
435
  */
398
- exports.it.only = function(name, opt_fn) {
399
- wrapIt();
400
- if (opt_fn) {
401
- WRAPPED.itOnly(name, opt_fn);
402
- } else {
403
- WRAPPED.itOnly(name);
436
+ function ignore(predicateFn) {
437
+ const isJasmine = global.jasmine && typeof global.jasmine === 'object';
438
+
439
+ const hooks = {
440
+ describe: getTestHook('describe'),
441
+ xdescribe: getTestHook('xdescribe'),
442
+ it: getTestHook('it'),
443
+ xit: getTestHook('xit')
444
+ };
445
+ hooks.fdescribe = isJasmine ? getTestHook('fdescribe') : hooks.describe.only;
446
+ hooks.fit = isJasmine ? getTestHook('fit') : hooks.it.only;
447
+
448
+ let describe = wrap(hooks.xdescribe, hooks.describe);
449
+ let fdescribe = wrap(hooks.xdescribe, hooks.fdescribe);
450
+ describe.only = fdescribe;
451
+
452
+ let it = wrap(hooks.xit, hooks.it);
453
+ let fit = wrap(hooks.xit, hooks.fit);
454
+ it.only = fit;
455
+
456
+ return {describe, it};
457
+
458
+ function wrap(onSkip, onRun) {
459
+ return function(...args) {
460
+ if (predicateFn()) {
461
+ onSkip(...args);
462
+ } else {
463
+ onRun(...args);
464
+ }
465
+ };
404
466
  }
405
- };
467
+ }
406
468
 
407
469
 
408
470
  /**
409
- * Adds a test to the current suite while suppressing it so it is not run.
410
- * @param {string} name The test name.
411
- * @param {function()=} opt_fn The test function, or `undefined` to define
412
- * a pending test case.
471
+ * @param {string} name
472
+ * @return {!Function}
473
+ * @throws {TypeError}
413
474
  */
414
- exports.xit = function(name, opt_fn) {
415
- if (!WRAPPED.xit) {
416
- WRAPPED.xit = wrapped(getMochaGlobal('xit'));
417
- }
418
- if (opt_fn) {
419
- WRAPPED.xit(name, opt_fn);
420
- } else {
421
- WRAPPED.xit(name);
475
+ function getTestHook(name) {
476
+ let fn = global[name];
477
+ let type = typeof fn;
478
+ if (type !== 'function') {
479
+ throw TypeError(
480
+ `Expected global.${name} to be a function, but is ${type}.`
481
+ + ' This can happen if you try using this module when running with'
482
+ + ' node directly instead of using jasmine or mocha');
422
483
  }
423
- };
484
+ return fn;
485
+ }
486
+
424
487
 
488
+ // PUBLIC API
425
489
 
426
- exports.it.skip = exports.xit;
427
- exports.ignore = ignore;
490
+
491
+ module.exports = {
492
+ Environment,
493
+ TargetBrowser,
494
+ SuiteOptions,
495
+ init,
496
+ ignore,
497
+ suite
498
+ };