dceky 1.0.5-beta.ky-declarations.12 → 1.0.5

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 (243) hide show
  1. package/README.md +45 -29
  2. package/lib/commands/assertDoesNotHaveClass.d.ts +18 -0
  3. package/lib/commands/assertDoesNotHaveClass.js +17 -0
  4. package/lib/commands/assertDoesNotHaveClass.js.map +1 -0
  5. package/lib/commands/assertHasClass.d.ts +18 -0
  6. package/lib/commands/assertHasClass.js +17 -0
  7. package/lib/commands/assertHasClass.js.map +1 -0
  8. package/lib/commands/assertNumElements.d.ts +18 -0
  9. package/lib/commands/assertNumElements.js +17 -0
  10. package/lib/commands/assertNumElements.js.map +1 -0
  11. package/lib/commands/clickWithRetry.d.ts +19 -0
  12. package/lib/commands/clickWithRetry.js +29 -0
  13. package/lib/commands/clickWithRetry.js.map +1 -0
  14. package/lib/commands/genTextOfLength.d.ts +20 -0
  15. package/lib/commands/genTextOfLength.js +20 -0
  16. package/lib/commands/genTextOfLength.js.map +1 -0
  17. package/lib/commands/getAttribute.d.ts +20 -0
  18. package/lib/commands/getAttribute.js +22 -0
  19. package/lib/commands/getAttribute.js.map +1 -0
  20. package/lib/commands/getClassName.d.ts +15 -0
  21. package/lib/commands/getClassName.js +21 -0
  22. package/lib/commands/getClassName.js.map +1 -0
  23. package/lib/commands/getCurrentDateInfo.d.ts +21 -0
  24. package/lib/commands/getCurrentDateInfo.js +25 -0
  25. package/lib/commands/getCurrentDateInfo.js.map +1 -0
  26. package/lib/commands/getId.d.ts +15 -0
  27. package/lib/commands/getId.js +21 -0
  28. package/lib/commands/getId.js.map +1 -0
  29. package/lib/commands/getNumElements.d.ts +14 -0
  30. package/lib/commands/getNumElements.js +19 -0
  31. package/lib/commands/getNumElements.js.map +1 -0
  32. package/lib/commands/getSpecialChars.d.ts +14 -0
  33. package/lib/commands/getSpecialChars.js +16 -0
  34. package/lib/commands/getSpecialChars.js.map +1 -0
  35. package/lib/commands/getTitle.d.ts +13 -0
  36. package/lib/commands/getTitle.js +20 -0
  37. package/lib/commands/getTitle.js.map +1 -0
  38. package/lib/commands/handleHarvardKey.d.ts +18 -0
  39. package/lib/commands/handleHarvardKey.js +56 -0
  40. package/lib/commands/handleHarvardKey.js.map +1 -0
  41. package/lib/commands/handleHarvardKey2.d.ts +14 -0
  42. package/lib/commands/handleHarvardKey2.js +88 -0
  43. package/lib/commands/handleHarvardKey2.js.map +1 -0
  44. package/lib/commands/launchAs.d.ts +20 -0
  45. package/lib/commands/launchAs.js +60 -0
  46. package/lib/commands/launchAs.js.map +1 -0
  47. package/lib/commands/launchLTIUsingToken.d.ts +19 -0
  48. package/lib/commands/launchLTIUsingToken.js +74 -0
  49. package/lib/commands/launchLTIUsingToken.js.map +1 -0
  50. package/lib/commands/listSelectLabels.d.ts +15 -0
  51. package/lib/commands/listSelectLabels.js +24 -0
  52. package/lib/commands/listSelectLabels.js.map +1 -0
  53. package/lib/commands/listSelectValues.d.ts +15 -0
  54. package/lib/commands/listSelectValues.js +26 -0
  55. package/lib/commands/listSelectValues.js.map +1 -0
  56. package/lib/commands/navigateToHref.d.ts +19 -0
  57. package/lib/commands/navigateToHref.js +23 -0
  58. package/lib/commands/navigateToHref.js.map +1 -0
  59. package/lib/commands/padWithZeros.d.ts +20 -0
  60. package/lib/commands/padWithZeros.js +24 -0
  61. package/lib/commands/padWithZeros.js.map +1 -0
  62. package/lib/commands/runScript.d.ts +16 -0
  63. package/lib/commands/runScript.js +25 -0
  64. package/lib/commands/runScript.js.map +1 -0
  65. package/lib/commands/typeInto.d.ts +20 -0
  66. package/lib/commands/typeInto.js +28 -0
  67. package/lib/commands/typeInto.js.map +1 -0
  68. package/lib/commands/uniquify.d.ts +15 -0
  69. package/lib/commands/uniquify.js +25 -0
  70. package/lib/commands/uniquify.js.map +1 -0
  71. package/lib/commands/visitCanvasEndpoint.d.ts +27 -0
  72. package/lib/commands/visitCanvasEndpoint.js +35 -0
  73. package/lib/commands/visitCanvasEndpoint.js.map +1 -0
  74. package/lib/commands/visitCanvasGETEndpoint.d.ts +20 -0
  75. package/lib/commands/visitCanvasGETEndpoint.js +26 -0
  76. package/lib/commands/visitCanvasGETEndpoint.js.map +1 -0
  77. package/lib/commands/waitForAtLeastOneElementPresent.d.ts +23 -0
  78. package/lib/commands/waitForAtLeastOneElementPresent.js +27 -0
  79. package/lib/commands/waitForAtLeastOneElementPresent.js.map +1 -0
  80. package/lib/commands/waitForElementVisible.d.ts +14 -0
  81. package/lib/commands/waitForElementVisible.js +20 -0
  82. package/lib/commands/waitForElementVisible.js.map +1 -0
  83. package/lib/index.js.map +1 -0
  84. package/lib/init.d.ts +6 -0
  85. package/lib/init.js +69 -0
  86. package/lib/init.js.map +1 -0
  87. package/lib/setup/genCommandImportFile.js +5 -0
  88. package/lib/setup/genCommandImportFile.js.map +1 -1
  89. package/lib/setup/genE2ELaunchFile.js +5 -0
  90. package/lib/setup/genE2ELaunchFile.js.map +1 -1
  91. package/lib/src/commands/extractDataFromClass.d.ts +7 -4
  92. package/lib/src/commands/extractDataFromClass.js +2 -1
  93. package/lib/src/commands/extractDataFromClass.js.map +1 -1
  94. package/lib/src/commands/extractDataFromClassByContents.d.ts +9 -5
  95. package/lib/src/commands/extractDataFromClassByContents.js +2 -1
  96. package/lib/src/commands/extractDataFromClassByContents.js.map +1 -1
  97. package/lib/src/commands/genTextOfLength.d.ts +20 -0
  98. package/lib/src/commands/genTextOfLength.js +20 -0
  99. package/lib/src/commands/genTextOfLength.js.map +1 -0
  100. package/lib/src/commands/getAttribute.d.ts +20 -0
  101. package/lib/src/commands/getAttribute.js +22 -0
  102. package/lib/src/commands/getAttribute.js.map +1 -0
  103. package/lib/src/commands/getClassName.d.ts +15 -0
  104. package/lib/src/commands/getClassName.js +21 -0
  105. package/lib/src/commands/getClassName.js.map +1 -0
  106. package/lib/src/commands/getCurrentDateInfo.d.ts +21 -0
  107. package/lib/src/commands/getCurrentDateInfo.js +25 -0
  108. package/lib/src/commands/getCurrentDateInfo.js.map +1 -0
  109. package/lib/src/commands/getId.d.ts +15 -0
  110. package/lib/src/commands/getId.js +21 -0
  111. package/lib/src/commands/getId.js.map +1 -0
  112. package/lib/src/commands/getJSON.d.ts +0 -1
  113. package/lib/src/commands/getJSON.js +1 -4
  114. package/lib/src/commands/getJSON.js.map +1 -1
  115. package/lib/src/commands/getSpecialChars.d.ts +14 -0
  116. package/lib/src/commands/getSpecialChars.js +16 -0
  117. package/lib/src/commands/getSpecialChars.js.map +1 -0
  118. package/lib/src/commands/getTitle.d.ts +13 -0
  119. package/lib/src/commands/getTitle.js +20 -0
  120. package/lib/src/commands/getTitle.js.map +1 -0
  121. package/lib/src/commands/index.js +29 -5
  122. package/lib/src/commands/index.js.map +1 -1
  123. package/lib/src/commands/launchLTIUsingToken.js +12 -4
  124. package/lib/src/commands/launchLTIUsingToken.js.map +1 -1
  125. package/lib/src/commands/listSelectLabels.d.ts +15 -0
  126. package/lib/src/commands/listSelectLabels.js +24 -0
  127. package/lib/src/commands/listSelectLabels.js.map +1 -0
  128. package/lib/src/commands/listSelectValues.d.ts +15 -0
  129. package/lib/src/commands/listSelectValues.js +27 -0
  130. package/lib/src/commands/listSelectValues.js.map +1 -0
  131. package/lib/src/commands/padWithZeros.d.ts +20 -0
  132. package/lib/src/commands/padWithZeros.js +24 -0
  133. package/lib/src/commands/padWithZeros.js.map +1 -0
  134. package/lib/src/commands/uniquify.d.ts +15 -0
  135. package/lib/src/commands/uniquify.js +26 -0
  136. package/lib/src/commands/uniquify.js.map +1 -0
  137. package/lib/src/commands/visitCanvasEndpoint.d.ts +26 -0
  138. package/lib/src/commands/visitCanvasEndpoint.js +36 -0
  139. package/lib/src/commands/visitCanvasEndpoint.js.map +1 -0
  140. package/lib/src/commands/waitForAtLeastOneElementPresent.d.ts +23 -0
  141. package/lib/src/commands/waitForAtLeastOneElementPresent.js +28 -0
  142. package/lib/src/commands/waitForAtLeastOneElementPresent.js.map +1 -0
  143. package/lib/src/init.js +28 -2
  144. package/lib/src/init.js.map +1 -1
  145. package/lib/start/constants/DEFAULT_THREADS_PER_COMBO.d.ts +6 -0
  146. package/lib/start/constants/DEFAULT_THREADS_PER_COMBO.js +9 -0
  147. package/lib/start/constants/DEFAULT_THREADS_PER_COMBO.js.map +1 -0
  148. package/lib/start/helpers/collectPngFiles.d.ts +9 -0
  149. package/lib/start/helpers/collectPngFiles.js +31 -0
  150. package/lib/start/helpers/collectPngFiles.js.map +1 -0
  151. package/lib/start/helpers/executeAllHeadlessCombinations.d.ts +15 -0
  152. package/lib/start/helpers/executeAllHeadlessCombinations.js +116 -0
  153. package/lib/start/helpers/executeAllHeadlessCombinations.js.map +1 -0
  154. package/lib/start/helpers/executeCypress.d.ts +17 -0
  155. package/lib/start/helpers/executeCypress.js +103 -0
  156. package/lib/start/helpers/executeCypress.js.map +1 -0
  157. package/lib/start/helpers/generateHtmlReport.d.ts +14 -0
  158. package/lib/start/helpers/generateHtmlReport.js +54 -0
  159. package/lib/start/helpers/generateHtmlReport.js.map +1 -0
  160. package/lib/start/helpers/generateReportHomepage.d.ts +9 -0
  161. package/lib/start/helpers/generateReportHomepage.js +142 -0
  162. package/lib/start/helpers/generateReportHomepage.js.map +1 -0
  163. package/lib/start/helpers/generateReporterConfig.d.ts +17 -0
  164. package/lib/start/helpers/generateReporterConfig.js +32 -0
  165. package/lib/start/helpers/generateReporterConfig.js.map +1 -0
  166. package/lib/start/helpers/getDateLabeledDir.d.ts +7 -0
  167. package/lib/start/helpers/getDateLabeledDir.js +38 -0
  168. package/lib/start/helpers/getDateLabeledDir.js.map +1 -0
  169. package/lib/start/helpers/mergeAllReportsAndGenerateHtml.d.ts +11 -0
  170. package/lib/start/helpers/mergeAllReportsAndGenerateHtml.js +121 -0
  171. package/lib/start/helpers/mergeAllReportsAndGenerateHtml.js.map +1 -0
  172. package/lib/start/helpers/mergeReports.d.ts +14 -0
  173. package/lib/start/helpers/mergeReports.js +63 -0
  174. package/lib/start/helpers/mergeReports.js.map +1 -0
  175. package/lib/start/helpers/reportHomepage.ejs +272 -0
  176. package/lib/start/helpers/runCypressHeadless.d.ts +18 -0
  177. package/lib/start/helpers/runCypressHeadless.js +138 -0
  178. package/lib/start/helpers/runCypressHeadless.js.map +1 -0
  179. package/lib/start/helpers/runCypressVisible.d.ts +8 -0
  180. package/lib/start/helpers/runCypressVisible.js +53 -0
  181. package/lib/start/helpers/runCypressVisible.js.map +1 -0
  182. package/lib/start/index.js +23 -5
  183. package/lib/start/index.js.map +1 -1
  184. package/lib/start/types/MochawesomeReporterConfig.d.ts +15 -0
  185. package/lib/start/types/MochawesomeReporterConfig.js +3 -0
  186. package/lib/start/types/MochawesomeReporterConfig.js.map +1 -0
  187. package/lib/start/types/Profile.d.ts +9 -0
  188. package/lib/start/types/Profile.js +3 -0
  189. package/lib/start/types/Profile.js.map +1 -0
  190. package/lib/start/types/ReportInfo.d.ts +14 -0
  191. package/lib/start/types/ReportInfo.js +3 -0
  192. package/lib/start/types/ReportInfo.js.map +1 -0
  193. package/lib/start/types/RunResult.d.ts +12 -0
  194. package/lib/start/types/RunResult.js +3 -0
  195. package/lib/start/types/RunResult.js.map +1 -0
  196. package/lib/start/types/ScreenshotInfo.d.ts +10 -0
  197. package/lib/start/types/ScreenshotInfo.js +3 -0
  198. package/lib/start/types/ScreenshotInfo.js.map +1 -0
  199. package/lib/start/types/TemplateReportInfo.d.ts +12 -0
  200. package/lib/start/types/TemplateReportInfo.js +3 -0
  201. package/lib/start/types/TemplateReportInfo.js.map +1 -0
  202. package/package.json +10 -8
  203. package/setup/genCommandImportFile.ts +6 -0
  204. package/setup/genE2ELaunchFile.ts +6 -0
  205. package/src/commands/extractDataFromClass.ts +17 -6
  206. package/src/commands/extractDataFromClassByContents.ts +21 -8
  207. package/src/commands/genTextOfLength.ts +54 -0
  208. package/src/commands/getAttribute.ts +58 -0
  209. package/src/commands/getClassName.ts +44 -0
  210. package/src/commands/getCurrentDateInfo.ts +57 -0
  211. package/src/commands/getId.ts +44 -0
  212. package/src/commands/getJSON.ts +0 -4
  213. package/src/commands/getSpecialChars.ts +34 -0
  214. package/src/commands/getTitle.ts +39 -0
  215. package/src/commands/index.ts +29 -5
  216. package/src/commands/launchLTIUsingToken.ts +12 -4
  217. package/src/commands/listSelectLabels.ts +47 -0
  218. package/src/commands/listSelectValues.ts +50 -0
  219. package/src/commands/padWithZeros.ts +53 -0
  220. package/src/commands/uniquify.ts +49 -0
  221. package/src/commands/visitCanvasEndpoint.ts +75 -0
  222. package/src/commands/waitForAtLeastOneElementPresent.ts +64 -0
  223. package/start/constants/DEFAULT_THREADS_PER_COMBO.ts +7 -0
  224. package/start/helpers/collectPngFiles.ts +25 -0
  225. package/start/helpers/executeAllHeadlessCombinations.ts +92 -0
  226. package/start/helpers/executeCypress.ts +66 -0
  227. package/start/helpers/generateHtmlReport.ts +71 -0
  228. package/start/helpers/generateReportHomepage.ts +148 -0
  229. package/start/helpers/generateReporterConfig.ts +39 -0
  230. package/start/helpers/getDateLabeledDir.ts +43 -0
  231. package/start/helpers/mergeAllReportsAndGenerateHtml.ts +150 -0
  232. package/start/helpers/mergeReports.ts +82 -0
  233. package/start/helpers/reportHomepage.ejs +272 -0
  234. package/start/helpers/runCypressHeadless.ts +164 -0
  235. package/start/helpers/runCypressVisible.ts +45 -0
  236. package/start/index.ts +23 -5
  237. package/start/types/MochawesomeReporterConfig.ts +23 -0
  238. package/start/types/Profile.ts +12 -0
  239. package/start/types/ReportInfo.ts +22 -0
  240. package/start/types/RunResult.ts +18 -0
  241. package/start/types/ScreenshotInfo.ts +13 -0
  242. package/start/types/TemplateReportInfo.ts +16 -0
  243. package/src/commands/visitCanvasGETEndpoint.ts +0 -61
