@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,8 +1,15 @@
1
+ export * from './BrowserCapabilities';
2
+ export * from './BrowsingSession';
1
3
  export * from './Cookie';
2
4
  export * from './CookieData';
5
+ export * from './dialogs';
6
+ export * from './Key';
3
7
  export * from './Locator';
4
- export * from './ModalDialog';
5
8
  export * from './Page';
6
9
  export * from './PageElement';
7
10
  export * from './PageElements';
11
+ export * from './RootLocator';
12
+ export * from './SelectOption';
8
13
  export * from './selectors';
14
+ export * from './Switchable';
15
+ export * from './SwitchableOrigin';
@@ -2,11 +2,21 @@ import { Answerable, f, Question } from '@serenity-js/core';
2
2
 
3
3
  import { ByCss } from './ByCss';
4
4
  import { ByCssContainingText } from './ByCssContainingText';
5
+ import { ByDeepCss } from './ByDeepCss';
5
6
  import { ById } from './ById';
6
7
  import { ByTagName } from './ByTagName';
7
8
  import { ByXPath } from './ByXPath';
8
9
 
10
+ /**
11
+ * @group Models
12
+ */
9
13
  export class By {
14
+
15
+ /**
16
+ * Locates a {@apilink PageElement} using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors).
17
+ *
18
+ * @param selector
19
+ */
10
20
  static css(selector: Answerable<string>): Question<Promise<ByCss>> {
11
21
  return Question.about(f`by css (${selector})`, async actor => {
12
22
  const bySelector = await actor.answer(selector);
@@ -14,6 +24,13 @@ export class By {
14
24
  });
15
25
  }
16
26
 
27
+ /**
28
+ * Locates a {@apilink PageElement} with a given [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
29
+ * using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors).
30
+ *
31
+ * @param selector
32
+ * @param text
33
+ */
17
34
  static cssContainingText(selector: Answerable<string>, text: Answerable<string>): Question<Promise<ByCssContainingText>> {
18
35
  return Question.about(f`by css (${selector}) containing text ${ text }`, async actor => {
19
36
  const bySelector = await actor.answer(selector);
@@ -22,6 +39,24 @@ export class By {
22
39
  });
23
40
  }
24
41
 
42
+ /**
43
+ * Locates a {@apilink PageElement} using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors)
44
+ * capable of piercing [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)-piercing
45
+ *
46
+ * @param selector
47
+ */
48
+ static deepCss(selector: Answerable<string>): Question<Promise<ByCss>> {
49
+ return Question.about(f`by deep css (${selector})`, async actor => {
50
+ const bySelector = await actor.answer(selector);
51
+ return new ByDeepCss(bySelector);
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Locates a {@apilink PageElement} using its [id](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors).
57
+ *
58
+ * @param selector
59
+ */
25
60
  static id(selector: Answerable<string>): Question<Promise<ById>> {
26
61
  return Question.about(f`by id (${selector})`, async actor => {
27
62
  const bySelector = await actor.answer(selector);
@@ -29,6 +64,11 @@ export class By {
29
64
  });
30
65
  }
31
66
 
67
+ /**
68
+ * Locates a {@apilink PageElement} using the name of its [HTML tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
69
+ *
70
+ * @param selector
71
+ */
32
72
  static tagName(selector: Answerable<string>): Question<Promise<ByTagName>> {
33
73
  return Question.about(f`by tag name (${selector})`, async actor => {
34
74
  const bySelector = await actor.answer(selector);
@@ -36,6 +76,11 @@ export class By {
36
76
  });
37
77
  }
38
78
 
79
+ /**
80
+ * Locates a {@apilink PageElement} using an [XPath selector](https://developer.mozilla.org/en-US/docs/Web/XPath).
81
+ *
82
+ * @param selector
83
+ */
39
84
  static xpath(selector: Answerable<string>): Question<Promise<ByXPath>> {
40
85
  return Question.about(f`by xpath (${selector})`, async actor => {
41
86
  const bySelector = await actor.answer(selector);
@@ -1,5 +1,12 @@
1
1
  import { Selector } from './Selector';
2
2
 
3
+ /**
4
+ * Locates a {@apilink PageElement} using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors).
5
+ *
6
+ * **Pro tip:** Instantiate using {@apilink By.css}
7
+ *
8
+ * @group Models
9
+ */
3
10
  export class ByCss extends Selector {
4
11
  constructor(public readonly value: string) {
5
12
  super();
@@ -1,5 +1,13 @@
1
1
  import { Selector } from './Selector';
2
2
 
3
+ /**
4
+ * Locates a {@apilink PageElement} with a given [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
5
+ * using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors).
6
+ *
7
+ * **Pro tip:** Instantiate using {@apilink By.cssContainingText}
8
+ *
9
+ * @group Models
10
+ */
3
11
  export class ByCssContainingText extends Selector {
4
12
  constructor(public readonly value: string, public readonly text: string) {
5
13
  super();
@@ -0,0 +1,15 @@
1
+ import { Selector } from './Selector';
2
+
3
+ /**
4
+ * Locates a {@apilink PageElement} using a [CSS selector](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors)
5
+ * capable of piercing [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)-piercing
6
+ *
7
+ * **Pro tip:** Instantiate using {@apilink By.deepCss}
8
+ *
9
+ * @group Models
10
+ */
11
+ export class ByDeepCss extends Selector {
12
+ constructor(public readonly value: string) {
13
+ super();
14
+ }
15
+ }
@@ -1,5 +1,12 @@
1
1
  import { Selector } from './Selector';
2
2
 
3
+ /**
4
+ * Locates a {@apilink PageElement} using its [id](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors).
5
+ *
6
+ * **Pro tip:** Instantiate using {@apilink By.id}
7
+ *
8
+ * @group Models
9
+ */
3
10
  export class ById extends Selector {
4
11
  constructor(public readonly value: string) {
5
12
  super();
@@ -1,5 +1,12 @@
1
1
  import { Selector } from './Selector';
2
2
 
3
+ /**
4
+ * Locates a {@apilink PageElement} using the name of its [HTML tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
5
+ *
6
+ * **Pro tip:** Instantiate using {@apilink By.tagName}
7
+ *
8
+ * @group Models
9
+ */
3
10
  export class ByTagName extends Selector {
4
11
  constructor(public readonly value: string) {
5
12
  super();
@@ -1,5 +1,12 @@
1
1
  import { Selector } from './Selector';
2
2
 
3
+ /**
4
+ * Locates a {@apilink PageElement} using an [XPath selector](https://developer.mozilla.org/en-US/docs/Web/XPath).
5
+ *
6
+ * **Pro tip:** Instantiate using {@apilink By.xpath}
7
+ *
8
+ * @group Models
9
+ */
3
10
  export class ByXPath extends Selector {
4
11
  constructor(public readonly value: string) {
5
12
  super();
@@ -1,9 +1,14 @@
1
1
  import { f } from '@serenity-js/core';
2
2
 
3
+ /**
4
+ * Describes a selector you use to identify a {@apilink PageElement} or a group of {@apilink PageElements}.
5
+ *
6
+ * @group Models
7
+ */
3
8
  export abstract class Selector {
4
9
 
5
10
  toString(): string {
6
- const selectorDescription = this.constructor.name.replace(/([a-z]+)([A-Z])/g, '$1 $2').toLowerCase();
11
+ const selectorDescription = this.constructor.name.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
7
12
  const parametersDescription = Object.keys(this).map(field => f`${this[field]}`).join(', ');
8
13
 
9
14
  return `${ selectorDescription } (${ parametersDescription })`;
@@ -1,6 +1,7 @@
1
1
  export * from './By';
2
2
  export * from './ByCss';
3
3
  export * from './ByCssContainingText';
4
+ export * from './ByDeepCss';
4
5
  export * from './ById';
5
6
  export * from './ByTagName';
6
7
  export * from './ByXPath';
@@ -1,112 +1,173 @@
1
- import { Answerable, AnswersQuestions, LogicError, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core';
1
+ import { Answerable, AnswersQuestions, d, LogicError, MetaQuestion, Question, QuestionAdapter, UsesAbilities } from '@serenity-js/core';
2
2
 
3
3
  import { PageElement } from '../models';
4
- import { ElementQuestion } from './ElementQuestion';
5
4
 
6
5
  /**
7
- * @desc
8
- * Returns the value of the given HTML attribute of a given {@link WebElement},
9
- * represented by Answerable<{@link @wdio/types~Element}>
10
- *
11
- * @example <caption>Example widget</caption>
12
- * <ul id="shopping-list" data-items-left="2">
13
- * <li data-state="bought">Coffee<li>
14
- * <li data-state="buy">Honey<li>
15
- * <li data-state="buy">Chocolate<li>
16
- * </ul>
17
- *
18
- * @example <caption>Retrieve a HTML attribute of a given WebElement</caption>
19
- * import { actorCalled } from '@serenity-js/core';
20
- * import { Ensure, equals } from '@serenity-js/assertions';
21
- * import { Attribute, by, BrowseTheWeb, Target } from '@serenity-js/webdriverio';
6
+ * Uses the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
7
+ * the value of the specified HTML attribute of a given {@apilink PageElement}.
8
+ *
9
+ * ## Example widget
10
+ *
11
+ * ```html
12
+ * <ul id="shopping-list" data-items-left="2">
13
+ * <li data-state="bought">Coffee<li>
14
+ * <li data-state="buy">Honey<li>
15
+ * <li data-state="buy">Chocolate<li>
16
+ * </ul>
17
+ * ```
18
+ *
19
+ * ## Retrieve an HTML attribute of a given {@apilink PageElement}
20
+ *
21
+ * ```ts
22
+ * import { actorCalled } from '@serenity-js/core'
23
+ * import { Ensure, equals } from '@serenity-js/assertions'
24
+ * import { Attribute, By, PageElement } from '@serenity-js/web'
22
25
  *
23
26
  * const shoppingList = () =>
24
- * Target.the('shopping list').located(by.id('shopping-list'))
25
- *
26
- * actorCalled('Lisa')
27
- * .whoCan(BrowseTheWeb.using(browser))
28
- * .attemptsTo(
29
- * Ensure.that(Attribute.called('data-items-left').of(shoppingList()), equals('2')),
30
- * )
31
- *
32
- * @example <caption>Find WebElements with a given attribute</caption>
33
- * import { actorCalled } from '@serenity-js/core';
34
- * import { Ensure, includes } from '@serenity-js/assertions';
35
- * import { Attribute, BrowseTheWeb, by, Target } from '@serenity-js/webdriverio';
36
- *
37
- * class ShoppingList {
38
- * static items = () =>
39
- * Target.all('items')
40
- * .located(by.css('#shopping-list li'))
41
- *
42
- * static outstandingItems = () =>
43
- * ShoppingList.items
44
- * .where(Attribute.called('data-state'), includes('buy'))
45
- * }
46
- *
47
- * actorCalled('Lisa')
48
- * .whoCan(BrowseTheWeb.using(browser))
49
- * .attemptsTo(
50
- * Ensure.that(
51
- * Text.ofAll(ShoppingList.outstandingItems()),
52
- * equals([ 'Honey', 'Chocolate' ])
53
- * ),
54
- * )
55
- *
56
- * @extends {ElementQuestion}
57
- * @implements {@serenity-js/core/lib/screenplay/questions~MetaQuestion}
27
+ * PageElement.located(By.id('shopping-list'))
28
+ * .describedAs('shopping list')
29
+ *
30
+ * await actorCalled('Lisa')
31
+ * .attemptsTo(
32
+ * Ensure.that(
33
+ * Attribute.called('data-items-left').of(shoppingList()),
34
+ * equals('2')
35
+ * ),
36
+ * )
37
+ * ```
38
+ *
39
+ * ## Using `Attribute` as {@apilink QuestionAdapter}
40
+ *
41
+ * ```ts
42
+ * import { actorCalled } from '@serenity-js/core'
43
+ * import { Ensure, equals } from '@serenity-js/assertions'
44
+ * import { Attribute, By, PageElement } from '@serenity-js/web'
45
+ *
46
+ * const shoppingList = () =>
47
+ * PageElement.located(By.css('#shopping-list'))
48
+ * .describedAs('shopping list')
49
+ *
50
+ * await actorCalled('Lisa')
51
+ * .attemptsTo(
52
+ * Ensure.that(
53
+ * Attribute.called('id').of(shoppingList()).toLocaleUpperCase(),
54
+ * equals('SHOPPING-LIST')
55
+ * ),
56
+ * )
57
+ * ```
58
+ *
59
+ * ## Using as filter in {@apilink PageElements|Page Element Query Language}
60
+ *
61
+ * ```ts
62
+ * import { actorCalled } from '@serenity-js/core'
63
+ * import { Ensure, includes } from '@serenity-js/assertions'
64
+ * import { Attribute, By, PageElements } from '@serenity-js/web'
65
+ *
66
+ * class ShoppingList {
67
+ * static items = () =>
68
+ * PageElements.located(By.css('#shopping-list li'))
69
+ * .describedAs('items')
70
+ *
71
+ * static outstandingItems = () =>
72
+ * ShoppingList.items()
73
+ * .where(
74
+ * Attribute.called('data-state'),
75
+ * includes('buy')
76
+ * )
77
+ * }
78
+ *
79
+ * await actorCalled('Lisa')
80
+ * .whoCan(BrowseTheWebWithWebdriverIO.using(browser))
81
+ * .attemptsTo(
82
+ * Ensure.that(
83
+ * Text.ofAll(ShoppingList.outstandingItems()),
84
+ * equals([ 'Honey', 'Chocolate' ])
85
+ * ),
86
+ * )
87
+ * ```
88
+ *
89
+ * ## Learn more
90
+ * - {@apilink BrowseTheWeb}
91
+ * - {@apilink MetaQuestion}
92
+ * - {@apilink QuestionAdapter}
93
+ * - {@apilink Question}
94
+ *
95
+ * @group Questions
58
96
  */
59
97
  export class Attribute
60
- extends ElementQuestion<Promise<string>>
98
+ extends Question<Promise<string>>
61
99
  implements MetaQuestion<Answerable<PageElement>, Promise<string>>
62
100
  {
101
+ private subject: string;
102
+
63
103
  /**
64
- * @param {Answerable<string>} name
65
- * @returns {Attribute}
104
+ * Instantiates a {@apilink Question} that uses
105
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
106
+ * the value of the specified HTML attribute of a given {@apilink PageElement}.
107
+ *
108
+ * @param name
109
+ * The name of the attribute to retrieve
66
110
  */
67
111
  static called(name: Answerable<string>): Attribute {
68
112
  return new Attribute(name);
69
113
  }
70
114
 
71
- /**
72
- * @param {Answerable<string>} name
73
- * @param {@serenity-js/core/lib/screenplay~Answerable<Element>} [element]
74
- */
75
- constructor(
115
+ protected constructor(
76
116
  private readonly name: Answerable<string>,
77
117
  private readonly element?: Answerable<PageElement>,
78
118
  ) {
79
- super(`"${ name }" attribute of ${ element }`);
119
+ super();
120
+ this.subject = element
121
+ ? d`${ name } attribute of ${ element }`
122
+ : d`${ name } attribute`
80
123
  }
81
124
 
82
125
  /**
83
- * @desc
84
- * Resolves to the value of a HTML attribute of the `target` element,
85
- * located in the context of a `parent` element.
126
+ * Resolves to the value of an HTML attribute of the `pageElement`.
86
127
  *
87
- * @param {Answerable<PageElement>} parent
88
- * @returns {Question<Promise<string[]>>}
128
+ * #### Learn more
129
+ * - {@apilink MetaQuestion}
89
130
  *
90
- * @see {@link Target.all}
91
- * @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
131
+ * @param pageElement
92
132
  */
93
- of(parent: Answerable<PageElement>): Question<Promise<string>> {
94
- return new Attribute(
95
- this.name,
96
- this.element
97
- ? PageElement.of(this.element, parent)
98
- : parent
99
- );
133
+ of(pageElement: Answerable<PageElement>): QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>> {
134
+ return Question.createAdapter(
135
+ new Attribute(
136
+ this.name,
137
+ this.element
138
+ ? PageElement.of(this.element, pageElement)
139
+ : pageElement
140
+ )
141
+ ) as QuestionAdapter<string> & MetaQuestion<Answerable<PageElement>, Promise<string>>;
100
142
  }
101
143
 
144
+ /**
145
+ * @inheritDoc
146
+ */
102
147
  async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
148
+ const name = await actor.answer(this.name);
149
+
103
150
  if (! this.element) {
104
- throw new LogicError(`Target not specified`); // todo: better error message?
151
+ throw new LogicError(d`Couldn't read attribute ${ name } of an unspecified page element.`);
105
152
  }
106
153
 
107
154
  const element = await actor.answer(this.element);
108
- const name = await actor.answer(this.name);
109
155
 
110
156
  return element.attribute(name);
111
157
  }
158
+
159
+ /**
160
+ * @inheritDoc
161
+ */
162
+ describedAs(subject: string): this {
163
+ this.subject = subject;
164
+ return this;
165
+ }
166
+
167
+ /**
168
+ * @inheritDoc
169
+ */
170
+ toString(): string {
171
+ return this.subject;
172
+ }
112
173
  }