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/coverage.js DELETED
@@ -1,384 +0,0 @@
1
- 'use strict'
2
-
3
- const { join, dirname, isAbsolute, relative, sep } = require('path')
4
- const { fork } = require('child_process')
5
- const { cleanDir, createDir, filename, download, allocPromise } = require('./tools')
6
- const { readdir, readFile, stat, writeFile, access, constants } = require('fs').promises
7
- const { Readable } = require('stream')
8
- const { getOutput, newProgress } = require('./output')
9
- const { resolvePackage } = require('./npm')
10
- const { promisify } = require('util')
11
- const { UTRError } = require('./error')
12
- const { $remoteOnLegacy } = require('./symbols')
13
-
14
- const $nycSettingsPath = Symbol('nycSettingsPath')
15
- const $coverageFileIndex = Symbol('coverageFileIndex')
16
- const $coverageRemote = Symbol('coverageRemote')
17
-
18
- let nycInstallationPath
19
- let nycScript
20
-
21
- async function setupNyc (job) {
22
- if (!nycInstallationPath) {
23
- nycInstallationPath = resolvePackage(job, 'nyc')
24
- }
25
- nycScript = join(await nycInstallationPath, 'bin/nyc.js')
26
- }
27
-
28
- async function nyc (job, ...args) {
29
- const output = getOutput(job)
30
- output.nyc(...args)
31
- const childProcess = fork(nycScript, args, { stdio: 'pipe' })
32
- output.monitor(childProcess)
33
- const { promise, resolve } = allocPromise()
34
- childProcess.on('close', resolve)
35
- return promise
36
- }
37
-
38
- async function safeNyc (job, ...args) {
39
- const code = await nyc(job, ...args)
40
- if (code !== 0) {
41
- const [command] = args
42
- throw UTRError.NYC_FAILED(`nyc ${command} failed with code ${code}`)
43
- }
44
- }
45
-
46
- const globalContextSearch = 'var global=new Function("return this")();'
47
- const globalContextReplace = 'var global=window.top;'
48
-
49
- const customFileSystem = {
50
- stat: path => stat(path)
51
- .then(stats => {
52
- stats.size -= globalContextSearch.length + globalContextReplace.length
53
- return stats
54
- }),
55
- readdir,
56
- createReadStream: async (path) => {
57
- const buffer = (await readFile(path))
58
- .toString()
59
- .replace(globalContextSearch, globalContextReplace)
60
- return Readable.from(buffer)
61
- }
62
- }
63
-
64
- async function instrument (job) {
65
- await setupNyc(job)
66
- job[$nycSettingsPath] = join(job.coverageTempDir, 'settings/.nycrc.json')
67
- await cleanDir(job.coverageTempDir)
68
- await createDir(join(job.coverageTempDir, 'settings'))
69
- const settings = JSON.parse((await readFile(job.coverageSettings)).toString())
70
- settings.cwd = job.webapp
71
- if (!settings.exclude) {
72
- settings.exclude = []
73
- }
74
- settings.exclude.push(join(job.coverageTempDir, '**'))
75
- if (job.cache) {
76
- settings.exclude.push(join(job.cache, '**'))
77
- }
78
- settings.exclude.push(join(job.reportDir, '**'))
79
- settings.exclude.push(join(job.coverageReportDir, '**'))
80
- await writeFile(job[$nycSettingsPath], JSON.stringify(settings))
81
- job.nycSettings = settings
82
- if (job.mode === 'url') {
83
- if (!job[$remoteOnLegacy]) {
84
- job[$coverageRemote] = true
85
- getOutput(job).instrumentationSkipped()
86
- return
87
- }
88
- }
89
- job.status = 'Instrumenting'
90
- await safeNyc(job, 'instrument', job.webapp, join(job.coverageTempDir, 'instrumented'), '--nycrc-path', job[$nycSettingsPath])
91
- }
92
-
93
- function getUrlOrigin (job) {
94
- const { origin } = new URL(job.url[0])
95
- if (job.url.some(url => new URL(url).origin !== origin)) {
96
- getOutput(job).assumingOneOrigin()
97
- }
98
- return origin
99
- }
100
-
101
- async function buildAllIndex (job) {
102
- async function scanFs (path, onFolder, onFile) {
103
- const items = await readdir(path)
104
- await onFolder(items.length)
105
- for (const item of items) {
106
- const itemPath = join(path, item)
107
- const itemStat = await stat(itemPath)
108
- if (itemStat.isDirectory()) {
109
- await scanFs(itemPath, onFolder, onFile)
110
- } else {
111
- await onFile(itemPath, (await readFile(itemPath)).toString())
112
- }
113
- }
114
- }
115
-
116
- const output = getOutput(job)
117
- output.debug('coverage', 'Build index for all files...')
118
- const progress = newProgress(job, 'Build index for all files', 1, 0)
119
-
120
- try {
121
- const index = []
122
- let scan
123
- let start
124
- if (job.mode === 'legacy' || job[$remoteOnLegacy]) {
125
- scan = scanFs
126
- start = join(job.coverageTempDir, 'instrumented')
127
- } else {
128
- scan = require(job.coverageRemoteScanner)
129
- start = getUrlOrigin(job)
130
- }
131
-
132
- await scan(
133
- start,
134
- count => {
135
- progress.total += count
136
- ++progress.count
137
- },
138
- async (file, source) => {
139
- if (file.endsWith('.js') || file.endsWith('.ts')) {
140
- output.debug('coverage', file)
141
- try {
142
- const coverageData = source
143
- .match(/coverageData\s*=\s*({[^;]*});/)[1]
144
- .replace(/([^"])(\w+):/g, (_, before, name) => `${before}"${name}":`)
145
- const [, coveragePath] = coverageData.match(/"path"\s*:\s*"([^"]+)"/)
146
- const UNDEFINED = '__undefined__'
147
- const validatedCoverageData = JSON.stringify(
148
- JSON.parse(coverageData.replace(/\bundefined\b/g, `"${UNDEFINED}"`)),
149
- (key, value) => {
150
- if (value === UNDEFINED) {
151
- return undefined
152
- }
153
- return value
154
- }
155
- )
156
- index.push(`"${coveragePath}": ${validatedCoverageData}`)
157
- } catch (e) {
158
- output.debug('coverage', `Error when extracting all coverage for ${file}`, e)
159
- }
160
- } else {
161
- output.debug('coverage', `Ignore all coverage for ${file}`)
162
- }
163
- ++progress.count
164
- }
165
- )
166
- if (index.length === 0) {
167
- output.noInfoForAllCoverage()
168
- } else {
169
- await writeFile(join(job.coverageTempDir, 'all-index.json'), `{${index.join(',')}}`)
170
- }
171
- } catch (e) {
172
- output.genericError(e, e.url)
173
- output.noInfoForAllCoverage()
174
- } finally {
175
- progress.done()
176
- }
177
- }
178
-
179
- async function getReadableSource (job, pathOrUrl) {
180
- if (isAbsolute(pathOrUrl)) {
181
- try {
182
- await access(pathOrUrl, constants.R_OK)
183
- return pathOrUrl
184
- } catch (e) {}
185
- }
186
- try {
187
- const filePath = join(job.webapp, pathOrUrl)
188
- await access(filePath, constants.R_OK)
189
- return filePath
190
- } catch (e) {}
191
- try {
192
- const origin = getUrlOrigin(job)
193
- if (!job.coverageSourceDir) {
194
- job.coverageSourceDir = join(job.coverageTempDir, 'sources')
195
- }
196
- const filePath = join(job.coverageSourceDir, pathOrUrl)
197
- await download(origin + pathOrUrl, filePath)
198
- return filePath
199
- } catch (e) {}
200
- }
201
-
202
- async function checkAllSourcesAreAvailable (job, coverageFilename) {
203
- const output = getOutput(job)
204
- job.status = 'Checking remote source files'
205
- output.debug('coverage', 'Checking remote source files...')
206
- const coverageData = require(coverageFilename)
207
- const filenames = Object.keys(coverageData)
208
- let changes = false
209
- let basePath
210
- for (const filename of filenames) {
211
- const fileData = coverageData[filename]
212
- const filePath = await getReadableSource(job, fileData.path)
213
- if (!filePath) {
214
- // TODO this will compromise coverage report generation
215
- continue
216
- }
217
- if (filePath && filePath !== fileData.path) {
218
- fileData.path = filePath
219
- changes = true
220
- }
221
- if (filename !== filePath) {
222
- delete coverageData[filename]
223
- coverageData[filePath] = fileData
224
- changes = true
225
- }
226
- const fileFolder = dirname(filePath)
227
- if (basePath === undefined) {
228
- basePath = fileFolder
229
- } else {
230
- const diff = relative(basePath, fileFolder).split(sep)
231
- while (diff.shift() === '..') {
232
- basePath = dirname(basePath)
233
- }
234
- }
235
- }
236
- if (basePath !== job.nycSettings.cwd) {
237
- job.nycSettings.cwd = basePath
238
- await writeFile(job[$nycSettingsPath], JSON.stringify(job.nycSettings))
239
- }
240
- if (changes) {
241
- await writeFile(coverageFilename, JSON.stringify(coverageData))
242
- }
243
- }
244
-
245
- async function generateCoverageReport (job) {
246
- job.status = 'Generating coverage report'
247
- if (job.nycSettings.all) {
248
- await buildAllIndex(job)
249
- }
250
- const output = getOutput(job)
251
- output.debug('coverage', 'Generating coverage report...')
252
- await cleanDir(job.coverageReportDir)
253
- const coverageMergedDir = join(job.coverageTempDir, 'merged')
254
- await createDir(coverageMergedDir)
255
- const coverageFilename = join(coverageMergedDir, 'coverage.json')
256
- await safeNyc(job, 'merge', job.coverageTempDir, coverageFilename)
257
- if (job[$coverageRemote]) {
258
- await checkAllSourcesAreAvailable(job, coverageFilename)
259
- }
260
- const reporters = job.coverageReporters.map(reporter => `--reporter=${reporter}`)
261
- if (!job.coverageReporters.includes('text')) {
262
- reporters.push('--reporter=text')
263
- }
264
- const checks = []
265
- if (job.coverageCheckBranches || job.coverageCheckFunctions || job.coverageCheckLines || job.coverageCheckStatements) {
266
- if (!job.coverageReporters.includes('lcov')) {
267
- reporters.push('--reporter=lcov')
268
- }
269
- checks.push(
270
- `--branches=${job.coverageCheckBranches}`,
271
- `--functions=${job.coverageCheckFunctions}`,
272
- `--lines=${job.coverageCheckLines}`,
273
- `--statements=${job.coverageCheckStatements}`,
274
- '--check-coverage'
275
- )
276
- }
277
- const returnCode = await nyc(job, 'report', ...reporters, ...checks, '--temp-dir', coverageMergedDir, '--report-dir', job.coverageReportDir, '--nycrc-path', job[$nycSettingsPath])
278
- if (checks.length) {
279
- // The checks are not triggered if the coverage is empty
280
- const lcov = await stat(join(job.coverageReportDir, 'lcov.info'))
281
- if (lcov.size === 0) {
282
- throw UTRError.NYC_FAILED('No coverage information extracted')
283
- }
284
- if (returnCode === 1) {
285
- // Assuming coverage report shows the error
286
- output.debug('coverage', `nyc report failed with code ${returnCode}`)
287
- job.failed = true
288
- }
289
- } else if (returnCode !== 0) {
290
- throw UTRError.NYC_FAILED(`nyc report failed with code ${returnCode}`)
291
- }
292
- }
293
-
294
- module.exports = {
295
- instrument: job => job.coverage && instrument(job),
296
- async collect (job, url, coverageData) {
297
- if (!job.coverage) {
298
- return
299
- }
300
- job[$coverageFileIndex] = (job[$coverageFileIndex] || 0) + 1
301
- const coverageFileName = join(job.coverageTempDir, `${filename(url)}_${job[$coverageFileIndex]}.json`)
302
- getOutput(job).debug('coverage', `saved coverage in '${coverageFileName}'`)
303
- await writeFile(coverageFileName, JSON.stringify(coverageData))
304
- },
305
- generateCoverageReport: job => job.coverage ? generateCoverageReport(job) : Promise.resolve(),
306
- mappings: async job => {
307
- if (!job.coverage) {
308
- return []
309
- }
310
- const instrumentedBasePath = join(job.coverageTempDir, 'instrumented')
311
- const instrumentedMapping = {
312
- match: /(.*\.js)(\?.*)?$/,
313
- cwd: instrumentedBasePath,
314
- file: '$1'
315
- }
316
- if (job.mode === 'legacy' || job[$remoteOnLegacy]) {
317
- return [{
318
- ...instrumentedMapping,
319
- 'custom-file-system': job.debugCoverageNoCustomFs ? undefined : customFileSystem
320
- }]
321
- }
322
- if (job.mode === 'url' && job.coverageProxy) {
323
- await setupNyc(job)
324
- // Assuming all files are coming from the same server
325
- const { origin } = new URL(job.url[0])
326
- let instrument
327
- try {
328
- const { createInstrumenter } = require(join(await nycInstallationPath, 'node_modules/istanbul-lib-instrument'))
329
- const instrumenter = createInstrumenter({
330
- produceSourceMap: true,
331
- coverageGlobalScope: 'window.top',
332
- coverageGlobalScopeFunc: false
333
- })
334
- instrument = promisify(instrumenter.instrument.bind(instrumenter))
335
- } catch (e) {
336
- // Recent version of nyc offers a different interface
337
- const createInstrumenter = require(join(await nycInstallationPath, 'lib/instrumenters/istanbul.js'))
338
- const instrumenter = createInstrumenter({
339
- produceSourceMap: true
340
- })
341
- instrument = async function (code, sourcePath) {
342
- return instrumenter.instrumentSync(code, sourcePath, { registerMap: () => {} })
343
- // TODO use regular expression !
344
- .replace(globalContextSearch, globalContextReplace)
345
- }
346
- }
347
- const sources = {}
348
- return [{
349
- match: /(.*\.js)(\?.*)?$/,
350
- custom: async (request, response, url) => {
351
- if (!url.match(job.coverageProxyInclude) || url.match(job.coverageProxyExclude)) {
352
- getOutput(job).debug('coverage', 'coverage_proxy ignore', url)
353
- return
354
- }
355
- const instrumentedSourcePath = join(instrumentedBasePath, url)
356
- try {
357
- await access(instrumentedSourcePath, constants.R_OK)
358
- return
359
- } catch (e) {}
360
- if (!sources[url]) {
361
- sources[url] = (async () => {
362
- const sourcePath = await getReadableSource(job, url)
363
- getOutput(job).debug('coverage', 'coverage_proxy instrument', url, sourcePath)
364
- if (sourcePath) {
365
- const source = (await readFile(sourcePath)).toString()
366
- const instrumentedSource = await instrument(source, sourcePath)
367
- await createDir(dirname(instrumentedSourcePath))
368
- await writeFile(instrumentedSourcePath, instrumentedSource)
369
- delete sources[url]
370
- }
371
- })()
372
- }
373
- await sources[url]
374
- }
375
- },
376
- instrumentedMapping,
377
- {
378
- match: /(.*)$/,
379
- url: `${origin}$1`
380
- }]
381
- }
382
- return []
383
- }
384
- }
package/src/csv-reader.js DELETED
@@ -1,36 +0,0 @@
1
- 'use strict'
2
-
3
- const { createReadStream } = require('fs')
4
- const readline = require('readline')
5
-
6
- const unescape = value => {
7
- if (value.startsWith('"') && value.endsWith('"')) {
8
- return JSON.parse(value)
9
- }
10
- return value
11
- }
12
-
13
- async function * buildCsvReader (fileName) {
14
- const fileStream = createReadStream(fileName)
15
- const rl = readline.createInterface({
16
- input: fileStream,
17
- crlfDelay: Infinity
18
- })
19
- let headers
20
- for await (const line of rl) {
21
- const fields = line.split('\t')
22
- if (headers === undefined) {
23
- headers = fields
24
- continue
25
- }
26
- const record = {}
27
- headers.forEach((field, index) => {
28
- record[field] = unescape(fields[index])
29
- })
30
- yield record
31
- }
32
- }
33
-
34
- module.exports = {
35
- buildCsvReader
36
- }
package/src/csv-writer.js DELETED
@@ -1,55 +0,0 @@
1
- 'use strict'
2
-
3
- const { writeFile } = require('fs/promises')
4
-
5
- const append = (fileName, line) => writeFile(fileName, line + '\n', { flag: 'a+' })
6
- const escape = value => {
7
- if (value === undefined) {
8
- return '❓'
9
- }
10
- const stringValue = value.toString()
11
- if (stringValue.match(/\r|\n|\t|"/)) {
12
- return JSON.stringify(stringValue)
13
- }
14
- return stringValue
15
- }
16
-
17
- class CsvWriter {
18
- #fileName
19
- #ready
20
- #fields
21
-
22
- constructor (fileName) {
23
- this.#fileName = fileName
24
- this.#ready = Promise.resolve()
25
- this.#fields = []
26
- }
27
-
28
- get ready () {
29
- return this.#ready
30
- }
31
-
32
- append (records) {
33
- if (!Array.isArray(records)) {
34
- records = [records]
35
- }
36
- if (this.#fields.length === 0) {
37
- this.#fields = Object.keys(records[0]).filter(name => name !== 'timestamp')
38
- this.#ready = this.#ready.then(() => append(this.#fileName, `timestamp\t${this.#fields.join('\t')}`))
39
- }
40
- const lines = records.map(record => {
41
- const { timestamp = Date.now() } = record
42
- return [
43
- timestamp,
44
- ...this.#fields.map(name => escape(record[name]))
45
- ].join('\t')
46
- }).join('\n')
47
- this.#ready = this.#ready.then(() => append(this.#fileName, lines))
48
- }
49
- }
50
-
51
- module.exports = {
52
- buildCsvWriter (fileName) {
53
- return new CsvWriter(fileName)
54
- }
55
- }
@@ -1,4 +0,0 @@
1
- {
2
- "all": true,
3
- "sourceMap": false
4
- }
@@ -1,217 +0,0 @@
1
- const { readFile, writeFile } = require('fs/promises')
2
- const { join } = require('path')
3
- const { Command, InvalidArgumentError } = require('commander')
4
- const { buildCsvWriter } = require('../csv-writer')
5
- const { any, arrayOf, boolean, integer, string } = require('../options')
6
-
7
- const noop = () => { }
8
-
9
- module.exports = ({
10
- metadata,
11
- flush = noop,
12
- beforeExit = noop,
13
- screenshot,
14
- capabilities: computeCapabilities,
15
- run,
16
- error = noop
17
- }) => {
18
- const command = new Command()
19
- command
20
- .name(`ui5-test-runner/@/${metadata.name}`)
21
- .description(`Browser instantiation command for ${metadata.name}`)
22
- .helpOption(false)
23
- metadata.options
24
- .map(option => {
25
- if (option[0] === 'browser') {
26
- const [, ...browsers] = option
27
- return [[
28
- '-b, --browser <name>', 'Browser driver',
29
- function (value) {
30
- if (value === undefined) {
31
- return browsers[0]
32
- }
33
- if (!browsers.includes(value)) {
34
- throw new InvalidArgumentError('Browser name')
35
- }
36
- return value
37
- },
38
- browsers[0]
39
- ]]
40
- }
41
- if (option === 'binary') {
42
- return [['--binary <binary>', 'Binary path']]
43
- }
44
- if (option === 'visible') {
45
- return [['--visible [flag]', 'Show the browser', false]]
46
- }
47
- if (option === 'viewport') {
48
- return [
49
- ['-w, --viewport-width <width>', 'Viewport width', 1920],
50
- ['-h, --viewport-height <height>', 'Viewport height', 1080]
51
- ]
52
- }
53
- if (option === 'language') {
54
- return [['-l, --language <lang...>', 'Language(s) (see rfc5646)', arrayOf(string, true), ['en-US']]]
55
- }
56
- if (option === 'unsecure') {
57
- return [['-u, --unsecure', 'Disable security features', false]]
58
- }
59
- return [option]
60
- })
61
- .flat()
62
- .forEach(([label, description, parser, defaultValue]) => {
63
- if (defaultValue === undefined && typeof parser !== 'function') {
64
- defaultValue = parser
65
- if (typeof defaultValue === 'number') {
66
- parser = integer
67
- } else if (typeof defaultValue === 'boolean') {
68
- parser = boolean
69
- } else {
70
- parser = any
71
- }
72
- }
73
- command.option(label, description, parser, defaultValue)
74
- })
75
-
76
- const append = () => { }
77
- let consoleWriter = { ready: Promise.resolve(), append }
78
- let networkWriter = { ready: Promise.resolve(), append }
79
-
80
- let stopping = false
81
- let settings
82
- let options
83
-
84
- async function exit (code) {
85
- if (stopping) {
86
- return
87
- }
88
- stopping = true
89
- if (settings && typeof settings.capabilities !== 'string' && settings.capabilities.traces.length) {
90
- try {
91
- await flush({
92
- settings,
93
- options,
94
- consoleWriter,
95
- networkWriter
96
- })
97
- } catch (e) {
98
- console.error('[exit:flush]', e)
99
- code = -3
100
- }
101
- await Promise.all([consoleWriter.ready, networkWriter.ready])
102
- }
103
- try {
104
- await beforeExit({
105
- settings,
106
- options
107
- })
108
- } catch (e) {
109
- console.error('[exit:beforeExit]', e)
110
- // but ignore
111
- }
112
- process.exit(code)
113
- }
114
-
115
- process.on('message', async message => {
116
- const { command } = message
117
- try {
118
- if (command === 'stop') {
119
- await exit(0)
120
- } else if (command === 'screenshot') {
121
- if (settings.capabilities.screenshot && screenshot && await screenshot({
122
- settings,
123
- options,
124
- filename: message.filename
125
- })) {
126
- process.send(message)
127
- } else {
128
- throw new Error('screenshot command failed')
129
- }
130
- }
131
- } catch (e) {
132
- console.error(e)
133
- exit(-2)
134
- }
135
- })
136
-
137
- if (process.argv[2] === 'test') {
138
- command.parse(process.argv.slice(3), { from: 'user' })
139
- console.log(command.opts(), command.args)
140
- return exit(0)
141
- }
142
-
143
- if (process.argv.length !== 3) {
144
- command.outputHelp()
145
- return exit(0)
146
- }
147
-
148
- async function main () {
149
- settings = JSON.parse((await readFile(process.argv[2])).toString())
150
- command.parse(settings.args, { from: 'user' })
151
- options = command.opts()
152
-
153
- options.chromeArgs = function () {
154
- const args = [
155
- 'true', // Not sure why but this changes the behavior of the browser
156
- '--start-maximized',
157
- '--no-sandbox',
158
- '--disable-gpu',
159
- '--disable-extensions',
160
- '--log-level=3',
161
- `--window-size=${options.viewportWidth},${options.viewportHeight}`
162
- ]
163
- if (options.language) {
164
- args.push(`--lang=${options.language.join(',')}`)
165
- }
166
- if (!options.visible) {
167
- args.push('--headless=new')
168
- }
169
- if (options.unsecure) {
170
- args.push(
171
- '--ignore-certificate-errors',
172
- '--disable-web-security',
173
- '--disable-features=IsolateOrigins',
174
- '--disable-features=BlockInsecurePrivateNetworkRequests',
175
- '--disable-site-isolation-trials'
176
- )
177
- }
178
- return args.concat(command.args)
179
- }
180
-
181
- if (typeof settings.capabilities === 'string') {
182
- let capabilities
183
- if (computeCapabilities !== undefined) {
184
- capabilities = await computeCapabilities({ settings, options })
185
- } else {
186
- capabilities = metadata.capabilities
187
- }
188
- await writeFile(settings.capabilities, JSON.stringify(capabilities, undefined, 2))
189
- return exit(0)
190
- }
191
-
192
- consoleWriter = buildCsvWriter(join(settings.dir, 'console.csv'))
193
- networkWriter = buildCsvWriter(join(settings.dir, 'network.csv'))
194
-
195
- await run({
196
- settings,
197
- options,
198
- consoleWriter,
199
- networkWriter,
200
- exit
201
- })
202
- }
203
-
204
- main()
205
- .catch(async e => {
206
- if (!stopping) {
207
- await error({
208
- settings,
209
- options,
210
- error: e,
211
- exit
212
- })
213
- console.error(e)
214
- }
215
- exit(-1)
216
- })
217
- }