@@ -0,0 +1,272 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Cypress Test Reports</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+ body {
14
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
15
+ background: #f5f5f5;
16
+ padding: 2rem 1rem;
17
+ color: #222;
18
+ }
19
+ .container {
20
+ max-width: 75rem;
21
+ margin: 0 auto;
22
+ background: #ffffff;
23
+ border-radius: 0.5rem;
24
+ border: 0.0625rem solid #e0e0e0;
25
+ box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.04);
26
+ }
27
+ header {
28
+ border-bottom: 0.0625rem solid #e0e0e0;
29
+ padding: 1.25rem 1.5rem;
30
+ text-align: center;
31
+ }
32
+ h1 {
33
+ font-size: 1.75rem;
34
+ margin-bottom: 0.625rem;
35
+ }
36
+ .subtitle {
37
+ font-size: 0.95rem;
38
+ color: #666666;
39
+ }
40
+ .content {
41
+ padding: 1.5rem;
42
+ }
43
+ .profile-section {
44
+ margin-bottom: 2.5rem;
45
+ }
46
+ .profile-title {
47
+ font-size: 1.1rem;
48
+ color: #111111;
49
+ margin-bottom: 0.75rem;
50
+ border-bottom: 0.0625rem solid #e0e0e0;
51
+ padding-bottom: 0.375rem;
52
+ }
53
+ .report-grid {
54
+ display: grid;
55
+ grid-template-columns: repeat(auto-fill, minmax(15.625rem, 1fr));
56
+ gap: 1.25rem;
57
+ margin-bottom: 1.875rem;
58
+ }
59
+ .report-card {
60
+ border: 0.0625rem solid #e0e0e0;
61
+ border-radius: 0.5rem;
62
+ padding: 1rem;
63
+ background: #fafafa;
64
+ }
65
+ .report-card.success {
66
+ border-color: #c8e6c9;
67
+ background: #f4f9f4;
68
+ }
69
+ .report-card.failed {
70
+ border-color: #ffcdd2;
71
+ background: #fdf5f6;
72
+ }
73
+ .browser-name {
74
+ font-size: 1rem;
75
+ font-weight: bold;
76
+ color: #222222;
77
+ margin-bottom: 0.625rem;
78
+ text-transform: capitalize;
79
+ }
80
+ .status {
81
+ display: inline-block;
82
+ padding: 0.25rem 0.75rem;
83
+ border-radius: 0.75rem;
84
+ font-size: 0.85em;
85
+ font-weight: bold;
86
+ margin-bottom: 0.625rem;
87
+ }
88
+ .status.success {
89
+ background: #2e7d32;
90
+ color: white;
91
+ }
92
+ .status.failed {
93
+ background: #c62828;
94
+ color: white;
95
+ }
96
+ .report-link {
97
+ display: inline-block;
98
+ margin-top: 0.625rem;
99
+ padding: 0.5rem 1rem;
100
+ background: #1976d2;
101
+ color: white;
102
+ text-decoration: none;
103
+ border-radius: 0.375rem;
104
+ transition: background 0.3s ease;
105
+ }
106
+ .report-link:hover {
107
+ background: #115293;
108
+ }
109
+ .timestamp {
110
+ font-size: 0.85em;
111
+ color: #777777;
112
+ margin-top: 0.5rem;
113
+ }
114
+ .summary {
115
+ background: #fafafa;
116
+ padding: 1rem 1.125rem;
117
+ border-radius: 0.375rem;
118
+ margin-bottom: 1.875rem;
119
+ border: 0.0625rem solid #e0e0e0;
120
+ }
121
+ .summary h2 {
122
+ color: #111111;
123
+ margin-bottom: 0.625rem;
124
+ font-size: 1rem;
125
+ }
126
+ .summary-stats {
127
+ display: flex;
128
+ gap: 1.25rem;
129
+ flex-wrap: wrap;
130
+ }
131
+ .stat {
132
+ display: flex;
133
+ flex-direction: column;
134
+ }
135
+ .stat-value {
136
+ font-size: 1.4rem;
137
+ font-weight: bold;
138
+ color: #1976d2;
139
+ }
140
+ .stat-label {
141
+ font-size: 0.9em;
142
+ color: #777777;
143
+ text-transform: uppercase;
144
+ letter-spacing: 0.0625rem;
145
+ }
146
+ .combined-report {
147
+ margin-bottom: 1.5rem;
148
+ padding: 0.875rem 1rem;
149
+ border-radius: 0.375rem;
150
+ border: 0.0625rem solid #d0d0d0;
151
+ background: #f9fafb;
152
+ display: flex;
153
+ align-items: center;
154
+ justify-content: space-between;
155
+ gap: 0.75rem;
156
+ }
157
+ .combined-report-title {
158
+ font-size: 0.95rem;
159
+ font-weight: 500;
160
+ color: #111111;
161
+ }
162
+ .combined-report-subtitle {
163
+ font-size: 0.85rem;
164
+ color: #777777;
165
+ margin-top: 0.125rem;
166
+ }
167
+ .combined-report-button {
168
+ padding: 0.5rem 1rem;
169
+ border-radius: 0.25rem;
170
+ border: 0.0625rem solid #1976d2;
171
+ background: #1976d2;
172
+ color: #ffffff;
173
+ text-decoration: none;
174
+ font-size: 0.9rem;
175
+ font-weight: 500;
176
+ white-space: nowrap;
177
+ }
178
+ .combined-report-button:hover {
179
+ background: #115293;
180
+ border-color: #115293;
181
+ }
182
+ .screenshot-list {
183
+ list-style: none;
184
+ padding-left: 0;
185
+ margin-top: 0.5rem;
186
+ }
187
+ .no-report {
188
+ color: #999;
189
+ font-size: 0.9em;
190
+ }
191
+ </style>
192
+ </head>
193
+ <body>
194
+ <div class="container">
195
+ <header>
196
+ <h1>Cypress Test Reports</h1>
197
+ <p class="subtitle">Profile and browser run summary</p>
198
+ </header>
199
+ <div class="content">
200
+ <% if (hasCombinedReport) { %>
201
+ <div class="combined-report">
202
+ <div>
203
+ <div class="combined-report-title">Combined report for all profiles and browsers</div>
204
+ <div class="combined-report-subtitle">
205
+ <% if (combinedTotalTests !== null && combinedPassedTests !== null) { %>
206
+ <%= combinedPassedTests %>/<%= combinedTotalTests %> tests passing in this run.
207
+ <% } else { %>
208
+ View a single consolidated Mochawesome report for this run.
209
+ <% } %>
210
+ </div>
211
+ </div>
212
+ <a href="all-runs.html" class="combined-report-button" target="_blank">Open combined report</a>
213
+ </div>
214
+ <% } %>
215
+
216
+ <div class="summary">
217
+ <h2>Summary</h2>
218
+ <div class="summary-stats">
219
+ <div class="stat">
220
+ <div class="stat-value"><%= totalRuns %></div>
221
+ <div class="stat-label">Total Runs</div>
222
+ </div>
223
+ <div class="stat">
224
+ <div class="stat-value"><%= passedRuns %></div>
225
+ <div class="stat-label">Passed</div>
226
+ </div>
227
+ <div class="stat">
228
+ <div class="stat-value"><%= failedRuns %></div>
229
+ <div class="stat-label">Failed</div>
230
+ </div>
231
+ <div class="stat">
232
+ <div class="stat-value"><%= profileCount %></div>
233
+ <div class="stat-label">Profiles</div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+
238
+ <% Object.entries(reportsByProfile).forEach(([profileName, profileReports]) => { %>
239
+ <div class="profile-section">
240
+ <h2 class="profile-title">📋 Profile: <%= profileName %></h2>
241
+ <div class="report-grid">
242
+ <% profileReports.forEach((report) => { %>
243
+ <div class="report-card <%= report.success ? 'success' : 'failed' %>">
244
+ <div class="browser-name">🌐 <%= report.browser %></div>
245
+ <span class="status <%= report.success ? 'success' : 'failed' %>">
246
+ <%= report.success ? '✅ Passed' : '❌ Failed' %>
247
+ </span>
248
+ <% if (report.totalTests !== undefined && report.passedTests !== undefined) { %>
249
+ <div class="timestamp"><%= report.passedTests %>/<%= report.totalTests %> tests passing</div>
250
+ <% } %>
251
+ <div class="timestamp"><%= report.timestamp %></div>
252
+ <% if (report.relativeReportPath) { %>
253
+ <a href="<%= report.relativeReportPath %>" class="report-link" target="_blank">View Report</a>
254
+ <% } else { %>
255
+ <p class="no-report">Report not available</p>
256
+ <% } %>
257
+ <% if (report.screenshots && report.screenshots.length > 0) { %>
258
+ <ul class="screenshot-list">
259
+ <% report.screenshots.forEach((screenshot) => { %>
260
+ <li><a href="<%= screenshot.href %>" class="report-link" target="_blank"><%= screenshot.name %></a></li>
261
+ <% }) %>
262
+ </ul>
263
+ <% } %>
264
+ </div>
265
+ <% }) %>
266
+ </div>
267
+ </div>
268
+ <% }) %>
269
+ </div>
270
+ </div>
271
+ </body>
272
+ </html>
@@ -0,0 +1,164 @@
1
+ /* eslint-disable no-console */
2
+
3
+ // Import libs
4
+ import { spawn } from 'child_process';
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+
8
+ // Import helpers
9
+ import getRootPath from './getRootPath';
10
+ import generateReporterConfig from './generateReporterConfig';
11
+ import mergeReports from './mergeReports';
12
+ import generateHtmlReport from './generateHtmlReport';
13
+
14
+ // Import shared types
15
+ import RunResult from '../types/RunResult';
16
+
17
+ // Import constants
18
+ import DEFAULT_THREADS_PER_COMBO from '../constants/DEFAULT_THREADS_PER_COMBO';
19
+
20
+ /**
21
+ * Run Cypress in headless mode for a single profile and browser using cypress-parallel
22
+ * @author Yuen Ler Chow
23
+ * @param opts - object of arguments
24
+ * @param opts.profileName - The profile name to use
25
+ * @param opts.browser - The browser to use
26
+ * @param opts.outputDir - The output directory for results
27
+ * @param [opts.numThreads] - The number of parallel threads to use (default: 2)
28
+ * @returns Promise that resolves with run result
29
+ */
30
+ const runCypressHeadless = (opts: {
31
+ profileName: string,
32
+ browser: string,
33
+ outputDir: string,
34
+ numThreads?: number,
35
+ }): Promise<RunResult> => {
36
+ const {
37
+ profileName,
38
+ browser,
39
+ outputDir,
40
+ numThreads = DEFAULT_THREADS_PER_COMBO,
41
+ } = opts;
42
+
43
+ return new Promise((resolve, reject) => {
44
+ const root = getRootPath();
45
+
46
+ // Ensure output directory exists
47
+ if (!fs.existsSync(outputDir)) {
48
+ fs.mkdirSync(outputDir, { recursive: true });
49
+ }
50
+
51
+ // Create subdirectory for this profile+browser combination
52
+ const comboDir = path.join(outputDir, `${profileName}-${browser}`);
53
+ if (!fs.existsSync(comboDir)) {
54
+ fs.mkdirSync(comboDir, { recursive: true });
55
+ }
56
+
57
+ // Create per-combo screenshots directory
58
+ const comboScreenshotsDir = path.join(comboDir, 'screenshots');
59
+ if (!fs.existsSync(comboScreenshotsDir)) {
60
+ fs.mkdirSync(comboScreenshotsDir, { recursive: true });
61
+ }
62
+
63
+ const env = {
64
+ ...process.env,
65
+ CYPRESS_PROFILE: profileName,
66
+ BROWSER: browser,
67
+ };
68
+
69
+ console.log(`\n🚀 Starting Cypress headless: ${profileName} + ${browser}`);
70
+ console.log(`Output: ${comboDir}\n`);
71
+
72
+ // Create reporter config for cypress-multi-reporters
73
+ const reporterConfigPath = path.join(comboDir, 'reporter-config.json');
74
+ const reporterConfig = generateReporterConfig({
75
+ resultsDir: outputDir,
76
+ profileName,
77
+ browserName: browser,
78
+ });
79
+ fs.writeFileSync(reporterConfigPath, JSON.stringify(reporterConfig, null, 2));
80
+
81
+ // Cypress parallel run command with browser, threads, and reporter config
82
+ const cypressArgsString = `--headless --browser ${browser} --config screenshotsFolder=${comboScreenshotsDir} --reporter cypress-multi-reporters --reporter-options configFile=${reporterConfigPath}`;
83
+
84
+ console.log(`Reporter config path: ${reporterConfigPath}`);
85
+ console.log(`Granular results dir: ${path.join(comboDir, 'granular-results')}`);
86
+
87
+ const args = [
88
+ 'cypress-parallel',
89
+ '-s',
90
+ 'cy:run',
91
+ '--threads',
92
+ numThreads.toString(),
93
+ '-d',
94
+ 'cypress/e2e/**/*',
95
+ '-a',
96
+ // eslint-disable-next-line quotes
97
+ `'"${cypressArgsString}"'`,
98
+ ];
99
+
100
+ const cypressProcess = spawn('npx', args, {
101
+ cwd: root,
102
+ env,
103
+ stdio: 'inherit',
104
+ shell: true,
105
+ });
106
+
107
+ cypressProcess.on('close', (code) => {
108
+ const success = code === 0;
109
+
110
+ // Merge granular mochawesome JSON and generate a single HTML report
111
+ let reportGenerated = true;
112
+ try {
113
+ // Merge all json test suites (test files) into one report
114
+ mergeReports({
115
+ resultsDir: outputDir,
116
+ profileName,
117
+ browserName: browser,
118
+ });
119
+
120
+ // Generate combined HTML report for all test suites for this single browser+profile combo
121
+ generateHtmlReport({
122
+ resultsDir: outputDir,
123
+ profileName,
124
+ browserName: browser,
125
+ });
126
+ } catch (reportError) {
127
+ console.error(`\n⚠️ Report generation failed for ${profileName} + ${browser}:`, reportError);
128
+ reportGenerated = false;
129
+ }
130
+
131
+ // By default, marge names the HTML after the JSON basename: report-data.html
132
+ const reportPath = path.join(
133
+ outputDir,
134
+ `${profileName}-${browser}`,
135
+ 'report',
136
+ 'report-data.html',
137
+ );
138
+
139
+ const result: RunResult = {
140
+ profileName,
141
+ browser,
142
+ success: success && reportGenerated,
143
+ outputDir: comboDir,
144
+ reportPath: reportGenerated ? reportPath : undefined,
145
+ };
146
+
147
+ if (success && reportGenerated) {
148
+ console.log(`\n✅ Completed: ${profileName} + ${browser}`);
149
+ } else if (!reportGenerated) {
150
+ console.log(`\n⚠️ Tests ran but report generation failed: ${profileName} + ${browser}`);
151
+ } else {
152
+ console.log(`\n❌ Failed: ${profileName} + ${browser} (exit code: ${code})`);
153
+ }
154
+
155
+ resolve(result);
156
+ });
157
+
158
+ cypressProcess.on('error', (error) => {
159
+ reject(error);
160
+ });
161
+ });
162
+ };
163
+
164
+ export default runCypressHeadless;
@@ -0,0 +1,45 @@
1
+ /* eslint-disable no-console */
2
+ import { spawn } from 'child_process';
3
+
4
+ // Import helpers
5
+ import getRootPath from './getRootPath';
6
+
7
+ /**
8
+ * Run Cypress in visible/interactive mode with a profile
9
+ * @author Yuen Ler Chow
10
+ * @param profileName - The profile name to use
11
+ * @returns Promise that resolves when Cypress closes
12
+ */
13
+ const runCypressVisible = (profileName: string): Promise<void> => {
14
+ return new Promise((resolve, reject) => {
15
+ const root = getRootPath();
16
+ const env = {
17
+ ...process.env,
18
+ CYPRESS_PROFILE: profileName,
19
+ };
20
+
21
+ console.log(`\n🚀 Launching Cypress in interactive mode with profile: ${profileName}`);
22
+ console.log(` CYPRESS_PROFILE=${profileName}\n`);
23
+
24
+ const cypressProcess = spawn('npx', ['cypress', 'open'], {
25
+ cwd: root,
26
+ env,
27
+ stdio: 'inherit',
28
+ shell: true,
29
+ });
30
+
31
+ cypressProcess.on('close', (code) => {
32
+ if (code === 0) {
33
+ resolve();
34
+ } else {
35
+ reject(new Error(`Cypress exited with code ${code}`));
36
+ }
37
+ });
38
+
39
+ cypressProcess.on('error', (error) => {
40
+ reject(error);
41
+ });
42
+ });
43
+ };
44
+
45
+ export default runCypressVisible;
package/start/index.ts CHANGED
@@ -17,9 +17,11 @@ import findProfilesByNames from './helpers/findProfilesByNames';
17
17
  import validateBrowsers from './helpers/validateBrowsers';
