@serenity-js/web 3.0.0-rc.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/CHANGELOG.md +336 -73
  2. package/README.md +8 -12
  3. package/lib/errors/BrowserWindowClosedError.d.ts +15 -0
  4. package/lib/errors/BrowserWindowClosedError.d.ts.map +1 -0
  5. package/lib/errors/BrowserWindowClosedError.js +21 -0
  6. package/lib/errors/BrowserWindowClosedError.js.map +1 -0
  7. package/lib/errors/CookieMissingError.d.ts +11 -0
  8. package/lib/errors/CookieMissingError.d.ts.map +1 -0
  9. package/lib/errors/CookieMissingError.js +10 -0
  10. package/lib/errors/CookieMissingError.js.map +1 -1
  11. package/lib/errors/ModalDialogObstructsScreenshotError.d.ts +15 -0
  12. package/lib/errors/ModalDialogObstructsScreenshotError.d.ts.map +1 -0
  13. package/lib/errors/ModalDialogObstructsScreenshotError.js +21 -0
  14. package/lib/errors/ModalDialogObstructsScreenshotError.js.map +1 -0
  15. package/lib/errors/index.d.ts +3 -0
  16. package/lib/errors/index.d.ts.map +1 -0
  17. package/lib/errors/index.js +7 -1
  18. package/lib/errors/index.js.map +1 -1
  19. package/lib/expectations/index.d.ts +1 -1
  20. package/lib/expectations/index.d.ts.map +1 -0
  21. package/lib/expectations/index.js +5 -2
  22. package/lib/expectations/index.js.map +1 -1
  23. package/lib/expectations/isActive.d.ts +14 -8
  24. package/lib/expectations/isActive.d.ts.map +1 -0
  25. package/lib/expectations/isActive.js +17 -11
  26. package/lib/expectations/isActive.js.map +1 -1
  27. package/lib/expectations/isClickable.d.ts +14 -13
  28. package/lib/expectations/isClickable.d.ts.map +1 -0
  29. package/lib/expectations/isClickable.js +15 -17
  30. package/lib/expectations/isClickable.js.map +1 -1
  31. package/lib/expectations/isEnabled.d.ts +14 -7
  32. package/lib/expectations/isEnabled.d.ts.map +1 -0
  33. package/lib/expectations/isEnabled.js +17 -9
  34. package/lib/expectations/isEnabled.js.map +1 -1
  35. package/lib/expectations/isSelected.d.ts +14 -7
  36. package/lib/expectations/isSelected.d.ts.map +1 -0
  37. package/lib/expectations/isSelected.js +15 -9
  38. package/lib/expectations/isSelected.js.map +1 -1
  39. package/lib/expectations/isVisible.d.ts +14 -7
  40. package/lib/expectations/isVisible.d.ts.map +1 -0
  41. package/lib/expectations/isVisible.js +17 -9
  42. package/lib/expectations/isVisible.js.map +1 -1
  43. package/lib/index.d.ts +1 -1
  44. package/lib/index.d.ts.map +1 -0
  45. package/lib/index.js +5 -2
  46. package/lib/index.js.map +1 -1
  47. package/lib/screenplay/abilities/BrowseTheWeb.d.ts +88 -45
  48. package/lib/screenplay/abilities/BrowseTheWeb.d.ts.map +1 -0
  49. package/lib/screenplay/abilities/BrowseTheWeb.js +89 -19
  50. package/lib/screenplay/abilities/BrowseTheWeb.js.map +1 -1
  51. package/lib/screenplay/abilities/index.d.ts +1 -1
  52. package/lib/screenplay/abilities/index.d.ts.map +1 -0
  53. package/lib/screenplay/abilities/index.js +5 -2
  54. package/lib/screenplay/abilities/index.js.map +1 -1
  55. package/lib/screenplay/index.d.ts +1 -0
  56. package/lib/screenplay/index.d.ts.map +1 -0
  57. package/lib/screenplay/index.js +5 -1
  58. package/lib/screenplay/index.js.map +1 -1
  59. package/lib/screenplay/interactions/Clear.d.ts +50 -55
  60. package/lib/screenplay/interactions/Clear.d.ts.map +1 -0
  61. package/lib/screenplay/interactions/Clear.js +70 -63
  62. package/lib/screenplay/interactions/Clear.js.map +1 -1
  63. package/lib/screenplay/interactions/Click.d.ts +41 -50
  64. package/lib/screenplay/interactions/Click.d.ts.map +1 -0
  65. package/lib/screenplay/interactions/Click.js +45 -55
  66. package/lib/screenplay/interactions/Click.js.map +1 -1
  67. package/lib/screenplay/interactions/DoubleClick.d.ts +64 -67
  68. package/lib/screenplay/interactions/DoubleClick.d.ts.map +1 -0
  69. package/lib/screenplay/interactions/DoubleClick.js +68 -72
  70. package/lib/screenplay/interactions/DoubleClick.js.map +1 -1
  71. package/lib/screenplay/interactions/Enter.d.ts +42 -51
  72. package/lib/screenplay/interactions/Enter.d.ts.map +1 -0
  73. package/lib/screenplay/interactions/Enter.js +42 -52
  74. package/lib/screenplay/interactions/Enter.js.map +1 -1
  75. package/lib/screenplay/interactions/ExecuteScript.d.ts +144 -148
  76. package/lib/screenplay/interactions/ExecuteScript.d.ts.map +1 -0
  77. package/lib/screenplay/interactions/ExecuteScript.js +163 -185
  78. package/lib/screenplay/interactions/ExecuteScript.js.map +1 -1
  79. package/lib/screenplay/interactions/Hover.d.ts +40 -50
  80. package/lib/screenplay/interactions/Hover.d.ts.map +1 -0
  81. package/lib/screenplay/interactions/Hover.js +44 -55
  82. package/lib/screenplay/interactions/Hover.js.map +1 -1
  83. package/lib/screenplay/interactions/Navigate.d.ts +106 -113
  84. package/lib/screenplay/interactions/Navigate.d.ts.map +1 -0
  85. package/lib/screenplay/interactions/Navigate.js +124 -146
  86. package/lib/screenplay/interactions/Navigate.js.map +1 -1
  87. package/lib/screenplay/interactions/PageElementInteraction.d.ts +12 -28
  88. package/lib/screenplay/interactions/PageElementInteraction.d.ts.map +1 -0
  89. package/lib/screenplay/interactions/PageElementInteraction.js +12 -33
  90. package/lib/screenplay/interactions/PageElementInteraction.js.map +1 -1
  91. package/lib/screenplay/interactions/Press.d.ts +61 -55
  92. package/lib/screenplay/interactions/Press.d.ts.map +1 -0
  93. package/lib/screenplay/interactions/Press.js +83 -72
  94. package/lib/screenplay/interactions/Press.js.map +1 -1
  95. package/lib/screenplay/interactions/RightClick.d.ts +59 -65
  96. package/lib/screenplay/interactions/RightClick.d.ts.map +1 -0
  97. package/lib/screenplay/interactions/RightClick.js +63 -70
  98. package/lib/screenplay/interactions/RightClick.js.map +1 -1
  99. package/lib/screenplay/interactions/Scroll.d.ts +46 -64
  100. package/lib/screenplay/interactions/Scroll.d.ts.map +1 -0
  101. package/lib/screenplay/interactions/Scroll.js +49 -71
  102. package/lib/screenplay/interactions/Scroll.js.map +1 -1
  103. package/lib/screenplay/interactions/Select.d.ts +217 -193
  104. package/lib/screenplay/interactions/Select.d.ts.map +1 -0
  105. package/lib/screenplay/interactions/Select.js +218 -245
  106. package/lib/screenplay/interactions/Select.js.map +1 -1
  107. package/lib/screenplay/interactions/Switch.d.ts +105 -128
  108. package/lib/screenplay/interactions/Switch.d.ts.map +1 -0
  109. package/lib/screenplay/interactions/Switch.js +121 -172
  110. package/lib/screenplay/interactions/Switch.js.map +1 -1
  111. package/lib/screenplay/interactions/TakeScreenshot.d.ts +28 -50
  112. package/lib/screenplay/interactions/TakeScreenshot.d.ts.map +1 -0
  113. package/lib/screenplay/interactions/TakeScreenshot.js +32 -57
  114. package/lib/screenplay/interactions/TakeScreenshot.js.map +1 -1
  115. package/lib/screenplay/interactions/index.d.ts +2 -3
  116. package/lib/screenplay/interactions/index.d.ts.map +1 -0
  117. package/lib/screenplay/interactions/index.js +6 -4
  118. package/lib/screenplay/interactions/index.js.map +1 -1
  119. package/lib/screenplay/models/BrowserCapabilities.d.ts +24 -0
  120. package/lib/screenplay/models/BrowserCapabilities.d.ts.map +1 -0
  121. package/lib/screenplay/models/BrowserCapabilities.js.map +1 -0
  122. package/lib/screenplay/models/BrowsingSession.d.ts +69 -0
  123. package/lib/screenplay/models/BrowsingSession.d.ts.map +1 -0
  124. package/lib/screenplay/models/BrowsingSession.js +101 -0
  125. package/lib/screenplay/models/BrowsingSession.js.map +1 -0
  126. package/lib/screenplay/models/Cookie.d.ts +104 -64
  127. package/lib/screenplay/models/Cookie.d.ts.map +1 -0
  128. package/lib/screenplay/models/Cookie.js +110 -59
  129. package/lib/screenplay/models/Cookie.js.map +1 -1
  130. package/lib/screenplay/models/CookieData.d.ts +20 -58
  131. package/lib/screenplay/models/CookieData.d.ts.map +1 -0
  132. package/lib/{input → screenplay/models}/Key.d.ts +13 -9
  133. package/lib/screenplay/models/Key.d.ts.map +1 -0
  134. package/lib/{input → screenplay/models}/Key.js +16 -13
  135. package/lib/screenplay/models/Key.js.map +1 -0
  136. package/lib/screenplay/models/Locator.d.ts +29 -8
  137. package/lib/screenplay/models/Locator.d.ts.map +1 -0
  138. package/lib/screenplay/models/Locator.js +53 -7
  139. package/lib/screenplay/models/Locator.js.map +1 -1
  140. package/lib/screenplay/models/Page.d.ts +398 -36
  141. package/lib/screenplay/models/Page.d.ts.map +1 -0
  142. package/lib/screenplay/models/Page.js +209 -4
  143. package/lib/screenplay/models/Page.js.map +1 -1
  144. package/lib/screenplay/models/PageElement.d.ts +77 -5
  145. package/lib/screenplay/models/PageElement.d.ts.map +1 -0
  146. package/lib/screenplay/models/PageElement.js +29 -7
  147. package/lib/screenplay/models/PageElement.js.map +1 -1
  148. package/lib/screenplay/models/PageElements.d.ts +16 -3
  149. package/lib/screenplay/models/PageElements.d.ts.map +1 -0
  150. package/lib/screenplay/models/PageElements.js +21 -8
  151. package/lib/screenplay/models/PageElements.js.map +1 -1
  152. package/lib/screenplay/models/RootLocator.d.ts +25 -0
  153. package/lib/screenplay/models/RootLocator.d.ts.map +1 -0
  154. package/lib/screenplay/models/RootLocator.js +52 -0
  155. package/lib/screenplay/models/RootLocator.js.map +1 -0
  156. package/lib/screenplay/models/SelectOption.d.ts +25 -0
  157. package/lib/screenplay/models/SelectOption.d.ts.map +1 -0
  158. package/lib/screenplay/models/SelectOption.js +37 -0
  159. package/lib/screenplay/models/SelectOption.js.map +1 -0
  160. package/lib/screenplay/models/Switchable.d.ts +23 -0
  161. package/lib/screenplay/models/Switchable.d.ts.map +1 -0
  162. package/lib/screenplay/{interactions/WaitBuilder.js → models/Switchable.js} +1 -1
  163. package/lib/screenplay/models/Switchable.js.map +1 -0
  164. package/lib/screenplay/models/SwitchableOrigin.d.ts +18 -0
  165. package/lib/screenplay/models/SwitchableOrigin.d.ts.map +1 -0
  166. package/lib/screenplay/{interactions/EnterBuilder.js → models/SwitchableOrigin.js} +1 -1
  167. package/lib/screenplay/models/SwitchableOrigin.js.map +1 -0
  168. package/lib/screenplay/models/dialogs/AbsentModalDialog.d.ts +15 -0
  169. package/lib/screenplay/models/dialogs/AbsentModalDialog.d.ts.map +1 -0
  170. package/lib/screenplay/models/dialogs/AbsentModalDialog.js +24 -0
  171. package/lib/screenplay/models/dialogs/AbsentModalDialog.js.map +1 -0
  172. package/lib/screenplay/models/dialogs/AcceptedModalDialog.d.ts +17 -0
  173. package/lib/screenplay/models/dialogs/AcceptedModalDialog.d.ts.map +1 -0
  174. package/lib/screenplay/models/dialogs/AcceptedModalDialog.js +29 -0
  175. package/lib/screenplay/models/dialogs/AcceptedModalDialog.js.map +1 -0
  176. package/lib/screenplay/models/dialogs/DismissedModalDialog.d.ts +17 -0
  177. package/lib/screenplay/models/dialogs/DismissedModalDialog.d.ts.map +1 -0
  178. package/lib/screenplay/models/dialogs/DismissedModalDialog.js +29 -0
  179. package/lib/screenplay/models/dialogs/DismissedModalDialog.js.map +1 -0
  180. package/lib/screenplay/models/dialogs/ModalDialog.d.ts +168 -0
  181. package/lib/screenplay/models/dialogs/ModalDialog.d.ts.map +1 -0
  182. package/lib/screenplay/models/dialogs/ModalDialog.js +174 -0
  183. package/lib/screenplay/models/dialogs/ModalDialog.js.map +1 -0
  184. package/lib/screenplay/models/dialogs/ModalDialogHandler.d.ts +38 -0
  185. package/lib/screenplay/models/dialogs/ModalDialogHandler.d.ts.map +1 -0
  186. package/lib/screenplay/models/dialogs/ModalDialogHandler.js +30 -0
  187. package/lib/screenplay/models/dialogs/ModalDialogHandler.js.map +1 -0
  188. package/lib/screenplay/models/dialogs/index.d.ts +6 -0
  189. package/lib/screenplay/models/dialogs/index.d.ts.map +1 -0
  190. package/lib/screenplay/models/dialogs/index.js +22 -0
  191. package/lib/screenplay/models/dialogs/index.js.map +1 -0
  192. package/lib/screenplay/models/index.d.ts +9 -1
  193. package/lib/screenplay/models/index.d.ts.map +1 -0
  194. package/lib/screenplay/models/index.js +13 -2
  195. package/lib/screenplay/models/index.js.map +1 -1
  196. package/lib/screenplay/models/selectors/By.d.ts +38 -0
  197. package/lib/screenplay/models/selectors/By.d.ts.map +1 -0
  198. package/lib/screenplay/models/selectors/By.js +43 -0
  199. package/lib/screenplay/models/selectors/By.js.map +1 -1
  200. package/lib/screenplay/models/selectors/ByCss.d.ts +8 -0
  201. package/lib/screenplay/models/selectors/ByCss.d.ts.map +1 -0
  202. package/lib/screenplay/models/selectors/ByCss.js +7 -0
  203. package/lib/screenplay/models/selectors/ByCss.js.map +1 -1
  204. package/lib/screenplay/models/selectors/ByCssContainingText.d.ts +9 -0
  205. package/lib/screenplay/models/selectors/ByCssContainingText.d.ts.map +1 -0
  206. package/lib/screenplay/models/selectors/ByCssContainingText.js +8 -0
  207. package/lib/screenplay/models/selectors/ByCssContainingText.js.map +1 -1
  208. package/lib/screenplay/models/selectors/ByDeepCss.d.ts +14 -0
  209. package/lib/screenplay/models/selectors/ByDeepCss.d.ts.map +1 -0
  210. package/lib/screenplay/models/selectors/ByDeepCss.js +20 -0
  211. package/lib/screenplay/models/selectors/ByDeepCss.js.map +1 -0
  212. package/lib/screenplay/models/selectors/ById.d.ts +8 -0
  213. package/lib/screenplay/models/selectors/ById.d.ts.map +1 -0
  214. package/lib/screenplay/models/selectors/ById.js +7 -0
  215. package/lib/screenplay/models/selectors/ById.js.map +1 -1
  216. package/lib/screenplay/models/selectors/ByTagName.d.ts +8 -0
  217. package/lib/screenplay/models/selectors/ByTagName.d.ts.map +1 -0
  218. package/lib/screenplay/models/selectors/ByTagName.js +7 -0
  219. package/lib/screenplay/models/selectors/ByTagName.js.map +1 -1
  220. package/lib/screenplay/models/selectors/ByXPath.d.ts +8 -0
  221. package/lib/screenplay/models/selectors/ByXPath.d.ts.map +1 -0
  222. package/lib/screenplay/models/selectors/ByXPath.js +7 -0
  223. package/lib/screenplay/models/selectors/ByXPath.js.map +1 -1
  224. package/lib/screenplay/models/selectors/Selector.d.ts +6 -0
  225. package/lib/screenplay/models/selectors/Selector.d.ts.map +1 -0
  226. package/lib/screenplay/models/selectors/Selector.js +6 -1
  227. package/lib/screenplay/models/selectors/Selector.js.map +1 -1
  228. package/lib/screenplay/models/selectors/index.d.ts +2 -0
  229. package/lib/screenplay/models/selectors/index.d.ts.map +1 -0
  230. package/lib/screenplay/models/selectors/index.js +6 -1
  231. package/lib/screenplay/models/selectors/index.js.map +1 -1
  232. package/lib/screenplay/questions/Attribute.d.ts +115 -67
  233. package/lib/screenplay/questions/Attribute.d.ts.map +1 -0
  234. package/lib/screenplay/questions/Attribute.js +128 -74
  235. package/lib/screenplay/questions/Attribute.js.map +1 -1
  236. package/lib/screenplay/questions/CssClasses.d.ts +124 -79
  237. package/lib/screenplay/questions/CssClasses.d.ts.map +1 -0
  238. package/lib/screenplay/questions/CssClasses.js +132 -83
  239. package/lib/screenplay/questions/CssClasses.js.map +1 -1
  240. package/lib/screenplay/questions/LastScriptExecution.d.ts +42 -6
  241. package/lib/screenplay/questions/LastScriptExecution.d.ts.map +1 -0
  242. package/lib/screenplay/questions/LastScriptExecution.js +45 -7
  243. package/lib/screenplay/questions/LastScriptExecution.js.map +1 -1
  244. package/lib/screenplay/questions/Selected.d.ts +202 -171
  245. package/lib/screenplay/questions/Selected.d.ts.map +1 -0
  246. package/lib/screenplay/questions/Selected.js +225 -186
  247. package/lib/screenplay/questions/Selected.js.map +1 -1
  248. package/lib/screenplay/questions/Text.d.ts +101 -82
  249. package/lib/screenplay/questions/Text.d.ts.map +1 -0
  250. package/lib/screenplay/questions/Text.js +143 -92
  251. package/lib/screenplay/questions/Text.js.map +1 -1
  252. package/lib/screenplay/questions/Value.d.ts +77 -44
  253. package/lib/screenplay/questions/Value.d.ts.map +1 -0
  254. package/lib/screenplay/questions/Value.js +84 -47
  255. package/lib/screenplay/questions/Value.js.map +1 -1
  256. package/lib/screenplay/questions/index.d.ts +1 -0
  257. package/lib/screenplay/questions/index.d.ts.map +1 -0
  258. package/lib/screenplay/questions/index.js +5 -1
  259. package/lib/screenplay/questions/index.js.map +1 -1
  260. package/lib/scripts/index.d.ts +2 -0
  261. package/lib/scripts/index.d.ts.map +1 -0
  262. package/lib/{input → scripts}/index.js +6 -2
  263. package/lib/scripts/index.js.map +1 -0
  264. package/lib/scripts/isVisible.d.ts +2 -0
  265. package/lib/scripts/isVisible.d.ts.map +1 -0
  266. package/lib/scripts/isVisible.js +96 -0
  267. package/lib/scripts/isVisible.js.map +1 -0
  268. package/lib/stage/crew/index.d.ts +1 -0
  269. package/lib/stage/crew/index.d.ts.map +1 -0
  270. package/lib/stage/crew/index.js +5 -1
  271. package/lib/stage/crew/index.js.map +1 -1
  272. package/lib/stage/crew/photographer/Photographer.d.ts +126 -39
  273. package/lib/stage/crew/photographer/Photographer.d.ts.map +1 -0
  274. package/lib/stage/crew/photographer/Photographer.js +161 -42
  275. package/lib/stage/crew/photographer/Photographer.js.map +1 -1
  276. package/lib/stage/crew/photographer/index.d.ts +1 -0
  277. package/lib/stage/crew/photographer/index.d.ts.map +1 -0
  278. package/lib/stage/crew/photographer/index.js +5 -1
  279. package/lib/stage/crew/photographer/index.js.map +1 -1
  280. package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.d.ts +13 -12
  281. package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.d.ts.map +1 -0
  282. package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js +22 -33
  283. package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js.map +1 -1
  284. package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.d.ts +8 -8
  285. package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.d.ts.map +1 -0
  286. package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js +7 -8
  287. package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js.map +1 -1
  288. package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.d.ts +8 -7
  289. package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.d.ts.map +1 -0
  290. package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.js +7 -7
  291. package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.d.ts +8 -8
  292. package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.d.ts.map +1 -0
  293. package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js +7 -8
  294. package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js.map +1 -1
  295. package/lib/stage/crew/photographer/strategies/index.d.ts +1 -0
  296. package/lib/stage/crew/photographer/strategies/index.d.ts.map +1 -0
  297. package/lib/stage/crew/photographer/strategies/index.js +5 -1
  298. package/lib/stage/crew/photographer/strategies/index.js.map +1 -1
  299. package/lib/stage/index.d.ts +1 -0
  300. package/lib/stage/index.d.ts.map +1 -0
  301. package/lib/stage/index.js +5 -1
  302. package/lib/stage/index.js.map +1 -1
  303. package/package.json +20 -43
  304. package/src/errors/BrowserWindowClosedError.ts +17 -0
  305. package/src/errors/CookieMissingError.ts +10 -0
  306. package/src/errors/ModalDialogObstructsScreenshotError.ts +17 -0
  307. package/src/errors/index.ts +2 -0
  308. package/src/expectations/index.ts +0 -1
  309. package/src/expectations/isActive.ts +23 -12
  310. package/src/expectations/isClickable.ts +22 -21
  311. package/src/expectations/isEnabled.ts +23 -9
  312. package/src/expectations/isSelected.ts +20 -10
  313. package/src/expectations/isVisible.ts +23 -9
  314. package/src/index.ts +0 -1
  315. package/src/screenplay/abilities/BrowseTheWeb.ts +95 -87
  316. package/src/screenplay/abilities/index.ts +0 -1
  317. package/src/screenplay/interactions/Clear.ts +75 -63
  318. package/src/screenplay/interactions/Click.ts +43 -54
  319. package/src/screenplay/interactions/DoubleClick.ts +66 -71
  320. package/src/screenplay/interactions/Enter.ts +41 -53
  321. package/src/screenplay/interactions/ExecuteScript.ts +207 -220
  322. package/src/screenplay/interactions/Hover.ts +42 -54
  323. package/src/screenplay/interactions/Navigate.ts +129 -156
  324. package/src/screenplay/interactions/PageElementInteraction.ts +14 -34
  325. package/src/screenplay/interactions/Press.ts +78 -69
  326. package/src/screenplay/interactions/RightClick.ts +61 -69
  327. package/src/screenplay/interactions/Scroll.ts +48 -71
  328. package/src/screenplay/interactions/Select.ts +229 -269
  329. package/src/screenplay/interactions/Switch.ts +123 -179
  330. package/src/screenplay/interactions/TakeScreenshot.ts +31 -57
  331. package/src/screenplay/interactions/index.ts +1 -3
  332. package/src/screenplay/models/BrowserCapabilities.ts +26 -0
  333. package/src/screenplay/models/BrowsingSession.ts +115 -0
  334. package/src/screenplay/models/Cookie.ts +115 -73
  335. package/src/screenplay/models/CookieData.ts +20 -58
  336. package/src/{input → screenplay/models}/Key.ts +12 -9
  337. package/src/screenplay/models/Locator.ts +43 -9
  338. package/src/screenplay/models/Page.ts +438 -37
  339. package/src/screenplay/models/PageElement.ts +92 -12
  340. package/src/screenplay/models/PageElements.ts +23 -9
  341. package/src/screenplay/models/RootLocator.ts +30 -0
  342. package/src/screenplay/models/SelectOption.ts +38 -0
  343. package/src/screenplay/models/Switchable.ts +24 -0
  344. package/src/screenplay/models/SwitchableOrigin.ts +18 -0
  345. package/src/screenplay/models/dialogs/AbsentModalDialog.ts +22 -0
  346. package/src/screenplay/models/dialogs/AcceptedModalDialog.ts +27 -0
  347. package/src/screenplay/models/dialogs/DismissedModalDialog.ts +27 -0
  348. package/src/screenplay/models/dialogs/ModalDialog.ts +200 -0
  349. package/src/screenplay/models/dialogs/ModalDialogHandler.ts +50 -0
  350. package/src/screenplay/models/dialogs/index.ts +5 -0
  351. package/src/screenplay/models/index.ts +8 -1
  352. package/src/screenplay/models/selectors/By.ts +45 -0
  353. package/src/screenplay/models/selectors/ByCss.ts +7 -0
  354. package/src/screenplay/models/selectors/ByCssContainingText.ts +8 -0
  355. package/src/screenplay/models/selectors/ByDeepCss.ts +15 -0
  356. package/src/screenplay/models/selectors/ById.ts +7 -0
  357. package/src/screenplay/models/selectors/ByTagName.ts +7 -0
  358. package/src/screenplay/models/selectors/ByXPath.ts +7 -0
  359. package/src/screenplay/models/selectors/Selector.ts +6 -1
  360. package/src/screenplay/models/selectors/index.ts +1 -0
  361. package/src/screenplay/questions/Attribute.ts +137 -76
  362. package/src/screenplay/questions/CssClasses.ts +135 -83
  363. package/src/screenplay/questions/LastScriptExecution.ts +45 -8
  364. package/src/screenplay/questions/Selected.ts +237 -191
  365. package/src/screenplay/questions/Text.ts +161 -96
  366. package/src/screenplay/questions/Value.ts +88 -48
  367. package/src/scripts/index.ts +1 -0
  368. package/src/scripts/isVisible.ts +113 -0
  369. package/src/stage/crew/photographer/Photographer.ts +142 -41
  370. package/src/stage/crew/photographer/strategies/PhotoTakingStrategy.ts +27 -42
  371. package/src/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.ts +7 -8
  372. package/src/stage/crew/photographer/strategies/TakePhotosOfFailures.ts +7 -7
  373. package/src/stage/crew/photographer/strategies/TakePhotosOfInteractions.ts +7 -8
  374. package/tsconfig.build.json +14 -0
  375. package/lib/expectations/ElementExpectation.d.ts +0 -83
  376. package/lib/expectations/ElementExpectation.js +0 -102
  377. package/lib/expectations/ElementExpectation.js.map +0 -1
  378. package/lib/input/Key.js.map +0 -1
  379. package/lib/input/index.d.ts +0 -1
  380. package/lib/input/index.js.map +0 -1
  381. package/lib/screenplay/abilities/BrowserCapabilities.d.ts +0 -5
  382. package/lib/screenplay/abilities/BrowserCapabilities.js.map +0 -1
  383. package/lib/screenplay/interactions/EnterBuilder.d.ts +0 -25
  384. package/lib/screenplay/interactions/EnterBuilder.js.map +0 -1
  385. package/lib/screenplay/interactions/PressBuilder.d.ts +0 -26
  386. package/lib/screenplay/interactions/PressBuilder.js +0 -3
  387. package/lib/screenplay/interactions/PressBuilder.js.map +0 -1
  388. package/lib/screenplay/interactions/SelectBuilder.d.ts +0 -33
  389. package/lib/screenplay/interactions/SelectBuilder.js +0 -3
  390. package/lib/screenplay/interactions/SelectBuilder.js.map +0 -1
  391. package/lib/screenplay/interactions/Wait.d.ts +0 -143
  392. package/lib/screenplay/interactions/Wait.js +0 -238
  393. package/lib/screenplay/interactions/Wait.js.map +0 -1
  394. package/lib/screenplay/interactions/WaitBuilder.d.ts +0 -32
  395. package/lib/screenplay/interactions/WaitBuilder.js.map +0 -1
  396. package/lib/screenplay/models/ModalDialog.d.ts +0 -9
  397. package/lib/screenplay/models/ModalDialog.js +0 -14
  398. package/lib/screenplay/models/ModalDialog.js.map +0 -1
  399. package/lib/screenplay/questions/ElementQuestion.d.ts +0 -33
  400. package/lib/screenplay/questions/ElementQuestion.js +0 -53
  401. package/lib/screenplay/questions/ElementQuestion.js.map +0 -1
  402. package/src/expectations/ElementExpectation.ts +0 -108
  403. package/src/input/index.ts +0 -1
  404. package/src/screenplay/abilities/BrowserCapabilities.ts +0 -5
  405. package/src/screenplay/interactions/EnterBuilder.ts +0 -28
  406. package/src/screenplay/interactions/PressBuilder.ts +0 -29
  407. package/src/screenplay/interactions/SelectBuilder.ts +0 -36
  408. package/src/screenplay/interactions/Wait.ts +0 -260
  409. package/src/screenplay/interactions/WaitBuilder.ts +0 -34
  410. package/src/screenplay/models/ModalDialog.ts +0 -19
  411. package/src/screenplay/questions/ElementQuestion.ts +0 -58
  412. package/tsconfig.eslint.json +0 -10
  413. /package/lib/screenplay/{abilities → models}/BrowserCapabilities.js +0 -0
