@serenity-js/webdriverio-8 3.31.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 (285) hide show
  1. package/CHANGELOG.md +1232 -0
  2. package/LICENSE.md +201 -0
  3. package/NOTICE.md +1 -0
  4. package/README.md +234 -0
  5. package/esm/adapter/TestRunnerLoader.d.ts +17 -0
  6. package/esm/adapter/TestRunnerLoader.d.ts.map +1 -0
  7. package/esm/adapter/TestRunnerLoader.js +63 -0
  8. package/esm/adapter/TestRunnerLoader.js.map +1 -0
  9. package/esm/adapter/WebdriverIOFrameworkAdapter.d.ts +25 -0
  10. package/esm/adapter/WebdriverIOFrameworkAdapter.d.ts.map +1 -0
  11. package/esm/adapter/WebdriverIOFrameworkAdapter.js +90 -0
  12. package/esm/adapter/WebdriverIOFrameworkAdapter.js.map +1 -0
  13. package/esm/adapter/WebdriverIOFrameworkAdapterFactory.d.ts +18 -0
  14. package/esm/adapter/WebdriverIOFrameworkAdapterFactory.d.ts.map +1 -0
  15. package/esm/adapter/WebdriverIOFrameworkAdapterFactory.js +18 -0
  16. package/esm/adapter/WebdriverIOFrameworkAdapterFactory.js.map +1 -0
  17. package/esm/adapter/WebdriverIONotifier.d.ts +71 -0
  18. package/esm/adapter/WebdriverIONotifier.d.ts.map +1 -0
  19. package/esm/adapter/WebdriverIONotifier.js +390 -0
  20. package/esm/adapter/WebdriverIONotifier.js.map +1 -0
  21. package/esm/adapter/index.d.ts +2 -0
  22. package/esm/adapter/index.d.ts.map +1 -0
  23. package/esm/adapter/index.js +2 -0
  24. package/esm/adapter/index.js.map +1 -0
  25. package/esm/adapter/reporter/BrowserCapabilitiesReporter.d.ts +18 -0
  26. package/esm/adapter/reporter/BrowserCapabilitiesReporter.d.ts.map +1 -0
  27. package/esm/adapter/reporter/BrowserCapabilitiesReporter.js +42 -0
  28. package/esm/adapter/reporter/BrowserCapabilitiesReporter.js.map +1 -0
  29. package/esm/adapter/reporter/InitialisesReporters.d.ts +8 -0
  30. package/esm/adapter/reporter/InitialisesReporters.d.ts.map +1 -0
  31. package/esm/adapter/reporter/InitialisesReporters.js +2 -0
  32. package/esm/adapter/reporter/InitialisesReporters.js.map +1 -0
  33. package/esm/adapter/reporter/OutputStreamBuffer.d.ts +13 -0
  34. package/esm/adapter/reporter/OutputStreamBuffer.d.ts.map +1 -0
  35. package/esm/adapter/reporter/OutputStreamBuffer.js +25 -0
  36. package/esm/adapter/reporter/OutputStreamBuffer.js.map +1 -0
  37. package/esm/adapter/reporter/OutputStreamBufferPrinter.d.ts +16 -0
  38. package/esm/adapter/reporter/OutputStreamBufferPrinter.d.ts.map +1 -0
  39. package/esm/adapter/reporter/OutputStreamBufferPrinter.js +24 -0
  40. package/esm/adapter/reporter/OutputStreamBufferPrinter.js.map +1 -0
  41. package/esm/adapter/reporter/ProvidesWriteStream.d.ts +8 -0
  42. package/esm/adapter/reporter/ProvidesWriteStream.d.ts.map +1 -0
  43. package/esm/adapter/reporter/ProvidesWriteStream.js +2 -0
  44. package/esm/adapter/reporter/ProvidesWriteStream.js.map +1 -0
  45. package/esm/adapter/reporter/TagPrinter.d.ts +17 -0
  46. package/esm/adapter/reporter/TagPrinter.d.ts.map +1 -0
  47. package/esm/adapter/reporter/TagPrinter.js +52 -0
  48. package/esm/adapter/reporter/TagPrinter.js.map +1 -0
  49. package/esm/adapter/reporter/index.d.ts +6 -0
  50. package/esm/adapter/reporter/index.d.ts.map +1 -0
  51. package/esm/adapter/reporter/index.js +6 -0
  52. package/esm/adapter/reporter/index.js.map +1 -0
  53. package/esm/api.d.ts +3 -0
  54. package/esm/api.d.ts.map +1 -0
  55. package/esm/api.js +2 -0
  56. package/esm/api.js.map +1 -0
  57. package/esm/config/WebdriverIOConfig.d.ts +95 -0
  58. package/esm/config/WebdriverIOConfig.d.ts.map +1 -0
  59. package/esm/config/WebdriverIOConfig.js +2 -0
  60. package/esm/config/WebdriverIOConfig.js.map +1 -0
  61. package/esm/config/index.d.ts +2 -0
  62. package/esm/config/index.d.ts.map +1 -0
  63. package/esm/config/index.js +2 -0
  64. package/esm/config/index.js.map +1 -0
  65. package/esm/index.d.ts +16 -0
  66. package/esm/index.d.ts.map +1 -0
  67. package/esm/index.js +14 -0
  68. package/esm/index.js.map +1 -0
  69. package/esm/screenplay/abilities/BrowseTheWebWithWebdriverIO.d.ts +40 -0
  70. package/esm/screenplay/abilities/BrowseTheWebWithWebdriverIO.d.ts.map +1 -0
  71. package/esm/screenplay/abilities/BrowseTheWebWithWebdriverIO.js +43 -0
  72. package/esm/screenplay/abilities/BrowseTheWebWithWebdriverIO.js.map +1 -0
  73. package/esm/screenplay/abilities/index.d.ts +2 -0
  74. package/esm/screenplay/abilities/index.d.ts.map +1 -0
  75. package/esm/screenplay/abilities/index.js +2 -0
  76. package/esm/screenplay/abilities/index.js.map +1 -0
  77. package/esm/screenplay/index.d.ts +3 -0
  78. package/esm/screenplay/index.d.ts.map +1 -0
  79. package/esm/screenplay/index.js +3 -0
  80. package/esm/screenplay/index.js.map +1 -0
  81. package/esm/screenplay/models/WebdriverIOBrowsingSession.d.ts +25 -0
  82. package/esm/screenplay/models/WebdriverIOBrowsingSession.d.ts.map +1 -0
  83. package/esm/screenplay/models/WebdriverIOBrowsingSession.js +125 -0
  84. package/esm/screenplay/models/WebdriverIOBrowsingSession.js.map +1 -0
  85. package/esm/screenplay/models/WebdriverIOCookie.d.ts +15 -0
  86. package/esm/screenplay/models/WebdriverIOCookie.d.ts.map +1 -0
  87. package/esm/screenplay/models/WebdriverIOCookie.js +42 -0
  88. package/esm/screenplay/models/WebdriverIOCookie.js.map +1 -0
  89. package/esm/screenplay/models/WebdriverIOErrorHandler.d.ts +9 -0
  90. package/esm/screenplay/models/WebdriverIOErrorHandler.d.ts.map +1 -0
  91. package/esm/screenplay/models/WebdriverIOErrorHandler.js +20 -0
  92. package/esm/screenplay/models/WebdriverIOErrorHandler.js.map +1 -0
  93. package/esm/screenplay/models/WebdriverIOModalDialogHandler.d.ts +27 -0
  94. package/esm/screenplay/models/WebdriverIOModalDialogHandler.d.ts.map +1 -0
  95. package/esm/screenplay/models/WebdriverIOModalDialogHandler.js +74 -0
  96. package/esm/screenplay/models/WebdriverIOModalDialogHandler.js.map +1 -0
  97. package/esm/screenplay/models/WebdriverIOPage.d.ts +50 -0
  98. package/esm/screenplay/models/WebdriverIOPage.d.ts.map +1 -0
  99. package/esm/screenplay/models/WebdriverIOPage.js +219 -0
  100. package/esm/screenplay/models/WebdriverIOPage.js.map +1 -0
  101. package/esm/screenplay/models/WebdriverIOPageElement.d.ts +34 -0
  102. package/esm/screenplay/models/WebdriverIOPageElement.d.ts.map +1 -0
  103. package/esm/screenplay/models/WebdriverIOPageElement.js +220 -0
  104. package/esm/screenplay/models/WebdriverIOPageElement.js.map +1 -0
  105. package/esm/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.d.ts +30 -0
  106. package/esm/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.d.ts.map +1 -0
  107. package/esm/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.js +77 -0
  108. package/esm/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.js.map +1 -0
  109. package/esm/screenplay/models/WebdriverProtocolErrorCode.d.ts +39 -0
  110. package/esm/screenplay/models/WebdriverProtocolErrorCode.d.ts.map +1 -0
  111. package/esm/screenplay/models/WebdriverProtocolErrorCode.js +40 -0
  112. package/esm/screenplay/models/WebdriverProtocolErrorCode.js.map +1 -0
  113. package/esm/screenplay/models/index.d.ts +5 -0
  114. package/esm/screenplay/models/index.d.ts.map +1 -0
  115. package/esm/screenplay/models/index.js +5 -0
  116. package/esm/screenplay/models/index.js.map +1 -0
  117. package/esm/screenplay/models/locators/WebdriverIOLocator.d.ts +33 -0
  118. package/esm/screenplay/models/locators/WebdriverIOLocator.d.ts.map +1 -0
  119. package/esm/screenplay/models/locators/WebdriverIOLocator.js +123 -0
  120. package/esm/screenplay/models/locators/WebdriverIOLocator.js.map +1 -0
  121. package/esm/screenplay/models/locators/WebdriverIORootLocator.d.ts +17 -0
  122. package/esm/screenplay/models/locators/WebdriverIORootLocator.d.ts.map +1 -0
  123. package/esm/screenplay/models/locators/WebdriverIORootLocator.js +30 -0
  124. package/esm/screenplay/models/locators/WebdriverIORootLocator.js.map +1 -0
  125. package/esm/screenplay/models/locators/index.d.ts +3 -0
  126. package/esm/screenplay/models/locators/index.d.ts.map +1 -0
  127. package/esm/screenplay/models/locators/index.js +3 -0
  128. package/esm/screenplay/models/locators/index.js.map +1 -0
  129. package/lib/adapter/TestRunnerLoader.d.ts +17 -0
  130. package/lib/adapter/TestRunnerLoader.d.ts.map +1 -0
  131. package/lib/adapter/TestRunnerLoader.js +67 -0
  132. package/lib/adapter/TestRunnerLoader.js.map +1 -0
  133. package/lib/adapter/WebdriverIOFrameworkAdapter.d.ts +25 -0
  134. package/lib/adapter/WebdriverIOFrameworkAdapter.d.ts.map +1 -0
  135. package/lib/adapter/WebdriverIOFrameworkAdapter.js +127 -0
  136. package/lib/adapter/WebdriverIOFrameworkAdapter.js.map +1 -0
  137. package/lib/adapter/WebdriverIOFrameworkAdapterFactory.d.ts +18 -0
  138. package/lib/adapter/WebdriverIOFrameworkAdapterFactory.d.ts.map +1 -0
  139. package/lib/adapter/WebdriverIOFrameworkAdapterFactory.js +22 -0
  140. package/lib/adapter/WebdriverIOFrameworkAdapterFactory.js.map +1 -0
  141. package/lib/adapter/WebdriverIONotifier.d.ts +71 -0
  142. package/lib/adapter/WebdriverIONotifier.d.ts.map +1 -0
  143. package/lib/adapter/WebdriverIONotifier.js +394 -0
  144. package/lib/adapter/WebdriverIONotifier.js.map +1 -0
  145. package/lib/adapter/index.d.ts +2 -0
  146. package/lib/adapter/index.d.ts.map +1 -0
  147. package/lib/adapter/index.js +18 -0
  148. package/lib/adapter/index.js.map +1 -0
  149. package/lib/adapter/reporter/BrowserCapabilitiesReporter.d.ts +18 -0
  150. package/lib/adapter/reporter/BrowserCapabilitiesReporter.d.ts.map +1 -0
  151. package/lib/adapter/reporter/BrowserCapabilitiesReporter.js +49 -0
  152. package/lib/adapter/reporter/BrowserCapabilitiesReporter.js.map +1 -0
  153. package/lib/adapter/reporter/InitialisesReporters.d.ts +8 -0
  154. package/lib/adapter/reporter/InitialisesReporters.d.ts.map +1 -0
  155. package/lib/adapter/reporter/InitialisesReporters.js +3 -0
  156. package/lib/adapter/reporter/InitialisesReporters.js.map +1 -0
  157. package/lib/adapter/reporter/OutputStreamBuffer.d.ts +13 -0
  158. package/lib/adapter/reporter/OutputStreamBuffer.d.ts.map +1 -0
  159. package/lib/adapter/reporter/OutputStreamBuffer.js +29 -0
  160. package/lib/adapter/reporter/OutputStreamBuffer.js.map +1 -0
  161. package/lib/adapter/reporter/OutputStreamBufferPrinter.d.ts +16 -0
  162. package/lib/adapter/reporter/OutputStreamBufferPrinter.d.ts.map +1 -0
  163. package/lib/adapter/reporter/OutputStreamBufferPrinter.js +28 -0
  164. package/lib/adapter/reporter/OutputStreamBufferPrinter.js.map +1 -0
  165. package/lib/adapter/reporter/ProvidesWriteStream.d.ts +8 -0
  166. package/lib/adapter/reporter/ProvidesWriteStream.d.ts.map +1 -0
  167. package/lib/adapter/reporter/ProvidesWriteStream.js +3 -0
  168. package/lib/adapter/reporter/ProvidesWriteStream.js.map +1 -0
  169. package/lib/adapter/reporter/TagPrinter.d.ts +17 -0
  170. package/lib/adapter/reporter/TagPrinter.d.ts.map +1 -0
  171. package/lib/adapter/reporter/TagPrinter.js +56 -0
  172. package/lib/adapter/reporter/TagPrinter.js.map +1 -0
  173. package/lib/adapter/reporter/index.d.ts +6 -0
  174. package/lib/adapter/reporter/index.d.ts.map +1 -0
  175. package/lib/adapter/reporter/index.js +22 -0
  176. package/lib/adapter/reporter/index.js.map +1 -0
  177. package/lib/api.d.ts +3 -0
  178. package/lib/api.d.ts.map +1 -0
  179. package/lib/api.js +18 -0
  180. package/lib/api.js.map +1 -0
  181. package/lib/config/WebdriverIOConfig.d.ts +95 -0
  182. package/lib/config/WebdriverIOConfig.d.ts.map +1 -0
  183. package/lib/config/WebdriverIOConfig.js +3 -0
  184. package/lib/config/WebdriverIOConfig.js.map +1 -0
  185. package/lib/config/index.d.ts +2 -0
  186. package/lib/config/index.d.ts.map +1 -0
  187. package/lib/config/index.js +18 -0
  188. package/lib/config/index.js.map +1 -0
  189. package/lib/index.d.ts +16 -0
  190. package/lib/index.d.ts.map +1 -0
  191. package/lib/index.js +52 -0
  192. package/lib/index.js.map +1 -0
  193. package/lib/package.json +1 -0
  194. package/lib/screenplay/abilities/BrowseTheWebWithWebdriverIO.d.ts +40 -0
  195. package/lib/screenplay/abilities/BrowseTheWebWithWebdriverIO.d.ts.map +1 -0
  196. package/lib/screenplay/abilities/BrowseTheWebWithWebdriverIO.js +47 -0
  197. package/lib/screenplay/abilities/BrowseTheWebWithWebdriverIO.js.map +1 -0
  198. package/lib/screenplay/abilities/index.d.ts +2 -0
  199. package/lib/screenplay/abilities/index.d.ts.map +1 -0
  200. package/lib/screenplay/abilities/index.js +18 -0
  201. package/lib/screenplay/abilities/index.js.map +1 -0
  202. package/lib/screenplay/index.d.ts +3 -0
  203. package/lib/screenplay/index.d.ts.map +1 -0
  204. package/lib/screenplay/index.js +19 -0
  205. package/lib/screenplay/index.js.map +1 -0
  206. package/lib/screenplay/models/WebdriverIOBrowsingSession.d.ts +25 -0
  207. package/lib/screenplay/models/WebdriverIOBrowsingSession.d.ts.map +1 -0
  208. package/lib/screenplay/models/WebdriverIOBrowsingSession.js +129 -0
  209. package/lib/screenplay/models/WebdriverIOBrowsingSession.js.map +1 -0
  210. package/lib/screenplay/models/WebdriverIOCookie.d.ts +15 -0
  211. package/lib/screenplay/models/WebdriverIOCookie.d.ts.map +1 -0
  212. package/lib/screenplay/models/WebdriverIOCookie.js +46 -0
  213. package/lib/screenplay/models/WebdriverIOCookie.js.map +1 -0
  214. package/lib/screenplay/models/WebdriverIOErrorHandler.d.ts +9 -0
  215. package/lib/screenplay/models/WebdriverIOErrorHandler.d.ts.map +1 -0
  216. package/lib/screenplay/models/WebdriverIOErrorHandler.js +24 -0
  217. package/lib/screenplay/models/WebdriverIOErrorHandler.js.map +1 -0
  218. package/lib/screenplay/models/WebdriverIOModalDialogHandler.d.ts +27 -0
  219. package/lib/screenplay/models/WebdriverIOModalDialogHandler.d.ts.map +1 -0
  220. package/lib/screenplay/models/WebdriverIOModalDialogHandler.js +78 -0
  221. package/lib/screenplay/models/WebdriverIOModalDialogHandler.js.map +1 -0
  222. package/lib/screenplay/models/WebdriverIOPage.d.ts +50 -0
  223. package/lib/screenplay/models/WebdriverIOPage.d.ts.map +1 -0
  224. package/lib/screenplay/models/WebdriverIOPage.js +256 -0
  225. package/lib/screenplay/models/WebdriverIOPage.js.map +1 -0
  226. package/lib/screenplay/models/WebdriverIOPageElement.d.ts +34 -0
  227. package/lib/screenplay/models/WebdriverIOPageElement.d.ts.map +1 -0
  228. package/lib/screenplay/models/WebdriverIOPageElement.js +257 -0
  229. package/lib/screenplay/models/WebdriverIOPageElement.js.map +1 -0
  230. package/lib/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.d.ts +30 -0
  231. package/lib/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.d.ts.map +1 -0
  232. package/lib/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.js +81 -0
  233. package/lib/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.js.map +1 -0
  234. package/lib/screenplay/models/WebdriverProtocolErrorCode.d.ts +39 -0
  235. package/lib/screenplay/models/WebdriverProtocolErrorCode.d.ts.map +1 -0
  236. package/lib/screenplay/models/WebdriverProtocolErrorCode.js +43 -0
  237. package/lib/screenplay/models/WebdriverProtocolErrorCode.js.map +1 -0
  238. package/lib/screenplay/models/index.d.ts +5 -0
  239. package/lib/screenplay/models/index.d.ts.map +1 -0
  240. package/lib/screenplay/models/index.js +21 -0
  241. package/lib/screenplay/models/index.js.map +1 -0
  242. package/lib/screenplay/models/locators/WebdriverIOLocator.d.ts +33 -0
  243. package/lib/screenplay/models/locators/WebdriverIOLocator.d.ts.map +1 -0
  244. package/lib/screenplay/models/locators/WebdriverIOLocator.js +128 -0
  245. package/lib/screenplay/models/locators/WebdriverIOLocator.js.map +1 -0
  246. package/lib/screenplay/models/locators/WebdriverIORootLocator.d.ts +17 -0
  247. package/lib/screenplay/models/locators/WebdriverIORootLocator.d.ts.map +1 -0
  248. package/lib/screenplay/models/locators/WebdriverIORootLocator.js +34 -0
  249. package/lib/screenplay/models/locators/WebdriverIORootLocator.js.map +1 -0
  250. package/lib/screenplay/models/locators/index.d.ts +3 -0
  251. package/lib/screenplay/models/locators/index.d.ts.map +1 -0
  252. package/lib/screenplay/models/locators/index.js +19 -0
  253. package/lib/screenplay/models/locators/index.js.map +1 -0
  254. package/package.json +122 -0
  255. package/src/adapter/TestRunnerLoader.ts +90 -0
  256. package/src/adapter/WebdriverIOFrameworkAdapter.ts +130 -0
  257. package/src/adapter/WebdriverIOFrameworkAdapterFactory.ts +39 -0
  258. package/src/adapter/WebdriverIONotifier.ts +480 -0
  259. package/src/adapter/index.ts +1 -0
  260. package/src/adapter/reporter/BrowserCapabilitiesReporter.ts +63 -0
  261. package/src/adapter/reporter/InitialisesReporters.ts +8 -0
  262. package/src/adapter/reporter/OutputStreamBuffer.ts +30 -0
  263. package/src/adapter/reporter/OutputStreamBufferPrinter.ts +30 -0
  264. package/src/adapter/reporter/ProvidesWriteStream.ts +8 -0
  265. package/src/adapter/reporter/TagPrinter.ts +69 -0
  266. package/src/adapter/reporter/index.ts +5 -0
  267. package/src/api.ts +2 -0
  268. package/src/config/WebdriverIOConfig.ts +94 -0
  269. package/src/config/index.ts +1 -0
  270. package/src/index.ts +32 -0
  271. package/src/screenplay/abilities/BrowseTheWebWithWebdriverIO.ts +46 -0
  272. package/src/screenplay/abilities/index.ts +1 -0
  273. package/src/screenplay/index.ts +2 -0
  274. package/src/screenplay/models/WebdriverIOBrowsingSession.ts +176 -0
  275. package/src/screenplay/models/WebdriverIOCookie.ts +51 -0
  276. package/src/screenplay/models/WebdriverIOErrorHandler.ts +25 -0
  277. package/src/screenplay/models/WebdriverIOModalDialogHandler.ts +99 -0
  278. package/src/screenplay/models/WebdriverIOPage.ts +311 -0
  279. package/src/screenplay/models/WebdriverIOPageElement.ts +280 -0
  280. package/src/screenplay/models/WebdriverIOPuppeteerModalDialogHandler.ts +100 -0
  281. package/src/screenplay/models/WebdriverProtocolErrorCode.ts +38 -0
  282. package/src/screenplay/models/index.ts +4 -0
  283. package/src/screenplay/models/locators/WebdriverIOLocator.ts +176 -0
  284. package/src/screenplay/models/locators/WebdriverIORootLocator.ts +34 -0
  285. package/src/screenplay/models/locators/index.ts +2 -0