18
18
  import extractArgValue from './helpers/extractArgValue';
19
19
  import getRootPath from './helpers/getRootPath';
20
+ import executeCypress from './helpers/executeCypress';
20
21
 
21
22
  // Import constants
22
23
  import AVAILABLE_BROWSERS from './constants/AVAILABLE_BROWSERS';
24
+ import DEFAULT_THREADS_PER_COMBO from './constants/DEFAULT_THREADS_PER_COMBO';
23
25
 
24
26
  // Get the project directory
25
27
  const pwd = getRootPath();
@@ -86,6 +88,20 @@ const headlessFlagValue = extractArgValue(args, '--headless');
86
88
  const hasHeadlessFlag = headlessFlagValue !== undefined;
87
89
  isHeadless = !!(envHeadlessRaw && envHeadlessRaw.toLowerCase() !== 'false') || hasHeadlessFlag;
88
90
 
91
+ // Check for THREADS_PER_COMBO (env var or CLI arg)
92
+ const envThreadsRaw = process.env.THREADS_PER_COMBO;
93
+ const argThreadsRaw = extractArgValue(args, '--threadsPerCombo');
94
+ const threadsRaw = envThreadsRaw || argThreadsRaw;
95
+ let threadsPerCombo: number | undefined;
96
+ if (threadsRaw) {
97
+ const parsed = Number.parseInt(threadsRaw, 10);
98
+ if (!Number.isNaN(parsed) && parsed > 0) {
99
+ threadsPerCombo = parsed;
100
+ } else {
101
+ console.warn(`⚠️ Invalid THREADS_PER_COMBO value: "${threadsRaw}". Using default (${DEFAULT_THREADS_PER_COMBO}).`);
102
+ }
103
+ }
104
+
89
105
  // If headless wasn't specified, ask the user to choose