@@ -1,321 +1,281 @@
1
- import { Answerable, q } from '@serenity-js/core';
2
- import { asyncMap, commaSeparated, formatted } from '@serenity-js/core/lib/io';
3
- import { inspected } from '@serenity-js/core/lib/io/inspected';
1
+ import { Answerable, d } from '@serenity-js/core';
2
+ import { asyncMap, commaSeparated } from '@serenity-js/core/lib/io';
3
+ import { stringified } from '@serenity-js/core/lib/io/stringified';
4
4
  import { Interaction } from '@serenity-js/core/lib/screenplay';
5
5
 
6
- import { By, PageElement, PageElements } from '../models';
7
- import { SelectBuilder } from './SelectBuilder';
6
+ import { PageElement, SelectOption } from '../models';
8
7
 
9
8
  /**
10
- * @desc
11
- * Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor} to
12
- * select an option from a [HTML `<select>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select),
13
- * either by its display name, or by value.
9
+ * Instructs an {@apilink Actor|actor} who has the {@apilink Ability|ability} to {@apilink BrowseTheWeb}
10
+ * to select an option from a [HTML `<select>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select),
11
+ * either by its display name, or by value.
14
12
  *
15
- * @see {@link Selected}
13
+ * ## Learn more
14
+ * - {@apilink Selected}
15
+ *
16
+ * @group Activities
16
17
  */
