ui5-test-runner 5.13.1 → 6.0.0-beta.2

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 (186) hide show
  1. package/README.md +3 -2
  2. package/dist/Npm.js +80 -0
  3. package/dist/browsers/IBrowser.js +1 -0
  4. package/dist/browsers/factory.js +9 -0
  5. package/dist/browsers/puppeteer.js +158 -0
  6. package/dist/cli.js +20 -0
  7. package/dist/configuration/CommandLine.js +112 -0
  8. package/dist/configuration/Configuration.js +1 -0
  9. package/dist/configuration/ConfigurationValidator.js +79 -0
  10. package/dist/configuration/Option.js +1 -0
  11. package/dist/configuration/OptionValidationError.js +15 -0
  12. package/dist/configuration/indexedOptions.js +13 -0
  13. package/dist/configuration/options.js +191 -0
  14. package/dist/configuration/validators/OptionValidator.js +1 -0
  15. package/dist/configuration/validators/boolean.js +15 -0
  16. package/dist/configuration/validators/browser.js +11 -0
  17. package/dist/configuration/validators/fsEntry.js +70 -0
  18. package/dist/configuration/validators/index.js +20 -0
  19. package/dist/configuration/validators/integer.js +10 -0
  20. package/dist/configuration/validators/percent.js +17 -0
  21. package/dist/configuration/validators/regexp.js +20 -0
  22. package/dist/configuration/validators/string.js +7 -0
  23. package/dist/configuration/validators/timeout.js +24 -0
  24. package/dist/configuration/validators/url.js +8 -0
  25. package/dist/modes/ModeFunction.js +1 -0
  26. package/dist/modes/Modes.js +9 -0
  27. package/dist/modes/execute.js +27 -0
  28. package/dist/modes/help.js +3 -0
  29. package/dist/modes/log/ILogStorage.js +1 -0
  30. package/dist/modes/log/LogMetrics.js +9 -0
  31. package/dist/modes/log/LogReader.js +37 -0
  32. package/dist/modes/log/LogStorage.js +68 -0
  33. package/dist/modes/log/REserve.js +101 -0
  34. package/dist/modes/log/index.js +58 -0
  35. package/dist/modes/test/REserve.js +31 -0
  36. package/dist/modes/test/agent.js +8 -0
  37. package/dist/modes/test/browser.js +37 -0
  38. package/dist/modes/test/index.js +66 -0
  39. package/dist/modes/test/pageTask.js +145 -0
  40. package/dist/modes/test/report.js +3 -0
  41. package/dist/modes/test/server.js +109 -0
  42. package/dist/modes/version.js +11 -0
  43. package/dist/platform/Exit.js +139 -0
  44. package/dist/platform/FileSystem.js +13 -0
  45. package/dist/platform/Host.js +10 -0
  46. package/dist/platform/Http.js +38 -0
  47. package/dist/platform/Path.js +5 -0
  48. package/dist/platform/Process.js +133 -0
  49. package/dist/platform/Terminal.js +47 -0
  50. package/dist/platform/Thread.js +43 -0
  51. package/dist/platform/ZLib.js +7 -0
  52. package/dist/platform/assert.js +17 -0
  53. package/dist/platform/constants.js +5 -0
  54. package/dist/platform/environment.js +28 -0
  55. package/dist/platform/index.js +13 -0
  56. package/dist/platform/logger/ILogger.js +1 -0
  57. package/dist/platform/logger/allCompressed.js +54 -0
  58. package/dist/platform/logger/compress.js +277 -0
  59. package/dist/platform/logger/output/BaseLoggerOutput.js +158 -0
  60. package/dist/platform/logger/output/InteractiveLoggerOutput.js +102 -0
  61. package/dist/platform/logger/output/StaticLoggerOutput.js +32 -0
  62. package/dist/platform/logger/output/factory.js +10 -0
  63. package/dist/platform/logger/output.js +58 -0
  64. package/dist/platform/logger/proxy.js +6 -0
  65. package/dist/platform/logger/toInternalLogAttributes.js +22 -0
  66. package/dist/platform/logger/types.js +7 -0
  67. package/dist/platform/logger.js +138 -0
  68. package/dist/platform/mock.js +104 -0
  69. package/dist/platform/version.js +8 -0
  70. package/dist/platform/workerBootstrap.js +21 -0
  71. package/dist/reports/html.js +46 -0
  72. package/dist/types/AgentState.js +1 -0
  73. package/dist/types/CommonTestReportFormat.js +50 -0
  74. package/dist/types/IError.js +1 -0
  75. package/dist/types/IUserInterfaceController.js +1 -0
  76. package/dist/types/typeUtilities.js +1 -0
  77. package/dist/ui/agent.js +3 -0
  78. package/dist/ui/html-report.js +2 -0
  79. package/dist/ui/lib.js +1 -0
  80. package/dist/ui/log-viewer.js +2 -0
  81. package/dist/utils/node/Folder.js +28 -0
  82. package/dist/utils/node/FramedStreamReader.js +86 -0
  83. package/dist/utils/node/FramedStreamWriter.js +27 -0
  84. package/dist/utils/shared/ProgressBar.js +43 -0
  85. package/dist/utils/shared/TestReportBuilder.js +48 -0
  86. package/dist/utils/shared/memoize.js +19 -0
  87. package/dist/utils/shared/object.js +8 -0
  88. package/dist/utils/shared/parallelize.js +59 -0
  89. package/dist/utils/shared/string.js +23 -0
  90. package/dist/utils/shared/toIError.js +17 -0
  91. package/package.json +73 -50
  92. package/.releaserc +0 -5
  93. package/index.js +0 -175
  94. package/jest.config.json +0 -31
  95. package/src/add-test-pages.js +0 -67
  96. package/src/batch.js +0 -214
  97. package/src/browsers.js +0 -319
  98. package/src/capabilities/index.js +0 -204
  99. package/src/capabilities/tests/basic/iframe.html +0 -8
  100. package/src/capabilities/tests/basic/index.html +0 -12
  101. package/src/capabilities/tests/basic/index.js +0 -20
  102. package/src/capabilities/tests/basic/ui5.html +0 -24
  103. package/src/capabilities/tests/dynamic-include/index.js +0 -21
  104. package/src/capabilities/tests/dynamic-include/mix.html +0 -11
  105. package/src/capabilities/tests/dynamic-include/one.html +0 -11
  106. package/src/capabilities/tests/dynamic-include/post.js +0 -3
  107. package/src/capabilities/tests/dynamic-include/test.js +0 -1
  108. package/src/capabilities/tests/dynamic-include/two.html +0 -11
  109. package/src/capabilities/tests/index.js +0 -16
  110. package/src/capabilities/tests/local-storage/index.html +0 -16
  111. package/src/capabilities/tests/local-storage/index.js +0 -21
  112. package/src/capabilities/tests/screenshot/index.html +0 -23
  113. package/src/capabilities/tests/screenshot/index.js +0 -24
  114. package/src/capabilities/tests/scripts/coverage.html +0 -32
  115. package/src/capabilities/tests/scripts/iframe.html +0 -18
  116. package/src/capabilities/tests/scripts/index.js +0 -59
  117. package/src/capabilities/tests/scripts/qunit.html +0 -22
  118. package/src/capabilities/tests/scripts/testsuite.html +0 -10
  119. package/src/capabilities/tests/scripts/testsuite.js +0 -8
  120. package/src/capabilities/tests/timeout/index.html +0 -21
  121. package/src/capabilities/tests/timeout/index.js +0 -19
  122. package/src/capabilities/tests/traces/index.html +0 -18
  123. package/src/capabilities/tests/traces/index.js +0 -81
  124. package/src/capabilities/tests/ui5/focus.html +0 -89
  125. package/src/capabilities/tests/ui5/index.js +0 -39
  126. package/src/capabilities/tests/ui5/language.html +0 -50
  127. package/src/capabilities/tests/ui5/timezone.html +0 -27
  128. package/src/clean.js +0 -22
  129. package/src/cors.js +0 -21
  130. package/src/coverage.js +0 -384
  131. package/src/csv-reader.js +0 -36
  132. package/src/csv-writer.js +0 -55
  133. package/src/defaults/.nycrc.json +0 -4
  134. package/src/defaults/browser.js +0 -217
  135. package/src/defaults/happy-dom.js +0 -123
  136. package/src/defaults/jsdom/compatibility.js +0 -163
  137. package/src/defaults/jsdom/debug.js +0 -23
  138. package/src/defaults/jsdom/resource-loader.js +0 -44
  139. package/src/defaults/jsdom/sap.ui.test.matchers.visible.js +0 -39
  140. package/src/defaults/jsdom.js +0 -95
  141. package/src/defaults/json-report.js +0 -36
  142. package/src/defaults/junit-xml-report.js +0 -90
  143. package/src/defaults/playwright.js +0 -142
  144. package/src/defaults/puppeteer.js +0 -124
  145. package/src/defaults/report/common.js +0 -38
  146. package/src/defaults/report/decompress.js +0 -19
  147. package/src/defaults/report/default.html +0 -99
  148. package/src/defaults/report/main.js +0 -69
  149. package/src/defaults/report/progress.js +0 -60
  150. package/src/defaults/report/styles.css +0 -66
  151. package/src/defaults/report.js +0 -91
  152. package/src/defaults/scan-ui5.js +0 -26
  153. package/src/defaults/selenium-webdriver/chrome.js +0 -39
  154. package/src/defaults/selenium-webdriver/edge.js +0 -24
  155. package/src/defaults/selenium-webdriver/firefox.js +0 -30
  156. package/src/defaults/selenium-webdriver.js +0 -129
  157. package/src/defaults/text-report.js +0 -108
  158. package/src/defaults/webdriverio.js +0 -80
  159. package/src/end.js +0 -62
  160. package/src/endpoints.js +0 -219
  161. package/src/error.js +0 -54
  162. package/src/get-job-progress.js +0 -78
  163. package/src/handle.js +0 -43
  164. package/src/if.js +0 -10
  165. package/src/inject/jest2qunit.js +0 -289
  166. package/src/inject/opa-iframe-coverage.js +0 -22
  167. package/src/inject/post.js +0 -141
  168. package/src/inject/qunit-hooks.js +0 -107
  169. package/src/inject/qunit-redirect.js +0 -65
  170. package/src/inject/ui5-coverage.js +0 -33
  171. package/src/job-mode.js +0 -65
  172. package/src/job.js +0 -493
  173. package/src/npm.js +0 -136
  174. package/src/options.js +0 -95
  175. package/src/output.js +0 -739
  176. package/src/parallelize.js +0 -63
  177. package/src/qunit-hooks.js +0 -219
  178. package/src/report.js +0 -89
  179. package/src/reserve.js +0 -25
  180. package/src/start.js +0 -133
  181. package/src/symbols.js +0 -8
  182. package/src/tests.js +0 -183
  183. package/src/timeout.js +0 -53
  184. package/src/tools.js +0 -179
  185. package/src/ui5.js +0 -199
  186. package/src/unhandled.js +0 -32