@@ -0,0 +1,480 @@
1
+ import type { Stage, StageCrewMember } from '@serenity-js/core';
2
+ import { LogicError } from '@serenity-js/core';
3
+ import type { DomainEvent} from '@serenity-js/core/lib/events/index.js';
4
+ import { AsyncOperationAttempted, AsyncOperationCompleted, SceneFinished, SceneStarts, TestRunFinishes, TestSuiteFinished, TestSuiteStarts } from '@serenity-js/core/lib/events/index.js';
5
+ import type {
6
+ Outcome,
7
+ TestSuiteDetails} from '@serenity-js/core/lib/model/index.js';
8
+ import {
9
+ CorrelationId,
10
+ Description,
11
+ ExecutionCompromised,
12
+ ExecutionFailedWithAssertionError,
13
+ ExecutionFailedWithError,
14
+ ExecutionIgnored,
15
+ ExecutionSkipped,
16
+ ImplementationPending, Name,
17
+ ProblemIndication
18
+ } from '@serenity-js/core/lib/model/index.js';
19
+ import type { Test as testStats } from '@wdio/reporter';
20
+ import type { Capabilities, Frameworks } from '@wdio/types';
21
+ import type { EventEmitter } from 'events';
22
+ import { match } from 'tiny-types';
23
+
24
+ import type { WebdriverIOConfig } from '../config/index.js';
25
+
26
+ // interface Argument {
27
+ // rows?: {
28
+ // cells: string[];
29
+ // }[];
30
+ // }
31
+ //
32
+ // export interface testStats {
33
+ // type: 'test:start' | 'test:pass' | 'test:fail' | 'test:retry' | 'test:pending' | 'test:end' | 'test:skip';
34
+ // title: string;
35
+ // parent: string;
36
+ // fullTitle: string;
37
+ // pending: boolean;
38
+ // file?: string;
39
+ // duration?: number;
40
+ // cid: string;
41
+ // specs: string[];
42
+ // uid: string;
43
+ // pendingReason?: string;
44
+ // error?: Error;
45
+ // errors?: Error[];
46
+ // retries?: number;
47
+ // argument?: string | Argument;
48
+ // }
49
+ //
50
+
51
+ /**
52
+ * @package
53
+ */
54
+ export class WebdriverIONotifier implements StageCrewMember {
55
+
56
+ /**
57
+ * We don't have access to the "context" object produced by Mocha,
58
+ * and can't assume that other test runners have a similar concept.
59
+ * Since, at the time of writing, none of the WebdriverIO rely on this parameter
60
+ * using a dummy seems to be sufficient.
61
+ * @private
62
+ */
63
+ private static dummmyContext = {};
64
+
65
+ private readonly events = new EventLog();
66
+ private readonly suites: TestSuiteDetails[] = [];
67
+
68
+ constructor(
69
+ private readonly config: WebdriverIOConfig,
70
+ private readonly capabilities: Capabilities.RemoteCapability,
71
+ private readonly reporter: EventEmitter,
72
+ private readonly successThreshold: Outcome | { Code: number },
73
+ private readonly cid: string,
74
+ private readonly specs: string[],
75
+ private failures: number = 0,
76
+ private stage?: Stage,
77
+ ) {
78
+ }
79
+
80
+ assignedTo(stage: Stage): StageCrewMember {
81
+ this.stage = stage;
82
+ return this;
83
+ }
84
+
85
+ notifyOf(event: DomainEvent): void {
86
+ return match<DomainEvent, void>(event)
87
+ .when(TestSuiteStarts, WebdriverIONotifier.prototype.onTestSuiteStarts.bind(this))
88
+ .when(TestSuiteFinished, WebdriverIONotifier.prototype.onTestSuiteFinished.bind(this))
89
+ .when(SceneStarts, WebdriverIONotifier.prototype.onSceneStarts.bind(this))
90
+ .when(SceneFinished, WebdriverIONotifier.prototype.onSceneFinished.bind(this))
91
+ .when(TestRunFinishes, WebdriverIONotifier.prototype.onTestRunFinishes.bind(this))
92
+ .else(() => void 0);
93
+ }
94
+
95
+ private onTestRunFinishes(): Promise<any> {
96
+ return this.invokeHooks('after', this.config.after, [this.failures, this.capabilities, this.specs]);
97
+ }
98
+
99
+ failureCount(): number {
100
+ return this.failures;
101
+ }
102
+
103
+ private onTestSuiteStarts(started: TestSuiteStarts): Promise<any> {
104
+ this.events.record(started.details.correlationId, started);
105
+
106
+ const suite = this.suiteStartEventFrom(started);
107
+
108
+ this.reporter.emit('suite:start', suite);
109
+
110
+ this.suites.push(started.details);
111
+
112
+ return this.invokeHooks('beforeSuite', this.config.beforeSuite, [suite as any]); // todo: correct types
113
+ }
114
+
115
+ private onTestSuiteFinished(finished: TestSuiteFinished): Promise<any> {
116
+ this.suites.pop();
117
+
118
+ const started = this.events.getByCorrelationId<TestSuiteStarts>(finished.details.correlationId);
119
+ const suite = this.suiteEndEventFrom(started, finished);
120
+
121
+ this.reporter.emit('suite:end', suite);
122
+
123
+ return this.invokeHooks('afterSuite', this.config.afterSuite, [suite as any]); // todo: correct types
124
+ }
125
+
126
+ private suiteStartEventFrom(started: TestSuiteStarts): { uid: string, cid: string, specs: string[] } & Frameworks.Suite {
127
+ return {
128
+ type: 'suite:start',
129
+ uid: started.details.correlationId.value,
130
+ cid: this.cid,
131
+ title: started.details.name.value,
132
+ fullTitle: this.suiteNamesConcatenatedWith(started.details.name.value),
133
+ parent: this.parentSuiteName(),
134
+ file: started.details.location.path.value,
135
+ specs: this.specs,
136
+ pending: false,
137
+ }
138
+ }
139
+
140
+ private suiteNamesConcatenatedWith(name: string): string {
141
+ return this.suites.map(suite => suite.name.value).concat(name).join(' ');
142
+ }
143
+
144
+ private suiteEndEventFrom(started: TestSuiteStarts, finished: TestSuiteFinished): Frameworks.Suite {
145
+ return {
146
+ ...this.suiteStartEventFrom(started),
147
+ type: 'suite:end',
148
+ duration: finished.timestamp.diff(started.timestamp).inMilliseconds()
149
+ }
150
+ }
151
+
152
+ private onSceneStarts(started: SceneStarts) {
153
+ const test = this.testStartEventFrom(started);
154
+
155
+ this.events.record(started.sceneId, started);
156
+
157
+ this.reporter.emit(test.type, test);
158
+
159
+ return this.invokeHooks('beforeTest', this.config.beforeTest, [ this.testFrom(started), WebdriverIONotifier.dummmyContext ]);
160
+ }
161
+
162
+ private onSceneFinished(finished: SceneFinished) {
163
+
164
+ if (finished.outcome.isWorseThan(this.successThreshold)) {
165
+ this.failures++;
166
+ }
167
+
168
+ const started = this.events.getByCorrelationId<SceneStarts>(finished.sceneId);
169
+ let testEnd: testStats;
170
+
171
+ if (this.willBeRetried(finished.outcome)) {
172
+ testEnd = this.testEndEventFrom(started, finished);
173
+
174
+ const type = 'test:retry';
175
+
176
+ this.reporter.emit(type, {
177
+ ...testEnd,
178
+ type,
179
+ error: this.errorFrom(finished.outcome),
180
+ });
181
+
182
+ } else {
183
+
184
+ const testResultEvent = this.testResultEventFrom(started, finished);
185
+ this.reporter.emit(testResultEvent.type, testResultEvent);
186
+
187
+ testEnd = this.testEndEventFrom(started, finished);
188
+ this.reporter.emit(testEnd.type, testEnd);
189
+ }
190
+
191
+ return this.invokeHooks('afterTest', this.config.afterTest, [ this.testFrom(started), WebdriverIONotifier.dummmyContext, this.testResultFrom(started, finished) ]);
192
+ }
193
+
194
+ private willBeRetried(outcome: Outcome): outcome is ExecutionIgnored {
195
+ return outcome instanceof ExecutionIgnored;
196
+ }
197
+
198
+ private testShortTitleFrom(started: SceneStarts): string {
199
+ return started.details.name.value
200
+ .replace(new RegExp(`^.*?(${ this.parentSuiteName() })`), '')
201
+ .trim();
202
+ }
203
+
204
+ private testFrom(started: SceneStarts): Frameworks.Test {
205
+ const
206
+ title = this.testShortTitleFrom(started);
207
+
208
+ return {
209
+ ctx: WebdriverIONotifier.dummmyContext,
210
+ file: started.details.location.path.value,
211
+ fullName: this.suiteNamesConcatenatedWith(title),
212
+ fullTitle: this.suiteNamesConcatenatedWith(title),
213
+ parent: this.parentSuiteName(),
214
+ pending: false,
215
+ title,
216
+ type: 'test' // I _think_ it's either 'test' or 'hook' - https://github.com/mochajs/mocha/blob/0ea732c1169c678ef116c3eb452cc94758fff150/lib/test.js#L31
217
+ }
218
+ }
219
+
220
+ private testStartEventFrom(started: SceneStarts): testStats {
221
+ const title = this.testShortTitleFrom(started);
222
+ return {
223
+ type: 'test:start',
224
+ title,
225
+ fullTitle: this.suiteNamesConcatenatedWith(title),
226
+ parent: this.parentSuiteName(),
227
+ file: started.details.location.path.value,
228
+ pending: false,
229
+ cid: this.cid,
230
+ uid: started.sceneId.value,
231
+ specs: this.specs,
232
+ }
233
+ }
234
+
235
+ private parentSuiteName() {
236
+ return this.suites.at(-1)?.name.value || '';
237
+ }
238
+
239
+ /**
240
+ * test status is 'passed' | 'pending' | 'skipped' | 'failed' | 'broken' | 'canceled'
241
+ * Since this is not documented, we're mimicking other WebdriverIO reporters, for example:
242
+ * https://github.com/webdriverio/webdriverio/blob/7415f3126e15a733b51721492e4995ceafae6046/packages/wdio-allure-reporter/src/constants.ts#L3-L9
243
+ *
244
+ * @param started
245
+ * @param finished
246
+ * @private
247
+ */
248
+ private testResultFrom(started: SceneStarts, finished: SceneFinished): Frameworks.TestResult {
249
+ const duration = finished.timestamp.diff(started.timestamp).inMilliseconds();
250
+ const defaultRetries = { attempts: 0, limit: 0 };
251
+
252
+ const passedOrFailed = (outcome: Outcome): boolean =>
253
+ this.whenSuccessful<boolean>(outcome, true, false);
254
+
255
+ return match<Outcome, Frameworks.TestResult>(finished.outcome)
256
+ .when(ExecutionCompromised, (outcome: ExecutionCompromised) => {
257
+ const error = this.errorFrom(outcome);
258
+ return {
259
+ duration,
260
+ error,
261
+ exception: error.message,
262
+ passed: passedOrFailed(outcome),
263
+ status: 'broken',
264
+ retries: defaultRetries
265
+ }
266
+ })
267
+ .when(ExecutionFailedWithError, (outcome: ExecutionFailedWithError) => {
268
+ const error = this.errorFrom(outcome);
269
+ return {
270
+ duration,
271
+ error,
272
+ exception: error.message,
273
+ passed: passedOrFailed(outcome),
274
+ status: 'broken',
275
+ retries: defaultRetries
276
+ }
277
+ })
278
+ .when(ExecutionFailedWithAssertionError, (outcome: ExecutionFailedWithAssertionError) => {
279
+ const error = this.errorFrom(outcome);
280
+ return {
281
+ duration,
282
+ error,
283
+ exception: error.message,
284
+ passed: passedOrFailed(outcome),
285
+ status: 'failed',
286
+ retries: defaultRetries
287
+ }
288
+ })
289
+ .when(ImplementationPending, (outcome: ImplementationPending) => {
290
+ const error = this.errorFrom(outcome);
291
+ return {
292
+ duration,
293
+ error,
294
+ exception: error.message,
295
+ passed: passedOrFailed(outcome),
296
+ status: 'pending',
297
+ retries: defaultRetries
298
+ }
299
+ })
300
+ .when(ExecutionIgnored, (outcome: ExecutionIgnored) => {
301
+ const error = this.errorFrom(outcome);
302
+ return {
303
+ duration,
304
+ error,
305
+ exception: error.message,
306
+ passed: passedOrFailed(outcome),
307
+ status: 'canceled', // fixme: mark as canceled for now for the lack of a better alternative;
308
+ retries: defaultRetries // consider capturing info about retries from Mocha and putting it on the ExecutionIgnored event so we can pass it on
309
+ }
310
+ })
311
+ .when(ExecutionSkipped, (outcome: ExecutionSkipped) => ({
312
+ duration,
313
+ exception: '',
314
+ passed: passedOrFailed(outcome),
315
+ status: 'skipped',
316
+ retries: defaultRetries
317
+ }))
318
+ .else(() => ({
319
+ duration,
320
+ exception: '',
321
+ passed: true,
322
+ status: 'passed',
323
+ retries: defaultRetries
324
+ }));
325
+ }
326
+
327
+ private testEndEventFrom(started: SceneStarts, finished: SceneFinished): testStats {
328
+ const duration = finished.timestamp.diff(started.timestamp).inMilliseconds();
329
+ return {
330
+ ...this.testStartEventFrom(started),
331
+ type: 'test:end',
332
+ duration
333
+ };
334
+ }
335
+
336
+ private whenSuccessful<O>(outcome: Outcome, resultWhenSuccessful: O, resultWhenNotSuccessful: O): O {
337
+ return ! outcome.isWorseThan(this.successThreshold) && (outcome instanceof ProblemIndication)
338
+ ? resultWhenSuccessful
339
+ : resultWhenNotSuccessful
340
+ }
341
+
342
+ private testResultEventFrom(started: SceneStarts, finished: SceneFinished): testStats {
343
+ const test = this.testEndEventFrom(started, finished)
344
+
345
+ const unlessSuccessful = (outcome: Outcome, type: testStats['type']) =>
346
+ this.whenSuccessful<testStats['type']>(outcome, 'test:pass', type);
347
+
348
+ return match<Outcome, testStats>(finished.outcome)
349
+ .when(ExecutionCompromised, (outcome: ExecutionCompromised) => ({
350
+ ...test,
351
+ type: unlessSuccessful(outcome, 'test:fail'),
352
+ error: this.errorFrom(outcome),
353
+ }))
354
+ .when(ExecutionFailedWithError, (outcome: ExecutionFailedWithError) => ({
355
+ ...test,
356
+ type: unlessSuccessful(outcome, 'test:fail'),
357
+ error: this.errorFrom(outcome),
358
+ }))
359
+ .when(ExecutionFailedWithAssertionError, (outcome: ExecutionFailedWithAssertionError) => ({
360
+ ...test,
361
+ type: unlessSuccessful(outcome, 'test:fail'),
362
+ error: this.errorFrom(outcome),
363
+ }))
364
+ .when(ImplementationPending, (outcome: ImplementationPending) => ({
365
+ ...test,
366
+ type: unlessSuccessful(outcome, 'test:pending'),
367
+ error: this.errorFrom(outcome),
368
+ pending: true,
369
+ pendingReason: outcome.error.message
370
+ }))
371
+ .when(ExecutionIgnored, (outcome: ExecutionIgnored) => ({
372
+ ...test,
373
+ // In WebdriverIO, skipped == pending == ignored
374
+ // https://github.com/webdriverio/webdriverio/blob/a1830046f367be7737af2c00561796c3ae5dd85b/packages/wdio-reporter/src/index.ts#L162
375
+ type: unlessSuccessful(outcome, 'test:pending'),
376
+ error: this.errorFrom(outcome),
377
+ pending: true,
378
+ pendingReason: outcome.error.message
379
+ }))
380
+ .when(ExecutionSkipped, (outcome: ExecutionSkipped) => ({
381
+ ...test,
382
+ // In WebdriverIO, skipped == pending == ignored
383
+ // https://github.com/webdriverio/webdriverio/blob/a1830046f367be7737af2c00561796c3ae5dd85b/packages/wdio-reporter/src/index.ts#L162
384
+ type: unlessSuccessful(outcome, 'test:pending'),
385
+ pending: true,
386
+ }))
387
+ .else(() => ({
388
+ ...test,
389
+ type: 'test:pass',
390
+ }));
391
+ }
392
+
393
+ private errorFrom(outcome: ProblemIndication) {
394
+ const error: Error & { type?: string, expected?: string, actual?: string } = outcome.error;
395
+
396
+ // https://github.com/webdriverio/webdriverio/blob/7ec2c60a7623de431d60bb3605957e6e4bdf057b/packages/wdio-mocha-framework/src/index.ts#L233
397
+ return {
398
+ name: error.name,
399
+ message: error.message,
400
+ stack: error.stack,
401
+ type: error.type || error.name,
402
+ expected: error.expected,
403
+ actual: error.actual
404
+ }
405
+ }
406
+
407
+ /**
408
+ * @see https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-utils/src/shim.ts
409
+ * @param hookName
410
+ * @param hookFunctions
411
+ * @param args
412
+ * @private
413
+ */
414
+ private invokeHooks<Result, InnerArguments extends any[]>(
415
+ hookName: string,
416
+ hookFunctions: ((...parameters: InnerArguments) => Promise<Result> | Result) | Array<((...parameters: InnerArguments) => Result)>,
417
+ args: InnerArguments
418
+ ): Promise<Array<Result | Error>> {
419
+
420
+ const hooks = Array.isArray(hookFunctions)
421
+ ? hookFunctions
422
+ : [ hookFunctions ];
423
+
424
+ const asyncOperationId = CorrelationId.create();
425
+
426
+ this.stage.announce(new AsyncOperationAttempted(
427
+ new Name(`WebdriverIONotifier#invokeHooks`),
428
+ new Description(`Invoking ${ hookName } hook`),
429
+ asyncOperationId,
430
+ this.stage.currentTime(),
431
+ ));
432
+
433
+ return Promise.all(hooks.map((hook) => new Promise<Result | Error>((resolve) => {
434
+ let result
435
+
436
+ try {
437
+ result = hook(...args);
438
+ } catch (error) {
439
+ return resolve(error);
440
+ }
441
+
442
+ /**
443
+ * if a promise is returned make sure we don't have a catch handler
444
+ * so in case of a rejection it won't cause the hook to fail
445
+ */
446
+ if (result && typeof result.then === 'function') {
447
+ return result.then(resolve, (error: Error) => {
448
+ resolve(error);
449
+ })
450
+ }
451
+
452
+ resolve(result);
453
+ }))).
454
+ then(results => {
455
+
456
+ this.stage.announce(new AsyncOperationCompleted(
457
+ asyncOperationId,
458
+ this.stage.currentTime(),
459
+ ));
460
+
461
+ return results;
462
+ });
463
+ }
464
+ }
465
+
466
+ class EventLog {
467
+ private readonly events = new Map<string, DomainEvent>();
468
+
469
+ record(correlationId: CorrelationId, event: DomainEvent) {
470
+ this.events.set(correlationId.value, event)
471
+ }
472
+
473
+ getByCorrelationId<T extends DomainEvent>(correlationId: CorrelationId): T {
474
+ if (! this.events.has(correlationId.value)) {
475
+ throw new LogicError(`Event with correlation id ${ correlationId } has never been recorded`);
476
+ }
477
+
478
+ return this.events.get(correlationId.value) as T;
479
+ }
480
+ }
@@ -0,0 +1 @@
1
+ export * from './WebdriverIOFrameworkAdapterFactory.js';
@@ -0,0 +1,63 @@
1
+ import type { Serenity } from '@serenity-js/core';
2
+ import { SceneTagged } from '@serenity-js/core/lib/events/index.js';
3
+ import type { Tag } from '@serenity-js/core/lib/model/index.js';
4
+ import Reporter from '@wdio/reporter';
5
+ import type { Capabilities, Options, Reporters } from '@wdio/types';
6
+
7
+ import { TagPrinter } from './TagPrinter.js';
8
+
9
+ /**
10
+ * @package
11
+ */
12
+ export class BrowserCapabilitiesReporter extends Reporter {
13
+
14
+ private readonly tagPrinter = new TagPrinter();
15
+ private readonly serenity: Serenity;
16
+
17
+ private readonly tags: Tag[] = [];
18
+
19
+ constructor (options: Partial<Reporters.Options> & { serenity: Serenity }) {
20
+ super({ ...options, stdout: false });
21
+
22
+ this.serenity = options.serenity;
23
+
24
+ this.on('runner:start', BrowserCapabilitiesReporter.prototype.recordBrowserAndPlatformTags.bind(this));
25
+ this.on('test:start', BrowserCapabilitiesReporter.prototype.emitRecordedTags.bind(this));
26
+ }
27
+
28
+ private recordBrowserAndPlatformTags(event: Options.RunnerStart) {
29
+ const tags = event.isMultiremote
30
+ ? this.tagsForAll(event.capabilities as unknown as Record<string, Capabilities.DesiredCapabilities | Capabilities.W3CCapabilities>) // fixme: WDIO MultiremoteCapabilities seem to have incorrect definition?
31
+ : this.tagPrinter.tagsFor(event.capabilities)
32
+
33
+ this.tags.push(...tags);
34
+ }
35
+
36
+ private tagsForAll(capabilities: Record<string, Capabilities.DesiredCapabilities | Capabilities.W3CCapabilities>): Tag[] {
37
+ return Object.keys(capabilities)
38
+ .reduce((existingTags, entryName) => {
39
+
40
+ const newTags = this.tagPrinter.tagsFor(capabilities[entryName]);
41
+ const uniqueNewTags = newTags.filter(tag => ! existingTags.some((existingTag: Tag) => existingTag.equals(tag)));
42
+
43
+ return [
44
+ ...existingTags,
45
+ // todo: maybe add some additional tag to indicate the custom capability name,
46
+ // or the fact that it's a multi-remote scenario?
47
+ ...uniqueNewTags,
48
+ ];
49
+ }, []);
50
+ }
51
+
52
+ private emitRecordedTags() {
53
+ this.tags.forEach(tag => {
54
+ this.serenity.announce(
55
+ new SceneTagged(
56
+ this.serenity.currentSceneId(),
57
+ tag,
58
+ this.serenity.currentTime(),
59
+ )
60
+ )
61
+ })
62
+ }
63
+ }
@@ -0,0 +1,8 @@
1
+ import type { Reporters } from '@wdio/types';
2
+
3
+ /**
4
+ * @package
5
+ */
6
+ export interface InitialisesReporters {
7
+ _loadReporter(reporter: Reporters.ReporterEntry): Promise<void>;
8
+ }
@@ -0,0 +1,30 @@
1
+ import type { OutputStream } from '@serenity-js/core/lib/adapter/index.js';
2
+
3
+ /**
4
+ * @package
5
+ */
6
+ export class OutputStreamBuffer implements OutputStream {
7
+ private buffer = '';
8
+
9
+ constructor(private readonly prefix: string) {
10
+ }
11
+
12
+ write(content: string): void {
13
+ this.buffer += content;
14
+ }
15
+
16
+ hasContent(): boolean {
17
+ return this.buffer !== '';
18
+ }
19
+
20
+ flush(): string {
21
+ const prefixedContent = this.buffer
22
+ .split('\n')
23
+ .map(line => `${ this.prefix } ${ line }\n`)
24
+ .join('');
25
+
26
+ this.buffer = '';
27
+
28
+ return prefixedContent;
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ import type { Stage, StageCrewMember } from '@serenity-js/core';
2
+ import type { OutputStream } from '@serenity-js/core/lib/adapter/index.js';
3
+ import type { DomainEvent} from '@serenity-js/core/lib/events/index.js';
4
+ import { SceneFinished } from '@serenity-js/core/lib/events/index.js';
5
+
6
+ import type { OutputStreamBuffer } from './OutputStreamBuffer.js';
7
+
8
+ /**
9
+ * @package
10
+ */
11
+ export class OutputStreamBufferPrinter implements StageCrewMember {
12
+ constructor(
13
+ private readonly buffer: OutputStreamBuffer,
14
+ private readonly outputStream: OutputStream,
15
+ private stage?: Stage,
16
+ ) {
17
+ }
18
+
19
+ assignedTo(stage: Stage): StageCrewMember {
20
+ this.stage = stage;
21
+
22
+ return this;
23
+ }
24
+
25
+ notifyOf(event: DomainEvent): void {
26
+ if (event instanceof SceneFinished && this.buffer.hasContent()) {
27
+ this.outputStream.write(this.buffer.flush());
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ import type { OutputStream } from '@serenity-js/core/lib/adapter/index.js';
2
+
3
+ /**
4
+ * @package
5
+ */
6
+ export interface ProvidesWriteStream {
7
+ getWriteStreamObject(reporter: string): OutputStream;
8
+ }