17
18
  export class Select {
18
19
 
19
20
  /**
20
- * @desc
21
- * Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
22
- * with a [`value`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value)
23
- * of a single [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
24
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
25
- *
26
- * @example <caption>Example widget</caption>
27
- * <select data-test='countries'>
28
- * <option value='UK'>United Kingdom</option>
29
- * <option value='PL'>Poland</option>
30
- * <option value='US'>United States</option>
31
- * </select>
32
- *
33
- * @example <caption>Lean Page Object describing the widget</caption>
34
- * import { Target } from '@serenity-js/protractor';
35
- * import { browser, by } from 'protractor';
36
- *
37
- * class Countries {
38
- * static dropdown = Target.the('countries dropdown')
39
- * .located(by.css('[data-test="countries"]'));
40
- * }
41
- *
42
- * @example <caption>Retrieving the selected value</caption>
43
- * import { actorCalled } from '@serenity-js/core';
44
- * import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
45
- * import { Ensure, equals } from '@serenity-js/assertions';
46
- * import { protractor } from 'protractor';
47
- *
48
- * actorCalled('Nick')
49
- * .whoCan(BrowseTheWeb.using(protractor.browser))
50
- * .attemptsTo(
51
- * Select.value('UK').from(Countries.dropdown),
52
- * Ensure.that(Selected.valueOf(Countries.dropdown), equals('UK')),
53
- * );
54
- *
55
- * @param {Answerable<string>} value
21
+ * Instantiates an {@apilink Interaction|interaction}
22
+ * that instructs the {@apilink Actor|actor}
23
+ * to select a single [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
24
+ * with a given [`value`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value).,
25
+ *
26
+ * #### Example widget
27
+ *
28
+ * ```html
29
+ * <select data-test='countries'>
30
+ * <option value='UK'>United Kingdom</option>
31
+ * <option value='PL'>Poland</option>
32
+ * <option value='US'>United States</option>
33
+ * </select>
34
+ * ```
35
+ *
36
+ * #### Lean Page Object describing the widget
37
+ *
38
+ * ```ts
39
+ * import { By, PageElement } from '@serenity-js/web'
40
+ *
41
+ * class Countries {
42
+ * static dropdown = () =>
43
+ * PageElement.located(By.css('[data-test="countries"]'))
44
+ * .describedAs('countries dropdown')
45
+ * }
46
+ * ```
47
+ *
48
+ * #### Retrieving the selected value
49
+ *
50
+ * ```ts
51
+ * import { actorCalled } from '@serenity-js/core'
52
+ * import { Select, Selected } from '@serenity-js/web';
53
+ * import { Ensure, equals } from '@serenity-js/assertions'
54
+ *
55
+ * await actorCalled('Nick')
56
+ * .attemptsTo(
57
+ * Select.value('UK').from(Countries.dropdown()),
58
+ * Ensure.that(Selected.valueOf(Countries.dropdown()), equals('UK')),
59
+ * )
60
+ * ```
61
+ *
62
+ * #### Learn more
63
+ * - {@apilink Selected.valueOf}
64
+ * - {@apilink PageElement}
65
+ *
66
+ * @param value
56
67
  * A value of the [`option` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
57
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
58
- *
59
- * @returns {SelectBuilder}
60
- *
61
- * @see {@link Selected.valueOf}
62
- * @see {@link BrowseTheWeb}
63
- * @see {@link Target}
64
- * @see {@link @serenity-js/assertions~Ensure}
65
- * @see {@link @serenity-js/assertions/lib/expectations~equals}
68
+ * for the {@apilink Actor} to select
66
69
  */
67
- static value(value: Answerable<string>): SelectBuilder {
70
+ static value(value: Answerable<string>): { from: (pageElement: Answerable<PageElement>) => Interaction } {
68
71
  return {
69
72
  from: (pageElement: Answerable<PageElement>): Interaction =>
70
- Interaction.where(formatted `#actor selects value ${ value } from ${ pageElement }`, async actor => {
71
- return PageElement.located(By.css(q`option[value=${ value }]`))
72
- .of(pageElement)
73
- .click()
74
- .performAs(actor);
73
+ Interaction.where(d`#actor selects value ${ value } from ${ pageElement }`, async actor => {
74
+ const element = await actor.answer(pageElement);
75
+ const desiredValue = await actor.answer(value);
76
+
77
+ await element.selectOptions(SelectOption.withValue(desiredValue));
75
78
  }),
76
79
  };
77
80
  }
78
81
 
79
82
  /**
80
- * @desc
81
- * Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
82
- * with [`value`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value)
83
- * of multiple [`<option>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
84
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
85
- *
86
- * @example <caption>Example widget</caption>
87
- * <select multiple data-test='countries'>
88
- * <option value='UK'>United Kingdom</option>
89
- * <option value='PL'>Poland</option>
90
- * <option value='US'>United States</option>
91
- * </select>
92
- *
93
- * @example <caption>Lean Page Object describing the widget</caption>
94
- * import { Target } from '@serenity-js/protractor';
95
- * import { browser, by } from 'protractor';
96
- *
97
- * class Countries {
98
- * static dropdown = Target.the('countries dropdown')
99
- * .located(by.css('[data-test="countries"]'));
100
- * }
101
- *
102
- * @example <caption>Retrieving the selected value</caption>
103
- * import { actorCalled } from '@serenity-js/core';
104
- * import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
105
- * import { Ensure, equals } from '@serenity-js/assertions';
106
- * import { protractor } from 'protractor';
107
- *
108
- * actorCalled('Nick')
109
- * .whoCan(BrowseTheWeb.using(protractor.browser))
110
- * .attemptsTo(
111
- * Select.values('UK').from(Countries.dropdown),
112
- * Ensure.that(Selected.valuesOf(Countries.dropdown), equals([ 'UK' ])),
113
- * );
114
- *
115
- * @param {Array<Answerable<string[] | string>>} values
116
- * Values of the [`option` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
117
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
83
+ * Instantiates an {@apilink Interaction|interaction}
84
+ * that instructs the {@apilink Actor|actor}
85
+ * to select multiple [`<option>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
86
+ * identified by their [`value`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value).
87
+ *
88
+ * #### Example widget
89
+ *
90
+ * ```ts
91
+ * <select multiple data-test='countries'>
92
+ * <option value='UK'>United Kingdom</option>
93
+ * <option value='PL'>Poland</option>
94
+ * <option value='US'>United States</option>
95
+ * </select>
96
+ * ```
97
+ *
98
+ * #### Lean Page Object describing the widget
99
+ *
100
+ * ```ts
101
+ * import { By, PageElement } from '@serenity-js/web'
118
102
  *
119
- * @returns {SelectBuilder}
103
+ * class Countries {
104
+ * static dropdown = () =>
105
+ * PageElement.located(By.css('[data-test="countries"]'))
106
+ * .describedAs('countries dropdown')
107
+ * }
108
+ * ```
120
109
  *
121
- * @see {@link Selected.valuesOf}
122
- * @see {@link BrowseTheWeb}
123
- * @see {@link Target}
124
- * @see {@link @serenity-js/assertions~Ensure}
125
- * @see {@link @serenity-js/assertions/lib/expectations~equals}
110
+ * #### Retrieving the selected value
111
+ *
112
+ * ```ts
113
+ * import { actorCalled } from '@serenity-js/core'
114
+ * import { Select, Selected } from '@serenity-js/web'
115
+ * import { Ensure, equals } from '@serenity-js/assertions'
116
+ *
117
+ * await actorCalled('Nick')
118
+ * .attemptsTo(
119
+ * Select.values('UK').from(Countries.dropdown()),
120
+ * Ensure.that(Selected.valuesOf(Countries.dropdown()), equals([ 'UK' ])),
121
+ * )
122
+ * ```
123
+ *
124
+ * #### Learn more
125
+ *
126
+ * - {@apilink Selected.valuesOf}
127
+ * - {@apilink PageElement}
128
+ *
129
+ * @param values
130
+ * Values of the [`option` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
131
+ * for the {@apilink Actor} to select
126
132
  */
127
- static values(...values: Array<Answerable<string[] | string>>): SelectBuilder {
133
+ static values(...values: Array<Answerable<string[] | string>>): { from: (pageElement: Answerable<PageElement>) => Interaction } {
128
134
  return {
129
135
  from: (pageElement: Answerable<PageElement>): Interaction =>
130
- Interaction.where(`#actor selects values ${ commaSeparated(values.flat(), item => inspected(item, { inline: true })) } from ${ inspected(pageElement, { inline: true }) }`, async actor => {
136
+ Interaction.where(`#actor selects values ${ commaSeparated(values.flat(), item => stringified(item, { inline: true })) } from ${ stringified(pageElement, { inline: true }) }`, async actor => {
131
137
 
132
- const answers = await asyncMap(values, value => actor.answer(value));
138
+ const answers = await asyncMap(values, value => actor.answer(value));
133
139
  const desiredValues = answers.flat();
134
140
 
135
- const options: PageElement[] = await PageElements.located(By.css(`option`))
136
- .of(pageElement)
137
- .answeredBy(actor);
141
+ const element = await actor.answer(pageElement);
138
142
 
139
- for (const option of options) {
140
- const shouldSelect = await optionsToSelect(hasValueEqualOneOf(desiredValues))(option);
141
- if (shouldSelect) {
142
- await option.click();
143
- }
144
- }
143
+ await element.selectOptions(... desiredValues.map(value => SelectOption.withValue(value)));
145
144
  }),
146
145
  };
147
146
  }
148
147
 
149
148
  /**
150
- * @desc
151
- * Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
152
- * with a single [`option`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
153
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
154
- *
155
- * @example <caption>Example widget</caption>
156
- * <select data-test='countries'>
157
- * <option value='UK'>United Kingdom</option>
158
- * <option value='PL'>Poland</option>
159
- * <option value='US'>United States</option>
160
- * </select>
161
- *
162
- * @example <caption>Lean Page Object describing the widget</caption>
163
- * import { Target } from '@serenity-js/protractor';
164
- * import { browser, by } from 'protractor';
165
- *
166
- * class Countries {
167
- * static dropdown = Target.the('countries dropdown')
168
- * .located(by.css('[data-test="countries"]'));
169
- * }
170
- *
171
- * @example <caption>Retrieving the selected value</caption>
172
- * import { actorCalled } from '@serenity-js/core';
173
- * import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
174
- * import { Ensure, equals } from '@serenity-js/assertions';
175
- * import { protractor } from 'protractor';
176
- *
177
- * actorCalled('Nick')
178
- * .whoCan(BrowseTheWeb.using(protractor.browser))
179
- * .attemptsTo(
180
- * Select.option('Poland').from(Countries.dropdown),
181
- * Ensure.that(
182
- * Selected.optionIn(Countries.dropdown),
183
- * equals('Poland')
184
- * ),
185
- * );
186
- *
187
- * @param {Answerable<string>} value
149
+ * Instantiates an {@apilink Interaction|interaction}
150
+ * that instructs the {@apilink Actor|actor}
151
+ * to select a single [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
152
+ * with a given description.
153
+ *
154
+ * #### Example widget
155
+ *
156
+ * ```html
157
+ * <select data-test='countries'>
158
+ * <option value='UK'>United Kingdom</option>
159
+ * <option value='PL'>Poland</option>
160
+ * <option value='US'>United States</option>
161
+ * </select>
162
+ * ```
163
+ *
164
+ * #### Lean Page Object describing the widget
165
+ * ```ts
166
+ * import { By, PageElement } from '@serenity-js/by'
167
+ *
168
+ * class Countries {
169
+ * static dropdown = () =>
170
+ * PageElement.located(By.css('[data-test="countries"]'))
171
+ * .describedAs('countries dropdown')
172
+ * }
173
+ * ```
174
+ *
175
+ * #### Retrieving the selected value
176
+ *
177
+ * ```ts
178
+ * import { actorCalled } from '@serenity-js/core'
179
+ * import { Select, Selected } from '@serenity-js/web'
180
+ * import { Ensure, equals } from '@serenity-js/assertions'
181
+ *
182
+ * await actorCalled('Nick')
183
+ * .whoCan(BrowseTheWeb.using(protractor.browser))
184
+ * .attemptsTo(
185
+ * Select.option('Poland').from(Countries.dropdown()),
186
+ * Ensure.that(
187
+ * Selected.optionIn(Countries.dropdown()),
188
+ * equals('Poland')
189
+ * ),
190
+ * )
191
+ * ```
192
+ *
193
+ * #### Learn more
194
+ * - {@apilink Selected.optionIn}
195
+ * - {@apilink PageElement}
196
+ *
197
+ * @param value
188
198
  * Text of the [`option` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
189
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
190
- *
191
- * @returns {SelectBuilder}
192
- *
193
- * @see {@link Selected.optionIn}
194
- * @see {@link BrowseTheWeb}
195
- * @see {@link Target}
196
- * @see {@link @serenity-js/assertions~Ensure}
197
- * @see {@link @serenity-js/assertions/lib/expectations~equals}
199
+ * for the {@apilink Actor} to select
198
200
  */
199
- static option(value: Answerable<string>): SelectBuilder {
201
+ static option(value: Answerable<string>): { from: (pageElement: Answerable<PageElement>) => Interaction } {
200
202
  return {
201
203
  from: (pageElement: Answerable<PageElement>): Interaction =>
202
- Interaction.where(formatted `#actor selects ${ value } from ${ pageElement }`, async actor => {
203
- return PageElement.located(By.cssContainingText('option', value))
204
- .of(pageElement)
205
- .click()
206
- .performAs(actor);
204
+ Interaction.where(d`#actor selects ${ value } from ${ pageElement }`, async actor => {
205
+ const element = await actor.answer(pageElement);
206
+ const desiredLabel = await actor.answer(value);
207
+
208
+ await element.selectOptions(SelectOption.withLabel(desiredLabel));
207
209
  }),
208
210
  };
209
211
  }
210
212
 
211
213
  /**
212
- * @desc
213
- * Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
214
- * with [`option`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
215
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
216
- *
217
- * @example <caption>Example widget</caption>
218
- * <select multiple data-test='countries'>
219
- * <option value='UK'>United Kingdom</option>
220
- * <option value='PL'>Poland</option>
221
- * <option value='US'>United States</option>
222
- * </select>
223
- *
224
- * @example <caption>Lean Page Object describing the widget</caption>
225
- * import { Target } from '@serenity-js/protractor';
226
- * import { browser, by } from 'protractor';
227
- *
228
- * class Countries {
229
- * static dropdown = Target.the('countries dropdown')
230
- * .located(by.css('[data-test="countries"]'));
231
- * }
232
- *
233
- * @example <caption>Retrieving the selected value</caption>
234
- * import { actorCalled } from '@serenity-js/core';
235
- * import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
236
- * import { Ensure, equals } from '@serenity-js/assertions';
237
- * import { protractor } from 'protractor';
238
- *
239
- * actorCalled('Nick')
240
- * .whoCan(BrowseTheWeb.using(protractor.browser))
241
- * .attemptsTo(
242
- * Select.options('Poland', 'United States').from(Countries.dropdown),
243
- * Ensure.that(
244
- * Selected.optionsIn(Countries.dropdown),
245
- * equals([ 'Poland', 'United States' ])
246
- * ),
247
- * );
248
- *
249
- * @param {Array<Answerable<string[] | string>>} values
214
+ * Instantiates an {@apilink Interaction|interaction}
215
+ * that instructs the {@apilink Actor|actor}
216
+ * to select multiple [`<option>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
217
+ * identified by their descriptions.
218
+ *
219
+ * #### Example widget
220
+ *
221
+ * ```html
222
+ * <select multiple data-test='countries'>
223
+ * <option value='UK'>United Kingdom</option>
224
+ * <option value='PL'>Poland</option>
225
+ * <option value='US'>United States</option>
226
+ * </select>
227
+ * ```
228
+ *
229
+ * #### Lean Page Object describing the widget
230
+ *
231
+ * ```ts
232
+ * import { By, PageElement } from '@serenity-js/web'
233
+ *
234
+ * class Countries {
235
+ * static dropdown = () =>
236
+ * PageElement.located(By.css('[data-test="countries"]'))
237
+ * .describedAs('countries dropdown')
238
+ * }
239
+ * ```
240
+ *
241
+ * ##### Retrieving the selected value
242
+ *
243
+ * ```ts
244
+ * import { actorCalled } from '@serenity-js/core'
245
+ * import { Select, Selected } from '@serenity-js/web'
246
+ * import { Ensure, equals } from '@serenity-js/assertions'
247
+ *
248
+ * await actorCalled('Nick')
249
+ * .whoCan(BrowseTheWeb.using(protractor.browser))
250
+ * .attemptsTo(
251
+ * Select.options('Poland', 'United States').from(Countries.dropdown()),
252
+ * Ensure.that(
253
+ * Selected.optionsIn(Countries.dropdown()),
254
+ * equals([ 'Poland', 'United States' ])
255
+ * ),
256
+ * )
257
+ * ```
258
+ *
259
+ * #### Learn more
260
+ * - {@apilink Selected.optionsIn}
261
+ * - {@apilink PageElement}
262
+ *
263
+ * @param values
250
264
  * Text of the [`option` elements ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
251
- * for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
252
- *
253
- * @returns {SelectBuilder}
254
- *
255
- * @see {@link Selected.optionsIn}
256
- * @see {@link BrowseTheWeb}
257
- * @see {@link Target}
258
- * @see {@link @serenity-js/assertions~Ensure}
259
- * @see {@link @serenity-js/assertions/lib/expectations~equals}
265
+ * for the {@apilink Actor} to select
260
266
  */
261
- static options(...values: Array<Answerable<string[] | string>>): SelectBuilder {
267
+ static options(...values: Array<Answerable<string[] | string>>): { from: (pageElement: Answerable<PageElement>) => Interaction } {
262
268
  return {
263
269
  from: (pageElement: Answerable<PageElement>): Interaction =>
264
- Interaction.where(`#actor selects ${ commaSeparated(values.flat(), item => inspected(item, { inline: true })) } from ${ inspected(pageElement, { inline: true }) }`, async actor => {
270
+ Interaction.where(`#actor selects ${ commaSeparated(values.flat(), item => stringified(item, { inline: true })) } from ${ stringified(pageElement, { inline: true }) }`, async actor => {
265
271
 
266
- const answers = await asyncMap(values, value => actor.answer(value));
267
- const desiredOptions = answers.flat();
272
+ const answers = await asyncMap(values, value => actor.answer(value));
273
+ const desiredLabels = answers.flat();
268
274
 
269
- const options: PageElement[] = await PageElements.located(By.css(`option`)).of(pageElement).answeredBy(actor);
275
+ const element = await actor.answer(pageElement);
270
276
 
271
- for (const option of options) {
272
- const shouldSelect = await optionsToSelect(hasTextEqualOneOf(desiredOptions))(option);
273
- if (shouldSelect) {
274
- await option.click()
275
- }
276
- }
277
+ await element.selectOptions(... desiredLabels.map(label => SelectOption.withLabel(label)));
277
278
  }),
278
279
  };
279
280
  }
280
281
  }
281
-
282
- /** @package */
283
- function hasValueEqualOneOf(desiredValues: string[]): (option: PageElement) => Promise<boolean> {
284
- return async (option: PageElement) => {
285
-
286
- const value = await option.value()
287
-
288
- return desiredValues.includes(value);
289
- }
290
- }
291
-
292
- /** @package */
293
- function hasTextEqualOneOf(desiredValues: string[]): (option: PageElement) => Promise<boolean> {
294
- return async (option: PageElement) => {
295
-
296
- const value = await option.text()
297
-
298
- return desiredValues.includes(value);
299
- }
300
- }
301
-
302
- /** @package */
303
- function optionsToSelect(criterion: (option: PageElement) => Promise<boolean>) {
304
- return (option: PageElement) =>
305
- isAlreadySelected(option)
306
- .then(alreadySelected =>
307
- criterion(option).then(criterionMet =>
308
- xor(alreadySelected, criterionMet)
309
- )
310
- );
311
- }
312
-
313
- /** @package */
314
- function isAlreadySelected(option: PageElement): Promise<boolean> {
315
- return option.isSelected();
316
- }
317
-
318
- /** @package */
319
- function xor(first: boolean, second: boolean): boolean {
320
- return first !== second;
321
- }