package/src/output.js DELETED
@@ -1,739 +0,0 @@
1
- 'use strict'
2
-
3
- const { readFileSync, writeFileSync } = require('fs')
4
- const { join } = require('path')
5
- const { memoryUsage } = require('process')
6
- const {
7
- $browsers,
8
- $statusProgressCount,
9
- $statusProgressTotal
10
- } = require('./symbols')
11
- const { filename, noop, pad } = require('./tools')
12
- const os = require('os')
13
- const { describeHandle } = require('./handle')
14
-
15
- const $output = Symbol('output')
16
- const $outputStart = Symbol('output-start')
17
- const $outputProgress = Symbol('output-progress')
18
- const $logServerIncomingCount = Symbol('log-server-incoming')
19
- const $logServerRedirectedCount = Symbol('log-server-redirected')
20
- const $logServerClosedCount = Symbol('log-server-closed')
21
- const $logServerRequests = Symbol('log-server-requests')
22
- const $interactive = Symbol('interactive')
23
-
24
- let cons = console
25
-
26
- const formatTime = duration => {
27
- duration = Math.ceil(duration / 1000)
28
- const seconds = duration % 60
29
- const minutes = (duration - seconds) / 60
30
- return minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0')
31
- }
32
-
33
- const getElapsed = job => formatTime(Date.now() - job[$outputStart])
34
-
35
- function * buildCleanSequence (job) {
36
- const { lines } = job[$output]
37
- if (!lines) {
38
- return
39
- }
40
- yield '\x1b[?12l'
41
- yield `\x1b[${lines.toString()}F`
42
- for (let line = 0; line < lines; ++line) {
43
- if (line > 1) {
44
- yield '\x1b[1E'
45
- }
46
- yield ''.padEnd(process.stdout.columns, ' ')
47
- }
48
- if (lines > 1) {
49
- yield `\x1b[${(lines - 1).toString()}F`
50
- } else {
51
- yield '\x1b[1G'
52
- }
53
- }
54
-
55
- function clean (job) {
56
- process.stdout.write([...buildCleanSequence(job)].join(''))
57
- }
58
-
59
- const BAR_WIDTH = 10
60
-
61
- function * bar (ratio, msg) {
62
- yield '['
63
- if (typeof ratio === 'string') {
64
- if (ratio.length > BAR_WIDTH) {
65
- yield ratio.substring(0, BAR_WIDTH - 3)
66
- yield '...'
67
- } else {
68
- const padded = ratio.padStart(BAR_WIDTH - Math.floor((BAR_WIDTH - ratio.length) / 2), '-').padEnd(BAR_WIDTH, '-')
69
- yield padded
70
- }
71
- yield '] '
72
- } else {
73
- const filled = Math.floor(BAR_WIDTH * Math.min(ratio, 1))
74
- yield ''.padEnd(filled, '\u2588')
75
- yield ''.padEnd(BAR_WIDTH - filled, '\u2591')
76
- yield '] '
77
- yield Math.floor(100 * ratio).toString().padStart(3, ' ').toString()
78
- yield '%'
79
- }
80
- yield ' '
81
- const spaceLeft = process.stdout.columns - BAR_WIDTH - 14
82
- if (msg.length > spaceLeft) {
83
- yield '...'
84
- yield msg.substring(msg.length - spaceLeft - 3)
85
- } else {
86
- yield msg
87
- }
88
- yield '\n'
89
- }
90
-
91
- const TICKS = ['\u280b', '\u2819', '\u2839', '\u2838', '\u283c', '\u2834', '\u2826', '\u2827', '\u2807', '\u280f']
92
-
93
- class Progress {
94
- #job = undefined
95
-
96
- constructor (job) {
97
- this.#job = job
98
- if (!job[$outputProgress]) {
99
- job[$outputProgress] = []
100
- }
101
- job[$outputProgress].push(this)
102
- }
103
-
104
- done () {
105
- const pos = this.#job[$outputProgress].indexOf(this)
106
- this.#job[$outputProgress].splice(pos, 1)
107
- }
108
- }
109
-
110
- function progress (job, cleanFirst = true) {
111
- if (process.send) {
112
- process.send({
113
- type: 'progress',
114
- count: job[$statusProgressCount],
115
- total: job[$statusProgressTotal]
116
- })
117
- }
118
- const sequence = []
119
- if (job[$interactive]) {
120
- if (cleanFirst) {
121
- sequence.push(...buildCleanSequence(job))
122
- }
123
- } else {
124
- if (job[$browsers]) {
125
- sequence.push(`${getElapsed(job)} │ Progress\n──────┴──────────\n`)
126
- } else {
127
- return
128
- }
129
- }
130
- const output = job[$output]
131
- output.lines = 1
132
- let progressRatio
133
- if (job.debugMemory) {
134
- ++output.lines
135
- const { rss, heapTotal, heapUsed, external, arrayBuffers } = memoryUsage()
136
- const fmt = size => `${(size / (1024 * 1024)).toFixed(2)}M`
137
- sequence.push(`MEM r:${fmt(rss)}, h:${fmt(heapUsed)}/${fmt(heapTotal)}, x:${fmt(external)}, a:${fmt(arrayBuffers)}\n`)
138
- }
139
- if (job.debugHandles) {
140
- ++output.lines
141
- const activeHandles = process._getActiveHandles ? process._getActiveHandles() : []
142
- sequence.push(`HANDLES ${activeHandles.length}\n`)
143
- for (let index = 0; index < activeHandles.length; ++index) {
144
- const handle = activeHandles[index]
145
- const bullet = index === activeHandles.length - 1 ? '└' : '├'
146
- ++output.lines
147
- const handleDescription = describeHandle(handle).label
148
- if (handleDescription.length > process.stdout.columns - 4) {
149
- sequence.push(`${bullet}─ ${handleDescription.slice(0, process.stdout.columns - 4)}\n`)
150
- } else {
151
- sequence.push(`${bullet}─ ${handleDescription}\n`)
152
- }
153
- }
154
- }
155
- if (job[$outputProgress]) {
156
- output.lines += job[$outputProgress].length
157
- job[$outputProgress].forEach(({ count, total, label }) => {
158
- if (total !== undefined) {
159
- sequence.push(...bar((count || 0) / (total || 1), label))
160
- } else {
161
- sequence.push(...bar('starting', label))
162
- }
163
- })
164
- }
165
- if (job[$statusProgressTotal]) {
166
- progressRatio = (job[$statusProgressCount] || 0) / job[$statusProgressTotal]
167
- }
168
- const status = `${TICKS[++output.lastTick % TICKS.length]} ${job.status}`
169
- if (progressRatio !== undefined) {
170
- sequence.push(...bar(progressRatio, status))
171
- } else {
172
- sequence.push(status, '\n')
173
- }
174
- process.stdout.write(sequence.join(''))
175
- }
176
-
177
- function output (job, ...args) {
178
- writeFileSync(
179
- join(job.reportDir, 'output.txt'),
180
- args.map(arg => {
181
- if (arg === undefined) {
182
- return 'undefined'
183
- }
184
- if (arg === null) {
185
- return 'null'
186
- }
187
- if (arg instanceof Error) {
188
- let error = `${arg.name} ${arg.message}`
189
- if (arg.cause) {
190
- error += `, cause : ${arg.cause.name} ${arg.cause.message}`
191
- }
192
- return error
193
- }
194
- if (typeof arg !== 'string') {
195
- return JSON.stringify(arg, undefined, 2)
196
- }
197
- return arg
198
- }).join(' ') + '\n',
199
- {
200
- encoding: 'utf-8',
201
- flag: 'a'
202
- }
203
- )
204
- }
205
-
206
- function log (job, ...texts) {
207
- cons.log(...texts)
208
- output(job, ...texts)
209
- }
210
-
211
- function warn (job, ...texts) {
212
- cons.warn(...texts)
213
- output(job, ...texts)
214
- }
215
-
216
- function err (job, ...texts) {
217
- cons.error(...texts)
218
- output(job, ...texts)
219
- }
220
-
221
- const p80 = () => pad(process.stdout.columns || 80)
222
-
223
- function browserIssue (job, { type, url, code, dir }) {
224
- const p = p80()
225
- log(job, p`┌──────────${pad.x('─')}┐`)
226
- log(job, p`│ BROWSER ${type.toUpperCase()} ${pad.x(' ')} │`)
227
- log(job, p`├──────┬─${pad.x('─')}──┤`)
228
- log(job, p`│ url │ ${pad.lt(url)} │`)
229
- log(job, p`├──────┼─${pad.x('─')}──┤`)
230
- const unsignedCode = new Uint32Array([code])[0]
231
- log(job, p`│ code │ 0x${unsignedCode.toString(16).toUpperCase()}${pad.x(' ')} │`)
232
- log(job, p`├──────┼─${pad.x('─')}──┤`)
233
- log(job, p`│ dir │ ${pad.lt(dir)} │`)
234
- log(job, p`├──────┴─${pad.x('─')}──┤`)
235
-
236
- const stderr = readFileSync(join(dir, 'stderr.txt')).toString().trim()
237
- if (stderr.length !== 0) {
238
- log(job, p`│ Error output (${stderr.length}) ${pad.x(' ')} │`)
239
- log(job, p`│ ${pad.w(stderr)} │`)
240
- } else {
241
- const stdout = readFileSync(join(dir, 'stdout.txt')).toString()
242
- if (stdout.length !== 0) {
243
- log(job, p`│ Standard output (${stderr.length}), last 10 lines... ${pad.x(' ')} │`)
244
- log(job, p`│ ${pad.w('...')} │`)
245
- log(job, p`│ ${pad.w(stdout.split(/\r?\n/).slice(-10).join('\n'))} │`)
246
- } else {
247
- log(job, p`│ No output ${pad.x(' ')} │`)
248
- }
249
- }
250
- log(job, p`└──────────${pad.x('─')}┘`)
251
- }
252
-
253
- function build (job) {
254
- let interactive = !job.ci
255
- const inJest = typeof jest !== 'undefined'
256
- if (inJest) {
257
- cons = { log: noop, warn: noop, error: noop }
258
- interactive = false
259
- } else if (process.stdout.columns === undefined || !process.stdout.isTTY) {
260
- interactive = false
261
- }
262
- if (!interactive) {
263
- const UTF8_BOM_CODE = '\ufeff'
264
- process.stdout.write(UTF8_BOM_CODE)
265
- }
266
- let wrap
267
- if (interactive) {
268
- job[$interactive] = true
269
- wrap = method => function () {
270
- let result
271
- clean(job)
272
- try {
273
- result = method.call(this, ...arguments)
274
- } finally {
275
- progress(job, false)
276
- }
277
- return result
278
- }
279
- } else {
280
- wrap = method => method
281
- }
282
- job[$outputStart] = Date.now()
283
-
284
- return {
285
- lastTick: 0,
286
- reportIntervalId: undefined,
287
- lines: 0,
288
-
289
- version: wrap(() => {
290
- const { name, version = 'dev' } = require(join(__dirname, '../package.json'))
291
- log(job, p80()` _ ____ _ _
292
- _ _(_) ___| | |_ ___ ___| |_ _ __ _ _ _ __ _ __ ___ _ __
293
- | | | | |___ \\ _____| __/ _ \\/ __| __|____| '__| | | | '_ \\| '_ \\ / _ \\ '__|
294
- | |_| | |___) |_____| || __/\\__ \\ ||_____| | | |_| | | | | | | | __/ |
295
- \\__,_|_|____/ \\__\\___||___/\\__| |_| \\__,_|_| |_|_| |_|\\___|_| `)
296
- const now = new Date()
297
- log(job, p80()`${name}@${version} / Node.js ${process.version} / ${now.toISOString()} (${now.getTimezoneOffset()})`)
298
- const cpus = {}
299
- for (const { model } of os.cpus()) {
300
- if (cpus[model]) {
301
- ++cpus[model]
302
- } else {
303
- cpus[model] = 1
304
- }
305
- }
306
- for (const [model, count] of Object.entries(cpus)) {
307
- log(job, p80()`${os.machine()} / ${count}x ${model}`)
308
- }
309
- if (job.debugDevMode) {
310
- log(job, p80()`⚠️ Development mode ⚠️`)
311
- }
312
- return { name, version }
313
- }),
314
-
315
- serving: wrap((url) => {
316
- log(job, p80()`Server running at ${pad.lt(url)}`)
317
- }),
318
-
319
- log: wrap((...texts) => {
320
- log(job, ...texts)
321
- }),
322
-
323
- error: wrap((...texts) => {
324
- err(job, ...texts)
325
- }),
326
-
327
- debug: (moduleSpecifier, ...args) => {
328
- const [mainModule] = moduleSpecifier.split('/')
329
- if (job.debugVerbose && (job.debugVerbose.includes('*') || job.debugVerbose.includes(moduleSpecifier) || job.debugVerbose.includes(mainModule))) {
330
- wrap(() => {
331
- console.log(`🐞${moduleSpecifier}`, ...args)
332
- output(job, `🐞${moduleSpecifier}`, ...args)
333
- })()
334
- }
335
- },
336
-
337
- logServerIncoming: wrap(({ id, method, url }) => {
338
- if (url.startsWith('/_/')) {
339
- return // avoids pollution
340
- }
341
- job[$logServerIncomingCount] = (job[$logServerIncomingCount] || 0) + 1
342
- job[$logServerRequests] ??= {}
343
- job[$logServerRequests][id] = { method, url }
344
- log(job, p80()`🛜 INC ${id.toString(36).toUpperCase().padStart(4, ' ')} ${method.padEnd(7, ' ')} ${pad.lt(url)}`)
345
- }),
346
-
347
- logServerRedirected: wrap(({ id, method, url, statusCode, timeSpent }) => {
348
- if (url.startsWith('/_/')) {
349
- return // avoids pollution
350
- }
351
- let statusText
352
- if (!statusCode) {
353
- statusText = 'N/A'
354
- } else {
355
- statusText = statusCode
356
- }
357
- job[$logServerRedirectedCount] = (job[$logServerRedirectedCount] || 0) + 1
358
- const request = job[$logServerRequests][id]
359
- request.redirected = true
360
- if (request.closed) {
361
- delete job[$logServerRequests][id]
362
- }
363
- log(job, p80()`🛜 SRV ${id.toString(36).toUpperCase().padStart(4, ' ')} ${method.padEnd(7, ' ')} ${pad.lt(url)} ${statusText} ${timeSpent.toString().padStart(4, ' ')}ms`)
364
- }),
365
-
366
- logServerClosed: wrap(({ id, method, url }) => {
367
- if (url.startsWith('/_/')) {
368
- return // avoids pollution
369
- }
370
- job[$logServerClosedCount] = (job[$logServerClosedCount] || 0) + 1
371
- const request = job[$logServerRequests][id]
372
- request.closed = true
373
- if (request.redirected) {
374
- delete job[$logServerRequests][id]
375
- }
376
- log(job, p80()`🛜 CLS ${id.toString(36).toUpperCase().padStart(4, ' ')} ${method.padEnd(7, ' ')} ${pad.lt(url)}`)
377
- }),
378
-
379
- logServerSummary: wrap(() => {
380
- log(job, p80()`🛜 requests: ${job[$logServerIncomingCount] || 0} incoming, ${job[$logServerRedirectedCount] || 0} redirected, ${job[$logServerClosedCount] || 0} closed.`)
381
- if (job[$logServerRequests] && Object.keys(job[$logServerRequests]).length) {
382
- log(job, job[$logServerRequests])
383
- }
384
- }),
385
-
386
- status (status) {
387
- let method
388
- if (interactive) {
389
- method = output
390
- } else {
391
- method = log
392
- }
393
- const text = `${getElapsed(job)} │ ${status}`
394
- method(job, '')
395
- method(job, text)
396
- method(job, '──────┴'.padEnd(text.length, '─'))
397
- delete job[$statusProgressCount]
398
- delete job[$statusProgressTotal]
399
- },
400
-
401
- watching: wrap(path => {
402
- log(job, p80()`Watching changes on ${pad.lt(path)}`)
403
- }),
404
-
405
- changeDetected: wrap((eventType, filename) => {
406
- log(job, p80()`${eventType} ${pad.lt(filename)}`)
407
- }),
408
-
409
- reportOnJobProgress () {
410
- if (this.reportIntervalId) {
411
- return
412
- }
413
- if (interactive) {
414
- this.reportIntervalId = setInterval(progress.bind(null, job), 250)
415
- } else if (job.outputInterval && !inJest) {
416
- this.reportIntervalId = setInterval(progress.bind(null, job), job.outputInterval)
417
- }
418
- },
419
-
420
- browserCapabilities: wrap(capabilities => {
421
- log(job, p80()`Browser capabilities :`)
422
- const { modules } = capabilities
423
- if (modules.length) {
424
- log(job, p80()` ├─ modules`)
425
- modules.forEach((module, index) => {
426
- let prefix
427
- if (index === modules.length - 1) {
428
- prefix = ' │ └─ '
429
- } else {
430
- prefix = ' │ ├─'
431
- }
432
- log(job, p80()`${prefix} ${pad.lt(module)}`)
433
- })
434
- }
435
- Object.keys(capabilities)
436
- .filter(key => key !== 'modules')
437
- .forEach((key, index, keys) => {
438
- let prefix
439
- if (index === keys.length - 1) {
440
- prefix = ' └─'
441
- } else {
442
- prefix = ' ├─'
443
- }
444
- let value = JSON.stringify(capabilities[key])
445
- if (key === 'scripts' && !capabilities[key] && job.debugCapabilitiesNoScript) {
446
- value += ' ⚠️ --debug-capabilities-no-script'
447
- }
448
- log(job, p80()`${prefix} ${key}: ${value}`)
449
- })
450
- }),
451
-
452
- resolvedPackage (name, path, version) {
453
- if (!name.match(/@\d+\.\d+\.\d+$/)) {
454
- name += `@${version}`
455
- }
456
- wrap(() => log(job, p80()`${name} in ${pad.lt(path)}`))()
457
- },
458
-
459
- packageNotLatest (name, latestVersion) {
460
- wrap(() => log(job, `⚠️ [PKGVRS] Latest version of ${name} is ${latestVersion}`))()
461
- },
462
-
463
- emptyBrowserArg () {
464
- wrap(() => log(job, '⚠️ [EBWARG] Empty browser argument filtered out'))()
465
- },
466
-
467
- detectedLeakOfHandles () {
468
- wrap(() => log(job, '⚠️ [HDLEAK] Leaking Node.js handle(s) detected. This may cause issues with the shutdown'))()
469
- },
470
-
471
- failedToTerminateStartCommand () {
472
- wrap(() => log(job, '⚠️ [STRTCT] Failed to query and terminate all start command child processes, some may leak'))()
473
- },
474
-
475
- browserStart (url) {
476
- const text = p80()`${getElapsed(job)} >> ${pad.lt(url)} [${filename(url)}]`
477
- if (interactive) {
478
- output(job, text)
479
- } else {
480
- wrap(() => log(job, text))()
481
- }
482
- },
483
-
484
- browserStopped (url) {
485
- let duration = ''
486
- const page = job.qunitPages && job.qunitPages[url]
487
- if (page) {
488
- duration = ' (' + formatTime(page.end - page.start) + ')'
489
- }
490
- const text = p80()`${getElapsed(job)} << ${pad.lt(url)} ${duration} [${filename(url)}]`
491
- if (interactive) {
492
- output(job, text)
493
- } else {
494
- wrap(() => log(job, text))()
495
- }
496
- },
497
-
498
- browserClosed: wrap((url, code, dir) => {
499
- browserIssue(job, { type: 'unexpected closed', url, code, dir })
500
- }),
501
-
502
- browserRetry (url, retry) {
503
- if (interactive) {
504
- output(job, '>>', url)
505
- } else {
506
- wrap(() => log(job, p80()`>> RETRY ${retry} ${pad.lt(url)}`))()
507
- }
508
- },
509
-
510
- browserTimeout: wrap((url, dir) => {
511
- browserIssue(job, { type: 'timeout', url, code: 0, dir })
512
- }),
513
-
514
- browserFailed: wrap((url, code, dir) => {
515
- browserIssue(job, { type: 'failed', url, code, dir })
516
- }),
517
-
518
- browserChildProcessError: wrap((url, { code }) => {
519
- log(job, p80()`⚠️ [BRWCPE] Child process error ${code}: ${pad.lt(url)}`)
520
- }),
521
-
522
- skipIf: wrap(() => {
523
- log(job, p80()`⚠️ [SKIPIF] Skipping execution (--if)`)
524
- }),
525
-
526
- batchStartingTask: wrap((label) => {
527
- if (!interactive) {
528
- log(job, p80()`${label}...`)
529
- }
530
- }),
531
-
532
- batchFailed: wrap((batch, reason) => {
533
- log(job, p80()`⚠️ [BATCHF] Failed to resolve batch ${batch}: ${reason}`)
534
- }),
535
-
536
- batchMode: wrap((batch, reason) => {
537
- log(job, p80()`⚠️ [BATCHM] Batch mode item execution`)
538
- }),
539
-
540
- startFailed: wrap((url, error) => {
541
- const p = p80()
542
- log(job, p`┌──────────${pad.x('─')}┐`)
543
- log(job, p`│ UNABLE TO START THE URL ${pad.x(' ')} │`)
544
- log(job, p`├──────┬─${pad.x('─')}──┤`)
545
- log(job, p`│ url │ ${pad.lt(url)} │`)
546
- log(job, p`├──────┴─${pad.x('─')}──┤`)
547
- if (error.stack) {
548
- log(job, p`│ ${pad.w(error.stack)} │`)
549
- } else {
550
- log(job, p`│ ${pad.w(error.toString())} │`)
551
- }
552
- log(job, p`└──────────${pad.x('─')}┘`)
553
- }),
554
-
555
- monitor (childProcess, live = true) {
556
- const defaults = {
557
- stdout: { buffer: [], method: log },
558
- stderr: { buffer: [], method: err }
559
- };
560
- ['stdout', 'stderr'].forEach(channel => {
561
- childProcess[channel].on('data', chunk => {
562
- const { buffer, method } = defaults[channel]
563
- const text = chunk.toString()
564
- if (live) {
565
- if (!text.includes('\n')) {
566
- buffer.push(text)
567
- return
568
- }
569
- const cached = buffer.join('')
570
- const last = text.split('\n').slice(-1)
571
- buffer.length = 0
572
- if (last) {
573
- buffer.push(last)
574
- }
575
- wrap(() => method(job, cached + text.split('\n').slice(0, -1).join('\n')))()
576
- } else {
577
- buffer.push(text)
578
- }
579
- })
580
- })
581
- if (live) {
582
- childProcess.on('close', () => {
583
- ['stdout', 'stderr'].forEach(channel => {
584
- const { buffer, method } = defaults[channel]
585
- if (buffer.length) {
586
- method(job, buffer.join(''))
587
- }
588
- })
589
- })
590
- }
591
- return {
592
- stdout: defaults.stdout.buffer,
593
- stderr: defaults.stderr.buffer
594
- }
595
- },
596
-
597
- nyc: wrap((...args) => {
598
- log(job, p80()`nyc ${args.map(arg => arg.toString()).join(' ')}`)
599
- }),
600
-
601
- instrumentationSkipped: wrap(() => {
602
- log(job, p80()`⚠️ [SKPNYC] Skipping nyc instrumentation (--url)`)
603
- }),
604
-
605
- coverageNotFound: wrap(() => {
606
- log(job, p80()`⚠️ [COVMIS] Coverage missing`)
607
- }),
608
-
609
- assumingOneOrigin: wrap(() => {
610
- log(job, p80()`⚠️ [COVORG] Considering only one origin`)
611
- }),
612
-
613
- noInfoForAllCoverage: wrap(() => {
614
- log(job, p80()`⚠️ [COVALL] Unable to process all coverage, report might be incomplete`)
615
- }),
616
-
617
- endpointError: wrap(({ api, url, data, error }) => {
618
- const p = p80()
619
- log(job, p`┌──────────${pad.x('─')}┐`)
620
- log(job, p`│ UNEXPECTED ENDPOINT ERROR ${pad.x(' ')} │`)
621
- log(job, p`├──────┬─${pad.x('─')}──┤`)
622
- log(job, p`│ api │ ${pad.lt(api)} │`)
623
- log(job, p`├──────┼─${pad.x('─')}──┤`)
624
- log(job, p`│ from │ ${pad.lt(url)} │`)
625
- log(job, p`├──────┴─${pad.x('─')}──┤`)
626
- log(job, p`│ data (${JSON.stringify(data).length}) ${pad.x(' ')} │`)
627
- log(job, p`│ ${pad.w(JSON.stringify(data, undefined, 2))} │`)
628
- log(job, p`├────────${pad.x('─')}──┤`)
629
- if (error.stack) {
630
- log(job, p`│ ${pad.w(error.stack)} │`)
631
- } else {
632
- log(job, p`│ ${pad.w(error.toString())} │`)
633
- }
634
- log(job, p`└──────────${pad.x('─')}┘`)
635
- }),
636
-
637
- serverError: wrap(({ method, url, reason }) => {
638
- const p = p80()
639
- log(job, p`┌──────────${pad.x('─')}┐`)
640
- log(job, p`│ UNEXPECTED SERVER ERROR ${pad.x(' ')} │`)
641
- log(job, p`├──────┬─${pad.x('─')}──┤`)
642
- log(job, p`│ verb │ ${pad.lt(method)} │`)
643
- log(job, p`├──────┼─${pad.x('─')}──┤`)
644
- log(job, p`│ url │ ${pad.lt(url)} │`)
645
- log(job, p`├──────┴─${pad.x('─')}──┤`)
646
- if (reason.stack) {
647
- log(job, p`│ ${pad.w(reason.stack)} │`)
648
- } else {
649
- log(job, p`│ ${pad.w(reason.toString())} │`)
650
- }
651
- log(job, p`└──────────${pad.x('─')}┘`)
652
- }),
653
-
654
- globalTimeout: wrap(url => {
655
- log(job, p80()`!! TIMEOUT ${pad.lt(url)}`)
656
- }),
657
-
658
- failFast: wrap(url => {
659
- log(job, p80()`!! FAILFAST ${pad.lt(url)}`)
660
- }),
661
-
662
- noTestPageFound: wrap(() => {
663
- err(job, p80()`No test page found (or all filtered out)`)
664
- }),
665
-
666
- failedToCacheUI5resource: wrap((path, statusCode) => {
667
- err(job, p80()`Unable to cache '${pad.lt(path)}' (status ${statusCode})`)
668
- }),
669
-
670
- genericError: wrap((error, url) => {
671
- const p = p80()
672
- log(job, p`┌──────────${pad.x('─')}┐`)
673
- log(job, p`│ UNEXPECTED ERROR ${pad.x(' ')} │`)
674
- if (url) {
675
- log(job, p`├──────┬─${pad.x('─')}──┤`)
676
- log(job, p`│ url │ ${pad.lt(url)} │`)
677
- log(job, p`├──────┴─${pad.x('─')}──┤`)
678
- } else {
679
- log(job, p`├────────${pad.x('─')}──┤`)
680
- }
681
- if (error.stack) {
682
- log(job, p`│ ${pad.w(error.stack)} │`)
683
- } else {
684
- log(job, p`│ ${pad.w(error.toString())} │`)
685
- }
686
- if (error.cause) {
687
- log(job, p`├────────${pad.x('─')}──┤`)
688
- log(job, p`│ Cause : ${pad.x(' ')} │`)
689
- if (error.cause.stack) {
690
- log(job, p`│ ${pad.w(error.cause.stack)} │`)
691
- } else {
692
- log(job, p`│ ${pad.w(error.cause.toString())} │`)
693
- }
694
- }
695
- log(job, p`└──────────${pad.x('─')}┘`)
696
- }),
697
-
698
- unhandled: wrap(() => {
699
- warn(job, p80()`⚠️ [UNHAND] Some requests are not handled properly, check the unhandled.txt report for more info`)
700
- }),
701
-
702
- reportGeneratorFailed: wrap((generator, exitCode, buffers) => {
703
- const p = p80()
704
- log(job, p`┌──────────${pad.x('─')}┐`)
705
- log(job, p`│ REPORT GENERATOR FAILED ${pad.x(' ')} │`)
706
- log(job, p`├───────────┬─${pad.x('─')}──┤`)
707
- log(job, p`│ generator │ ${pad.lt(generator)} │`)
708
- log(job, p`├───────────┼─${pad.x('─')}──┤`)
709
- log(job, p`│ exit code │ ${pad.lt(exitCode.toString())} │`)
710
- log(job, p`├───────────┴─${pad.x('─')}──┤`)
711
- log(job, p`│ ${pad.w(buffers.stderr.join(''))} │`)
712
- log(job, p`└──────────${pad.x('─')}┘`)
713
- }),
714
-
715
- stop () {
716
- if (this.reportIntervalId) {
717
- clearInterval(this.reportIntervalId)
718
- if (interactive) {
719
- clean(job)
720
- }
721
- }
722
- }
723
- }
724
- }
725
-
726
- module.exports = {
727
- getOutput (job) {
728
- if (!job[$output]) {
729
- job[$output] = build(job)
730
- }
731
- return job[$output]
732
- },
733
-
734
- newProgress (job, label, total, count) {
735
- const progress = new Progress(job)
736
- Object.assign(progress, { label, total, count })
737
- return progress
738
- }
739
- }