@serenity-js/web 3.0.0-rc.9 → 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 +329 -74
  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
@@ -2,163 +2,228 @@ import { Answerable, AnswersQuestions, d, MetaQuestion, Question, QuestionAdapte
2
2
  import { asyncMap } from '@serenity-js/core/lib/io';
3
3
 
4
4
  import { PageElement, PageElements } from '../models';
5
- import { ElementQuestion } from './ElementQuestion';
6
5
 
7
6
  /**
8
- * @desc
9
- * Resolves to the visible (i.e. not hidden by CSS) `innerText` of:
10
- * - a given {@link WebElement}, represented by Answerable<{@link @wdio/types~Element}>
11
- * - a group of {@link WebElement}s, represented by Answerable<{@link @wdio/types~ElementList}>
12
- *
13
- * The result includes the visible text of any sub-elements, without any leading or trailing whitespace.
14
- *
15
- * @example <caption>Example widget</caption>
16
- * <h1>Shopping list</h1>
17
- * <ul id="shopping-list">
18
- * <li>Coffee<li>
19
- * <li class="bought">Honey<li>
20
- * <li>Chocolate<li>
21
- * </ul>
22
- *
23
- * @example <caption>Retrieve text of a single element</caption>
24
- * import { actorCalled } from '@serenity-js/core';
25
- * import { Ensure, equals } from '@serenity-js/assertions';
26
- * import { BrowseTheWeb, by, Target, Text } from '@serenity-js/webdriverio';
27
- *
28
- * const header = () =>
29
- * Target.the('header').located(by.tagName('h1'))
30
- *
31
- * actorCalled('Lisa')
32
- * .whoCan(BrowseTheWeb.using(browser))
33
- * .attemptsTo(
34
- * Ensure.that(Text.of(header()), equals('Shopping list')),
35
- * )
36
- *
37
- * @example <caption>Retrieve text of a multiple elements</caption>
38
- * import { actorCalled } from '@serenity-js/core';
39
- * import { Ensure, equals } from '@serenity-js/assertions';
40
- * import { BrowseTheWeb, by, Target, Text } from '@serenity-js/webdriverio';
41
- *
42
- * const shoppingListItems = () =>
43
- * Target.the('shopping list items').located(by.css('#shopping-list li'))
44
- *
45
- * actorCalled('Lisa')
46
- * .whoCan(BrowseTheWeb.using(browser))
47
- * .attemptsTo(
48
- * Ensure.that(
49
- * Text.ofAll(shoppingListItems()),
50
- * equals([ 'Coffee', 'Honey', 'Chocolate' ])
51
- * ),
52
- * )
53
- *
54
- * @example <caption>Find element with matching text</caption>
55
- * import { actorCalled } from '@serenity-js/core';
56
- * import { contain, Ensure } from '@serenity-js/assertions';
57
- * import { BrowseTheWeb, by, CssClasses, Target, Text } from '@serenity-js/webdriverio';
58
- *
59
- * const shoppingListItemCalled = (name: string) =>
60
- * Target.the('shopping list items').located(by.css('#shopping-list li'))
61
- * .where(Text, equals(name))
62
- * .first()
63
- *
64
- * actorCalled('Lisa')
65
- * .whoCan(BrowseTheWeb.using(browser))
66
- * .attemptsTo(
67
- * Ensure.that(
68
- * CssClasses.of(shoppingListItemCalled('Honey)),
69
- * contain('bought')
70
- * ),
71
- * )
72
- *
73
- * @public
74
- * @see {@link Target}
7
+ * Uses the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
8
+ * the visible (i.e. not hidden by CSS) [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText) of:
9
+ * - a given {@apilink PageElement}
10
+ * - a group of {@apilink PageElements}
11
+ *
12
+ * The result includes the visible text of any sub-elements, without any leading or trailing whitespace.
13
+ *
14
+ * ## Example widget
15
+ *
16
+ * ```html
17
+ * <h1>Shopping list</h1>
18
+ * <ul id="shopping-list">
19
+ * <li>Coffee<li>
20
+ * <li class="bought">Honey<li>
21
+ * <li>Chocolate<li>
22
+ * </ul>
23
+ * ```
24
+ *
25
+ * ## Retrieve text of a single {@apilink PageElement}
26
+ *
27
+ * ```ts
28
+ * import { actorCalled } from '@serenity-js/core'
29
+ * import { Ensure, equals } from '@serenity-js/assertions'
30
+ * import { By, PageElement, Text } from '@serenity-js/web'
31
+ *
32
+ * const header = () =>
33
+ * PageElement.located(By.css('h1'))
34
+ * .describedAs('header')
35
+ *
36
+ * await actorCalled('Lisa')
37
+ * .whoCan(BrowseTheWebWithWebdriverIO.using(browser))
38
+ * .attemptsTo(
39
+ * Ensure.that(Text.of(header()), equals('Shopping list')),
40
+ * )
41
+ * ```
42
+ *
43
+ * ## Retrieve text of multiple {@apilink PageElements}
44
+ *
45
+ * ```ts
46
+ * import { actorCalled } from '@serenity-js/core'
47
+ * import { Ensure, equals } from '@serenity-js/assertions'
48
+ * import { By, PageElement, Text } from '@serenity-js/web'
49
+ *
50
+ * const shoppingListItems = () =>
51
+ * PageElements.located(By.css('#shopping-list li'))
52
+ * .describedAs('shopping list items')
53
+ *
54
+ * await actorCalled('Lisa')
55
+ * .attemptsTo(
56
+ * Ensure.that(
57
+ * Text.ofAll(shoppingListItems()),
58
+ * equals([ 'Coffee', 'Honey', 'Chocolate' ])
59
+ * ),
60
+ * )
61
+ * ```
62
+ *
63
+ * ## Using as filter in {@apilink PageElements|Page Element Query Language}
64
+ *
65
+ * ```ts
66
+ * import { actorCalled } from '@serenity-js/core'
67
+ * import { contain, Ensure } from '@serenity-js/assertions'
68
+ * import { By, CssClasses, PageElement, Text } from '@serenity-js/web'
69
+ *
70
+ * const shoppingListItemCalled = (name: string) =>
71
+ * PageElements.located(By.css('#shopping-list li'))
72
+ * .describedAs('shopping list items')
73
+ * .where(Text, equals(name))
74
+ * .first()
75
+ *
76
+ * await actorCalled('Lisa')
77
+ * .attemptsTo(
78
+ * Ensure.that(
79
+ * CssClasses.of(shoppingListItemCalled('Honey)),
80
+ * contain('bought')
81
+ * ),
82
+ * )
83
+ * ```
84
+ *
85
+ * ## Learn more
86
+ * - {@apilink BrowseTheWeb}
87
+ * - {@apilink MetaQuestion}
88
+ * - {@apilink QuestionAdapter}
89
+ * - {@apilink Question}
90
+ *
91
+ * @group Questions
75
92
  */
76
93
  export class Text {
77
94
 
78
95
  /**
79
- * @desc
80
- * Retrieves text of a single {@link WebElement},
81
- * represented by Answerable<{@link @wdio/types~Element}>.
96
+ * Instantiates a {@apilink Question} that uses
97
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
98
+ * the text of a single {@apilink PageElement}.
82
99
  *
83
- * @param {Answerable<PageElement>} element
84
- * @returns {Question<Promise<string>> & MetaQuestion<Answerable<PageElement>, Promise<string>>}
100
+ * #### Learn more
101
+ * - {@apilink MetaQuestion}
85
102
  *
86
- * @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
103
+ * @param pageElement
87
104
  */
88
- static of(element: Answerable<PageElement>):
105
+ static of(pageElement: Answerable<PageElement>):
89
106
  QuestionAdapter<string> & // eslint-disable-line @typescript-eslint/indent
90
107
  MetaQuestion<Answerable<PageElement>, Promise<string>> // eslint-disable-line @typescript-eslint/indent
91
108
  {
92
- return TextOfSingleElement.of(element);
109
+ return TextOfSingleElement.of(pageElement);
93
110
  }
94
111
 
95
112
  /**
96
- * @desc
97
- * Retrieves text of a group of {@link WebElement}s,
98
- * represented by Answerable<{@link @wdio/types~ElementList}>
113
+ * Instantiates a {@apilink Question} that uses
114
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
115
+ * the text of a group of {@apilink PageElements}.
99
116
  *
100
- * @param {Answerable<PageElement[]>} elements
101
- * @returns {Question<Promise<string[]>> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>}
117
+ * #### Learn more
118
+ * - {@apilink MetaQuestion}
102
119
  *
103
- * @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
120
+ * @param pageElements
104
121
  */
105
- static ofAll(elements: PageElements): QuestionAdapter<string[]> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>
106
- static ofAll(elements: Answerable<PageElement[]>): QuestionAdapter<string[]>
107
- static ofAll(elements: PageElements | Answerable<PageElement[]>): QuestionAdapter<string[]> {
108
- if (elements instanceof PageElements) {
109
- return TextOfMultipleElements.of(elements);
122
+ static ofAll(pageElements: PageElements): QuestionAdapter<string[]> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>
123
+ static ofAll(pageElements: Answerable<PageElement[]>): QuestionAdapter<string[]>
124
+ static ofAll(pageElements: PageElements | Answerable<PageElement[]>): QuestionAdapter<string[]> {
125
+ if (pageElements instanceof PageElements) {
126
+ return TextOfMultipleElements.of(pageElements);
110
127
  }
111
128
 
112
- return Question.about(d`the text of ${ elements }`, async actor => {
113
- const pageElements: PageElement[] = await actor.answer(elements);
129
+ return Question.about(d`the text of ${ pageElements }`, async actor => {
130
+ const elements: PageElement[] = await actor.answer(pageElements);
114
131
 
115
- return asyncMap(pageElements, element => element.text());
132
+ return asyncMap(elements, element => element.text());
116
133
  });
117
134
  }
118
135
  }
119
136
 
120
137
  class TextOfSingleElement
121
- extends ElementQuestion<Promise<string>>
138
+ extends Question<Promise<string>>
122
139
  implements MetaQuestion<Answerable<PageElement>, Promise<string>>
123
140
  {
141
+ /**
142
+ * @private
143
+ */
144
+ private subject: string;
145
+
124
146
  static of(element: Answerable<PageElement>): QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>> {
125
147
  return Question.createAdapter(new TextOfSingleElement(element)) as QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>>;
126
148
  }
127
149
 
128
- constructor(private readonly element: Answerable<PageElement>) {
129
- super(`the text of ${ element }`);
150
+ protected constructor(private readonly element: Answerable<PageElement>) {
151
+ super();
152
+ this.subject = d`the text of ${ element }`;
130
153
  }
131
154
 
132
155
  of(parent: Answerable<PageElement>): Question<Promise<string>> {
133
156
  return new TextOfSingleElement(PageElement.of(this.element, parent));
134
157
  }
135
158
 
159
+ /**
160
+ * @inheritDoc
161
+ */
136
162
  async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
137
163
  const element = await actor.answer(this.element);
138
164
 
139
165
  return element.text();
140
166
  }
167
+
168
+ /**
169
+ * @inheritDoc
170
+ */
171
+ describedAs(subject: string): this {
172
+ this.subject = subject;
173
+ return this;
174
+ }
175
+
176
+ /**
177
+ * @inheritDoc
178
+ */
179
+ toString(): string {
180
+ return this.subject;
181
+ }
141
182
  }
142
183
 
143
184
  class TextOfMultipleElements
144
- extends ElementQuestion<Promise<string[]>>
185
+ extends Question<Promise<string[]>>
145
186
  implements MetaQuestion<Answerable<PageElement>, Promise<string[]>>
146
187
  {
188
+ /**
189
+ * @private
190
+ */
191
+ private subject: string;
192
+
147
193
  static of(elements: PageElements): QuestionAdapter<string[]> & MetaQuestion<Answerable<PageElement>, Promise<string[]>> {
148
194
  return Question.createAdapter(new TextOfMultipleElements(elements)) as QuestionAdapter<string[]> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>;
149
195
  }
150
196
 
151
- constructor(private readonly elements: PageElements) {
152
- super(d`the text of ${ elements }`);
197
+ protected constructor(private readonly elements: PageElements) {
198
+ super();
199
+ this.subject = d`the text of ${ elements }`;
153
200
  }
154
201
 
155
202
  of(parent: Answerable<PageElement>): Question<Promise<string[]>> {
156
203
  return new TextOfMultipleElements(this.elements.of(parent));
157
204
  }
158
205
 
206
+ /**
207
+ * @inheritDoc
208
+ */
159
209
  async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string[]> {
160
210
  const elements: PageElement[] = await actor.answer(this.elements);
161
211
 
162
212
  return asyncMap(elements, element => element.text());
163
213
  }
214
+
215
+ /**
216
+ * @inheritDoc
217
+ */
218
+ describedAs(subject: string): this {
219
+ this.subject = subject;
220
+ return this;
221
+ }
222
+
223
+ /**
224
+ * @inheritDoc
225
+ */
226
+ toString(): string {
227
+ return this.subject;
228
+ }
164
229
  }
@@ -1,82 +1,122 @@
1
- import { Answerable, AnswersQuestions, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core';
2
- import { formatted } from '@serenity-js/core/lib/io';
1
+ import { Answerable, AnswersQuestions, d, MetaQuestion, Question, QuestionAdapter, UsesAbilities } from '@serenity-js/core';
3
2
 
4
3
  import { PageElement } from '../models';
5
- import { ElementQuestion } from './ElementQuestion';
6
4
 
7
5
  /**
8
- * @desc
9
- * Returns the `value` attribute of a given {@link WebElement},
10
- * represented by Answerable<{@link @wdio/types~Element}>
6
+ * Uses the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
7
+ * the `value` attribute of a given {@apilink PageElement}.
11
8
  *
12
- * @example <caption>Example widget</caption>
13
- * <input type="text" id="username" value="Alice" />
9
+ * ## Example widget
10
+ * ```html
11
+ * <input type="text" id="username" value="Alice" />
12
+ * ```
14
13
  *
15
- * @example <caption>Retrieve CSS classes of a given WebElement</caption>
16
- * import { actorCalled } from '@serenity-js/core';
17
- * import { Ensure, equals } from '@serenity-js/assertions';
18
- * import { BrowseTheWeb, by, Value, Target } from '@serenity-js/webdriverio';
14
+ * ## Retrieve the `value` of a given {@apilink PageElement}
19
15
  *
20
- * const usernameField = () =>
21
- * Target.the('username field').located(by.id('username'))
16
+ * ```ts
17
+ * import { actorCalled } from '@serenity-js/core'
18
+ * import { Ensure, equals } from '@serenity-js/assertions'
19
+ * import { By, PageElement, Value } from '@serenity-js/web'
22
20
  *
23
- * actorCalled('Lisa')
24
- * .whoCan(BrowseTheWeb.using(browser))
25
- * .attemptsTo(
26
- * Ensure.that(Value.of(usernameField), equals('Alice')),
27
- * )
21
+ * const usernameField = () =>
22
+ * PageElement.located(By.id('username'))
23
+ * .describedAs('username field')
28
24
  *
29
- * @extends {@serenity-js/core/lib/screenplay~Question}
30
- * @implements {@serenity-js/core/lib/screenplay/questions~MetaQuestion}
25
+ * await actorCalled('Lisa')
26
+ * .attemptsTo(
27
+ * Ensure.that(Value.of(usernameField), equals('Alice')),
28
+ * )
29
+ * ```
30
+ *
31
+ * ## Using Value as {@apilink QuestionAdapter}
32
+ *
33
+ * ```ts
34
+ * import { actorCalled } from '@serenity-js/core'
35
+ * import { Ensure, equals } from '@serenity-js/assertions'
36
+ * import { By, PageElement, Value } from '@serenity-js/web'
37
+ *
38
+ * const usernameField = () =>
39
+ * PageElement.located(By.id('username'))
40
+ * .describedAs('username field')
41
+ *
42
+ * await actorCalled('Lisa')
43
+ * .attemptsTo(
44
+ * Ensure.that(
45
+ * Value.of(usernameField).toLocaleLowerCase()[0],
46
+ * equals('a') // [a]lice
47
+ * ),
48
+ * )
49
+ * ```
50
+ *
51
+ * ## Learn more
52
+ * - {@apilink BrowseTheWeb}
53
+ * - {@apilink MetaQuestion}
54
+ * - {@apilink QuestionAdapter}
55
+ * - {@apilink Question}
56
+ *
57
+ * @group Questions
31
58
  */
32
59
  export class Value
33
- extends ElementQuestion<Promise<string>>
60
+ extends Question<Promise<string>>
34
61
  implements MetaQuestion<Answerable<PageElement>, Promise<string>>
35
62
  {
63
+ private subject: string;
64
+
36
65
  /**
37
- * @param {Answerable<PageElement>} element
38
- * @returns {Value}
66
+ * Instantiates a {@apilink Question} that uses
67
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
68
+ * the `value` attribute of a given {@apilink PageElement}.
69
+ *
70
+ * #### Learn more
71
+ * - {@apilink MetaQuestion}
72
+ *
73
+ * @param pageElement
39
74
  */
40
- static of(element: Answerable<PageElement>): Question<Promise<string>> & MetaQuestion<Answerable<PageElement>, Promise<string>> {
41
- return new Value(element);
75
+ static of(pageElement: Answerable<PageElement>): QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>> {
76
+ return Question.createAdapter(new Value(pageElement)) as QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>>;
42
77
  }
43
78
 
44
- /**
45
- * @param {Answerable<PageElement>} element
46
- */
47
- constructor(private readonly element: Answerable<PageElement>) {
48
- super(formatted`the value of ${ element }`);
79
+ protected constructor(private readonly element: Answerable<PageElement>) {
80
+ super();
81
+ this.subject = d`the value of ${ element }`;
49
82
  }
50
83
 
51
84
  /**
52
- * @desc
53
- * Resolves to the value of a given [`input`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
54
- * {@link WebElement}, located in the context of a `parent` element.
85
+ * Instantiates a {@apilink Question} that uses
86
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
87
+ * the `value` attribute of a given {@apilink PageElement}
88
+ * located within the `parent` element.
55
89
  *
56
- * @param {Answerable<PageElement>} parent
57
- * @returns {Question<Promise<string>>}
90
+ * #### Learn more
91
+ * - {@apilink MetaQuestion}
58
92
  *
59
- * @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
93
+ * @param parent
60
94
  */
61
95
  of(parent: Answerable<PageElement>): Question<Promise<string>> {
62
96
  return new Value(PageElement.of(this.element, parent));
63
97
  }
64
98
 
65
99
  /**
66
- * @desc
67
- * Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
68
- * answer this {@link @serenity-js/core/lib/screenplay~Question}.
69
- *
70
- * @param {AnswersQuestions & UsesAbilities} actor
71
- * @returns {Promise<void>}
72
- *
73
- * @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
74
- * @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
75
- * @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
100
+ * @inheritDoc
76
101
  */
77
102
  async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
78
- const element = await this.resolve(actor, this.element);
103
+ const element = await actor.answer(this.element);
79
104
 
80
105
  return element.value();
81
106
  }
107
+
108
+ /**
109
+ * @inheritDoc
110
+ */
111
+ describedAs(subject: string): this {
112
+ this.subject = subject;
113
+ return this;
114
+ }
115
+
116
+ /**
117
+ * @inheritDoc
118
+ */
119
+ toString(): string {
120
+ return this.subject;
121
+ }
82
122
  }
@@ -0,0 +1 @@
1
+ export * from './isVisible';
@@ -0,0 +1,113 @@
1
+ /* eslint-disable unicorn/no-for-loop,unicorn/consistent-function-scoping */
2
+ /* istanbul ignore next */
3
+ export function isVisible(domNode: HTMLElement): boolean {
4
+
5
+ const style = window.getComputedStyle(domNode);
6
+
7
+ if (style.opacity === '0') {
8
+ return false;
9
+ }
10
+
11
+ if (style.visibility === 'hidden') {
12
+ return false;
13
+ }
14
+
15
+ if (style.display === 'none') {
16
+ return false;
17
+ }
18
+
19
+ if (!domNode.getBoundingClientRect || !domNode.scrollIntoView || !domNode.contains || !domNode.getClientRects || !document.elementFromPoint) {
20
+ return false
21
+ }
22
+
23
+ // Edge before switching to Chromium
24
+ const isOldEdge = !!window['StyleMedia']
25
+
26
+ // get overlapping element
27
+ function getOverlappingElement (element: HTMLElement, context?: Document) {
28
+ context = context || document
29
+ const dimensions = element.getBoundingClientRect()
30
+ const x = dimensions.left + (element.clientWidth / 2)
31
+ const y = dimensions.top + (element.clientHeight / 2)
32
+ return context.elementFromPoint(x, y)
33
+ }
34
+
35
+ // get overlapping element rects (currently only the first)
36
+ // applicable if element's text is multiline.
37
+ function getOverlappingRects (element: HTMLElement, context?: Document) {
38
+ context = context || document
39
+ const elements = []
40
+
41
+ const rects = element.getClientRects()
42
+ // webdriver clicks on center of the first element's rect (line of text), it might change in future
43
+ const rect = rects[0]
44
+ const x = rect.left + (rect.width / 2)
45
+ const y = rect.top + (rect.height / 2)
46
+ elements.push(context.elementFromPoint(x, y))
47
+
48
+ return elements
49
+ }
50
+
51
+ // get overlapping elements
52
+ function getOverlappingElements (element: HTMLElement, context?: Document) {
53
+ return [getOverlappingElement(element, context)].concat(getOverlappingRects(element, context))
54
+ }
55
+
56
+ // is a node a descendant of a given node
57
+ function nodeContains (element: HTMLElement, otherNode: HTMLElement) {
58
+ // Edge doesn't support neither Shadow Dom nor contains if ShadowRoot polyfill is used
59
+ if (isOldEdge) {
60
+ let tempElement = otherNode as HTMLElement | ShadowRoot | Element
61
+ while (tempElement) {
62
+ if (tempElement === element) {
63
+ return true
64
+ }
65
+
66
+ tempElement = tempElement.parentNode as ShadowRoot
67
+ // DocumentFragment / ShadowRoot polyfill like ShadyRoot
68
+ if (tempElement && tempElement.nodeType === 11 && tempElement.host) {
69
+ tempElement = tempElement.host
70
+ }
71
+ }
72
+ return false
73
+ }
74
+
75
+ return element.contains(otherNode)
76
+ }
77
+
78
+ // is one of overlapping elements the `elem` or one of its child
79
+ function isOverlappingElementMatch (elementsFromPoint: HTMLElement[], element: HTMLElement): boolean {
80
+ if (elementsFromPoint.some(function (elementFromPoint) {
81
+ return elementFromPoint === element || nodeContains(element, elementFromPoint)
82
+ })) {
83
+ return true
84
+ }
85
+
86
+ // shadow root
87
+ // filter unique elements with shadowRoot
88
+ const elementsWithShadowRoot = [].concat(elementsFromPoint).filter(function (x: HTMLElement) {
89
+ return x && x.shadowRoot && x.shadowRoot.elementFromPoint
90
+ })
91
+
92
+ // getOverlappingElements of every element with shadowRoot
93
+ let shadowElementsFromPoint: HTMLElement[] = []
94
+ for (let i = 0; i < elementsWithShadowRoot.length; ++i) {
95
+ const shadowElement = elementsWithShadowRoot[i]
96
+ shadowElementsFromPoint = shadowElementsFromPoint.concat(
97
+ getOverlappingElements(element, (shadowElement as HTMLElement).shadowRoot as any) as any
98
+ )
99
+ }
100
+ // remove duplicates and parents
101
+ shadowElementsFromPoint = [].concat(shadowElementsFromPoint).filter(function (x) {
102
+ return !elementsFromPoint.includes(x)
103
+ })
104
+
105
+ if (shadowElementsFromPoint.length === 0) {
106
+ return false
107
+ }
108
+
109
+ return isOverlappingElementMatch(shadowElementsFromPoint, element)
110
+ }
111
+
112
+ return isOverlappingElementMatch(getOverlappingElements(domNode) as any as HTMLElement[], domNode)
113
+ }