90
106
  if (!envHeadlessRaw && !hasHeadlessFlag) {
91
107
  const choices = showChooser({
@@ -157,8 +173,10 @@ if (
157
173
  selectedProfiles = choices.map((choice) => { return profiles[choice.index]; });
158
174
  }
159
175
 
160
- // Execute commands for each combination of profile and browser (not yet implemented)
161
- console.log('Starting Cypress with the following configuration:');
162
- console.log(`Profiles: ${selectedProfiles.map((p) => { return p.profileName; }).join(', ')}`);
163
- console.log(`Browsers: ${selectedBrowsers.join(', ')}`);
164
- console.log(`Headless: ${isHeadless}`);
176
+ // Execute Cypress with selected configuration
177
+ executeCypress({
178
+ selectedProfiles,
179
+ selectedBrowsers,
180
+ isHeadless,
181
+ threadsPerCombo,
182
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Mochawesome reporter configuration
3
+ * @author Yuen Ler Chow
4
+ */
5
+ type MochawesomeReporterConfig = {
6
+ // The reporter(s) to enable (e.g., "mochawesome")
7
+ reporterEnabled: string;
8
+ // Options for the mochawesome reporter
9
+ mochawesomeReporterOptions: {
10
+ // Directory where report files will be saved
11
+ reportDir: string;
12
+ // Filename pattern for report files (supports [name] placeholder)
13
+ reportFilename: string;
14
+ // Whether to overwrite existing report files
15
+ overwrite: boolean;
16
+ // Whether to generate HTML reports
17
+ html: boolean;
18
+ // Whether to generate JSON reports
19
+ json: boolean;
20
+ };
21
+ };
22
+
23
+ export default MochawesomeReporterConfig;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Profile configuration
3
+ * @author Yuen Ler Chow
4
+ */
5
+ type Profile = {
6
+ // The filename of the profile (e.g., "prod.Profile.ts")
7
+ file: string;
8
+ // The name of the profile extracted from the filename (e.g., "prod")
9
+ profileName: string;
10
+ };
11
+
12
+ export default Profile;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Information about a generated report
3
+ * @author Yuen Ler Chow
4
+ */
5
+ type ReportInfo = {
6
+ // The name of the profile (e.g., "prod", "stage")
7
+ profileName: string;
8
+ // The browser used (e.g., "chrome", "edge")
9
+ browser: string;
10
+ // Path to the generated HTML report file
11
+ reportPath: string;
12
+ // True if the test run was successful
13
+ success: boolean;
14
+ // Human-readable timestamp of when the report was generated
15
+ timestamp: string;
16
+ // Total number of tests in the report
17
+ totalTests?: number;
18
+ // Number of tests that passed
19
+ passedTests?: number;
20
+ };
21
+
22
+ export default ReportInfo;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Result from a Cypress headless run
3
+ * @author Yuen Ler Chow
4
+ */
5
+ type RunResult = {
6
+ // The name of the profile used for this run (e.g., "prod", "stage")
7
+ profileName: string;
8
+ // The browser used for this run (e.g., "chrome", "edge")
9
+ browser: string;
10
+ // Whether the test run completed successfully (all tests passed and report generated)
11
+ success: boolean;
12
+ // The output directory for this specific profile+browser combination
13
+ outputDir: string;
14
+ // Path to the generated HTML report file, undefined if report generation failed
15
+ reportPath?: string;
16
+ };
17
+
18
+ export default RunResult;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Information about a screenshot captured during a Cypress test run,
3
+ * used for linking screenshots in the report homepage
4
+ * @author Yuen Ler Chow
5
+ */
6
+ type ScreenshotInfo = {
7
+ // Relative URL path to the screenshot file from the report homepage
8
+ href: string;
9
+ // Display name for the screenshot (typically the relative file path)
10
+ name: string;
11
+ };
12
+
13
+ export default ScreenshotInfo;
@@ -0,0 +1,16 @@
1
+ import ReportInfo from './ReportInfo';
2
+ import ScreenshotInfo from './ScreenshotInfo';
3
+
4
+ /**
5
+ * Extended version of ReportInfo with additional computed fields
6
+ * needed for rendering the EJS report homepage template
7
+ * @author Yuen Ler Chow
8
+ */
9
+ type TemplateReportInfo = ReportInfo & {
10
+ // Relative URL path to the HTML report file, or null if report doesn't exist
11
+ relativeReportPath: string | null;
12
+ // List of screenshots captured during this test run
13
+ screenshots: ScreenshotInfo[];
14
+ };
15
+
16
+ export default TemplateReportInfo;