ui5-test-runner 4.5.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,18 +34,15 @@ A self-sufficient test runner for UI5 applications enabling parallel execution o
34
34
 
35
35
  ## ⚠️ Breaking changes
36
36
 
37
- ### v4
38
- * Dropping support of Node.js 16
39
-
40
- ### v3
41
- * Dropping support of Node.js 14
42
-
43
- ### v2
44
-
45
- * Command line **parameters** as well as configuration file **syntax** have changed
46
- * Dependencies are installed **on demand**
47
- * Browser instantiation command evolved in an **incompatible way** (see [documentation](https://arnaudbuchholz.github.io/ui5-test-runner/browser.html)).
48
- * Output is different (report, traces)
37
+ | Version | Reason |
38
+ |-|-|
39
+ | **5**.0.0 | • Some coverage reports now includes **all** files, leading to a potential decrease of coverage |
40
+ | **4**.0.0 | • Drop support of Node.js 16 |
41
+ | **3**.0.0 | • Drop support of Node.js 14 |
42
+ | **2**.0.0 | • Command line **parameters** as well as configuration file **syntax** have changed |
43
+ || • Dependencies are installed **on demand** |
44
+ || • Browser instantiation command evolved in an **incompatible way** (see [documentation](https://arnaudbuchholz.github.io/ui5-test-runner/browser.html)) |
45
+ || Output is different (report, traces) |
49
46
 
50
47
  ## ✒ Contributors
51
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui5-test-runner",
3
- "version": "4.5.1",
3
+ "version": "5.0.0",
4
4
  "description": "Standalone test runner for UI5",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@openui5/types": "^1.123.0",
54
- "@ui5/cli": "^3.9.2",
54
+ "@ui5/cli": "^3.10.0",
55
55
  "@ui5/middleware-code-coverage": "^1.1.1",
56
56
  "dotenv": "^16.4.5",
57
57
  "jest": "^29.7.0",
@@ -61,7 +61,7 @@
61
61
  "standard": "^17.1.0",
62
62
  "start-server-and-test": "^2.0.3",
63
63
  "typescript": "^5.4.5",
64
- "ui5-tooling-transpile": "^3.3.7"
64
+ "ui5-tooling-transpile": "^3.4.0"
65
65
  },
66
66
  "optionalDependencies": {
67
67
  "fsevents": "^2.3.3"
package/src/browsers.js CHANGED
@@ -116,8 +116,9 @@ async function start (job, url, scripts = []) {
116
116
  }
117
117
  }
118
118
  if (resolvedScripts.length) {
119
- resolvedScripts.unshift(`window['ui5-test-runner/base-host'] = 'http://localhost:${job.port}'
120
- `)
119
+ resolvedScripts.unshift(`(function () {
120
+ window['ui5-test-runner/base-host'] = 'http://localhost:${job.port}'
121
+ }())`)
121
122
  }
122
123
  const progress = newProgress(job, url)
123
124
  const pageBrowser = {
package/src/coverage.js CHANGED
@@ -1,11 +1,11 @@
1
1
  'use strict'
2
2
 
3
- const { join, dirname, isAbsolute } = require('path')
3
+ const { join, dirname, isAbsolute, relative, sep } = require('path')
4
4
  const { fork } = require('child_process')
5
5
  const { cleanDir, createDir, filename, download, allocPromise } = require('./tools')
6
6
  const { readdir, readFile, stat, writeFile, access, constants } = require('fs').promises
7
7
  const { Readable } = require('stream')
8
- const { getOutput } = require('./output')
8
+ const { getOutput, newProgress } = require('./output')
9
9
  const { resolvePackage } = require('./npm')
10
10
  const { promisify } = require('util')
11
11
  const { UTRError } = require('./error')
@@ -64,7 +64,7 @@ async function instrument (job) {
64
64
  await cleanDir(job.coverageTempDir)
65
65
  await createDir(join(job.coverageTempDir, 'settings'))
66
66
  const settings = JSON.parse((await readFile(job.coverageSettings)).toString())
67
- settings.cwd = job.cwd
67
+ settings.cwd = job.webapp
68
68
  if (!settings.exclude) {
69
69
  settings.exclude = []
70
70
  }
@@ -75,6 +75,7 @@ async function instrument (job) {
75
75
  settings.exclude.push(join(job.reportDir, '**'))
76
76
  settings.exclude.push(join(job.coverageReportDir, '**'))
77
77
  await writeFile(job[$nycSettingsPath], JSON.stringify(settings))
78
+ job.nycSettings = settings
78
79
  if (job.mode === 'url') {
79
80
  if (!job[$remoteOnLegacy]) {
80
81
  job[$coverageRemote] = true
@@ -86,6 +87,92 @@ async function instrument (job) {
86
87
  await nyc(job, 'instrument', job.webapp, join(job.coverageTempDir, 'instrumented'), '--nycrc-path', job[$nycSettingsPath])
87
88
  }
88
89
 
90
+ function getUrlOrigin (job) {
91
+ const { origin } = new URL(job.url[0])
92
+ if (job.url.some(url => new URL(url).origin !== origin)) {
93
+ getOutput(job).assumingOneOrigin()
94
+ }
95
+ return origin
96
+ }
97
+
98
+ async function buildAllIndex (job) {
99
+ async function scanFs (path, onFolder, onFile) {
100
+ const items = await readdir(path)
101
+ await onFolder(items.length)
102
+ for (const item of items) {
103
+ const itemPath = join(path, item)
104
+ const itemStat = await stat(itemPath)
105
+ if (itemStat.isDirectory()) {
106
+ await scanFs(itemPath, onFolder, onFile)
107
+ } else {
108
+ await onFile(itemPath, (await readFile(itemPath)).toString())
109
+ }
110
+ }
111
+ }
112
+
113
+ const output = getOutput(job)
114
+ output.debug('coverage', 'Build index for all files...')
115
+ const progress = newProgress(job, 'Build index for all files', 1, 0)
116
+
117
+ try {
118
+ const index = []
119
+ let scan
120
+ let start
121
+ if (job.mode === 'legacy' || job[$remoteOnLegacy]) {
122
+ scan = scanFs
123
+ start = join(job.coverageTempDir, 'instrumented')
124
+ } else {
125
+ scan = require(job.coverageRemoteScanner)
126
+ start = getUrlOrigin(job)
127
+ }
128
+
129
+ await scan(
130
+ start,
131
+ count => {
132
+ progress.total += count
133
+ ++progress.count
134
+ },
135
+ async (file, source) => {
136
+ if (file.endsWith('.js') || file.endsWith('.ts')) {
137
+ output.debug('coverage', file)
138
+ try {
139
+ const coverageData = source
140
+ .match(/coverageData\s*=\s*({[^;]*});/)[1]
141
+ .replace(/([^"])(\w+):/g, (_, before, name) => `${before}"${name}":`)
142
+ const [, coveragePath] = coverageData.match(/"path"\s*:\s*"([^"]+)"/)
143
+ const UNDEFINED = '__undefined__'
144
+ const validatedCoverageData = JSON.stringify(
145
+ JSON.parse(coverageData.replace(/\bundefined\b/g, `"${UNDEFINED}"`)),
146
+ (key, value) => {
147
+ if (value === UNDEFINED) {
148
+ return undefined
149
+ }
150
+ return value
151
+ }
152
+ )
153
+ index.push(`"${coveragePath}": ${validatedCoverageData}`)
154
+ } catch (e) {
155
+ output.debug('coverage', `Error when extracting all coverage for ${file}`, e)
156
+ }
157
+ } else {
158
+ output.debug('coverage', `Ignore all coverage for ${file}`)
159
+ }
160
+ ++progress.count
161
+ }
162
+ )
163
+ if (index.length === 0) {
164
+ output.noInfoForAllCoverage()
165
+ } else {
166
+ await writeFile(join(job.coverageTempDir, 'all-index.json'), `{${index.join(',')}}`)
167
+ }
168
+ } catch (e) {
169
+ output.genericError(e)
170
+ output.noInfoForAllCoverage()
171
+ } finally {
172
+ progress.done()
173
+ }
174
+ }
175
+
89
176
  async function getReadableSource (job, pathOrUrl) {
90
177
  if (isAbsolute(pathOrUrl)) {
91
178
  try {
@@ -99,16 +186,59 @@ async function getReadableSource (job, pathOrUrl) {
99
186
  return filePath
100
187
  } catch (e) {}
101
188
  try {
102
- // Assuming all files are coming from the same server
103
- const { origin } = new URL(job.testPageUrls[0])
104
- const filePath = join(job.coverageTempDir, 'sources', pathOrUrl)
189
+ const origin = getUrlOrigin(job)
190
+ if (!job.coverageSourceDir) {
191
+ job.coverageSourceDir = join(job.coverageTempDir, 'sources')
192
+ }
193
+ const filePath = join(job.coverageSourceDir, pathOrUrl)
105
194
  await download(origin + pathOrUrl, filePath)
106
195
  return filePath
107
196
  } catch (e) {}
108
197
  }
109
198
 
199
+ async function checkAllSourcesAreAvailable (job, coverageFilename) {
200
+ const output = getOutput(job)
201
+ job.status = 'Checking remote source files'
202
+ output.debug('coverage', 'Checking remote source files...')
203
+ const coverageData = require(coverageFilename)
204
+ const filenames = Object.keys(coverageData)
205
+ let changes = 0
206
+ let basePath
207
+ for (const filename of filenames) {
208
+ const fileData = coverageData[filename]
209
+ const filePath = await getReadableSource(job, fileData.path)
210
+ if (!filePath) {
211
+ // TODO this will compromise coverage report generation
212
+ continue
213
+ }
214
+ if (filePath && filePath !== fileData.path) {
215
+ fileData.path = filePath
216
+ ++changes
217
+ }
218
+ const fileFolder = dirname(filePath)
219
+ if (basePath === undefined) {
220
+ basePath = fileFolder
221
+ } else {
222
+ const diff = relative(basePath, fileFolder).split(sep)
223
+ while (diff.shift() === '..') {
224
+ basePath = dirname(basePath)
225
+ }
226
+ }
227
+ }
228
+ if (basePath !== job.nycSettings.cwd) {
229
+ job.nycSettings.cwd = basePath
230
+ await writeFile(job[$nycSettingsPath], JSON.stringify(job.nycSettings))
231
+ }
232
+ if (changes > 0) {
233
+ await writeFile(coverageFilename, JSON.stringify(coverageData))
234
+ }
235
+ }
236
+
110
237
  async function generateCoverageReport (job) {
111
238
  job.status = 'Generating coverage report'
239
+ if (job.nycSettings.all) {
240
+ await buildAllIndex(job)
241
+ }
112
242
  const output = getOutput(job)
113
243
  output.debug('coverage', 'Generating coverage report...')
114
244
  await cleanDir(job.coverageReportDir)
@@ -116,23 +246,8 @@ async function generateCoverageReport (job) {
116
246
  await createDir(coverageMergedDir)
117
247
  const coverageFilename = join(coverageMergedDir, 'coverage.json')
118
248
  await nyc(job, 'merge', job.coverageTempDir, coverageFilename)
119
- if (job[$coverageRemote] && !job.coverageProxy) {
120
- job.status = 'Checking remote source files'
121
- output.debug('coverage', 'Checking remote source files...')
122
- const coverageData = require(coverageFilename)
123
- const filenames = Object.keys(coverageData)
124
- let changes = 0
125
- for (const filename of filenames) {
126
- const fileData = coverageData[filename]
127
- const filePath = await getReadableSource(job, fileData.path)
128
- if (filePath && filePath !== fileData.path) {
129
- fileData.path = filePath
130
- ++changes
131
- }
132
- }
133
- if (changes > 0) {
134
- await writeFile(coverageFilename, JSON.stringify(coverageData))
135
- }
249
+ if (job[$coverageRemote]) {
250
+ await checkAllSourcesAreAvailable(job, coverageFilename)
136
251
  }
137
252
  const reporters = job.coverageReporters.map(reporter => `--reporter=${reporter}`)
138
253
  if (!job.coverageReporters.includes('text')) {
@@ -201,7 +316,7 @@ module.exports = {
201
316
  return [{
202
317
  match: /(.*\.js)(\?.*)?$/,
203
318
  custom: async (request, response, url) => {
204
- if (!url.match(job.coverageProxyInclude) || url.match(/\bresources\b/) || url.match(job.coverageProxyExclude)) {
319
+ if (!url.match(job.coverageProxyInclude) || url.match(job.coverageProxyExclude)) {
205
320
  getOutput(job).debug('coverage', 'coverage_proxy ignore', url)
206
321
  return
207
322
  }
@@ -210,21 +325,20 @@ module.exports = {
210
325
  await access(instrumentedSourcePath, constants.R_OK)
211
326
  return
212
327
  } catch (e) {}
213
- const instrumenting = sources[url]
214
- if (instrumenting) {
215
- await instrumenting
216
- return // ok
328
+ if (!sources[url]) {
329
+ sources[url] = (async () => {
330
+ const sourcePath = await getReadableSource(job, url)
331
+ getOutput(job).debug('coverage', 'coverage_proxy instrument', url, sourcePath)
332
+ if (sourcePath) {
333
+ const source = (await readFile(sourcePath)).toString()
334
+ const instrumentedSource = await instrument(source, sourcePath)
335
+ await createDir(dirname(instrumentedSourcePath))
336
+ await writeFile(instrumentedSourcePath, instrumentedSource)
337
+ delete sources[url]
338
+ }
339
+ })()
217
340
  }
218
- sources[url] = (async () => {
219
- const sourcePath = await getReadableSource(job, url)
220
- getOutput(job).debug('coverage', 'coverage_proxy instrument', url, sourcePath)
221
- if (sourcePath) {
222
- const source = (await readFile(sourcePath)).toString()
223
- const instrumentedSource = await instrument(source, sourcePath)
224
- await createDir(dirname(instrumentedSourcePath))
225
- await writeFile(instrumentedSourcePath, instrumentedSource)
226
- }
227
- })()
341
+ await sources[url]
228
342
  }
229
343
  },
230
344
  instrumentedMapping,
@@ -39,7 +39,8 @@ async function main () {
39
39
  time = (new Date(test.end) - new Date(test.start)) / 1000
40
40
  }
41
41
  o(` <testcase
42
- name="${xmlEscape(test.name)}" ${
42
+ name="${xmlEscape(test.name)}"
43
+ classname="${xmlEscape(module.name)}" ${
43
44
  time === undefined
44
45
  ? ''
45
46
  : `
@@ -8,17 +8,22 @@ require('./browser')({
8
8
  name: 'puppeteer',
9
9
  options: [
10
10
  ['--visible [flag]', 'Show the browser', false],
11
+ ['--firefox [flag]', 'Use firefox instead of chrome', false],
12
+ ['--binary <binary>', 'Binary path'],
11
13
  ['-w, --viewport-width <width>', 'Viewport width', 1920],
12
14
  ['-h, --viewport-height <height>', 'Viewport height', 1080],
13
15
  ['-l, --language <lang...>', 'Language(s)', ['en-US']],
14
16
  ['-u, --unsecure', 'Disable security features', false],
15
17
  ['--basic-auth-username <username>', 'Username for basic authentication', ''],
16
18
  ['--basic-auth-password <password>', 'Password for basic authentication', '']
17
- ],
18
- capabilities: {
19
+ ]
20
+ },
21
+
22
+ async capabilities ({ settings, options }) {
23
+ return {
19
24
  modules: ['puppeteer'],
20
25
  screenshot: '.png',
21
- scripts: true,
26
+ scripts: !options.firefox,
22
27
  traces: ['console', 'network']
23
28
  }
24
29
  },
@@ -68,7 +73,14 @@ require('./browser')({
68
73
  )
69
74
  }
70
75
 
76
+ let product
77
+ if (options.firefox) {
78
+ product = 'firefox'
79
+ }
80
+
71
81
  browser = await puppeteer.launch({
82
+ product,
83
+ executablePath: options.binary,
72
84
  headless: options.visible ? false : 'new',
73
85
  defaultViewport: null,
74
86
  args
@@ -0,0 +1,20 @@
1
+ module.exports = async function scanUI5 (url, onFolder, onFile) {
2
+ if (url.match(/\/((?:test-)?resources\/.*)/)) {
3
+ return // ignore UI5 resources
4
+ }
5
+ const html = await (await fetch(url)).text()
6
+ const items = [...html.matchAll(/<a href="([^"]+)" class="icon/ig)]
7
+ .map(([_, item]) => item)
8
+ .filter(item => item.endsWith('/') || item.endsWith('.js') || item.endsWith('.ts'))
9
+ await onFolder(items.length)
10
+ for (const item of items) {
11
+ const itemUrl = new URL(item, url).toString()
12
+ if (item.endsWith('/')) {
13
+ await scanUI5(itemUrl, onFolder, onFile)
14
+ } else if (item.endsWith('.ts')) {
15
+ await onFile(itemUrl, await (await fetch(itemUrl.replace(/\.ts$/, '.js'))).text())
16
+ } else {
17
+ await onFile(itemUrl, await (await fetch(itemUrl + '?instrument=true')).text())
18
+ }
19
+ }
20
+ }
@@ -4,8 +4,7 @@ module.exports = async ({
4
4
  seleniumWebdriver,
5
5
  settings,
6
6
  options,
7
- loggingPreferences,
8
- $capabilities
7
+ loggingPreferences
9
8
  }) => {
10
9
  const { Browser, Builder } = seleniumWebdriver
11
10
  const edge = require(join(settings.modules['selenium-webdriver'], 'edge'))
@@ -4,15 +4,14 @@ module.exports = async ({
4
4
  seleniumWebdriver,
5
5
  settings,
6
6
  options,
7
- loggingPreferences,
8
- $capabilities
7
+ loggingPreferences
9
8
  }) => {
10
9
  const { Browser, Builder } = seleniumWebdriver
11
10
  const firefox = require(join(settings.modules['selenium-webdriver'], 'firefox'))
12
11
 
13
12
  const firefoxOptions = new firefox.Options()
14
13
  if (!options.visible) {
15
- firefoxOptions.headless = true
14
+ firefoxOptions.addArguments('-headless')
16
15
  }
17
16
  firefoxOptions.setLoggingPrefs(loggingPreferences)
18
17
  if (options.binary) {
@@ -7,7 +7,7 @@ const { writeFile } = require('fs/promises')
7
7
  let logging
8
8
  let driver
9
9
 
10
- function browser (value, defaultValue) {
10
+ function browser (value) {
11
11
  if (value === undefined) {
12
12
  return 'chrome'
13
13
  }
@@ -0,0 +1,89 @@
1
+ 'use strict'
2
+
3
+ const { InvalidArgumentError } = require('commander')
4
+
5
+ let browserio
6
+
7
+ function browser (value) {
8
+ if (value === undefined) {
9
+ return 'chrome'
10
+ }
11
+ if (!['chrome', 'firefox'].includes(value)) {
12
+ throw new InvalidArgumentError('Browser name')
13
+ }
14
+ return value
15
+ }
16
+
17
+ require('./browser')({
18
+ metadata: {
19
+ name: 'webdriverio',
20
+ options: [
21
+ ['--visible [flag]', 'Show the browser', false],
22
+ ['-b, --browser <name>', 'Browser driver', browser, 'chrome'],
23
+ ['--binary <binary>', 'Binary path']
24
+ ]
25
+ },
26
+
27
+ async capabilities ({ settings, options }) {
28
+ return {
29
+ modules: ['webdriverio'],
30
+ screenshot: '.png',
31
+ scripts: true,
32
+ traces: []
33
+ }
34
+ },
35
+
36
+ async screenshot ({ filename }) {
37
+ if (browserio) {
38
+ await browserio.saveScreenshot(filename)
39
+ return true
40
+ }
41
+ },
42
+
43
+ async beforeExit () {
44
+ if (browserio) {
45
+ await browserio.deleteSession()
46
+ }
47
+ },
48
+
49
+ async run ({
50
+ settings: { url, scripts, modules },
51
+ options,
52
+ consoleWriter,
53
+ networkWriter
54
+ }) {
55
+ const { remote } = require(modules.webdriverio)
56
+
57
+ const [browserOptions, args] = {
58
+ chrome: [
59
+ 'goog:chromeOptions',
60
+ options.visible ? [] : ['--headless=new', '--log-level=3', '--disable-gpu']
61
+ ],
62
+ firefox: [
63
+ 'moz:firefoxOptions',
64
+ options.visible ? [] : ['-headless']
65
+ ]
66
+ }[options.browser]
67
+
68
+ browserio = await remote({
69
+ capabilities: {
70
+ browserName: options.browser,
71
+ webSocketUrl: true,
72
+ [browserOptions]: {
73
+ args,
74
+ binary: options.binary
75
+ }
76
+ }
77
+ })
78
+
79
+ if (scripts && scripts.length) {
80
+ for (const script of scripts) {
81
+ await browserio.scriptAddPreloadScript({
82
+ functionDeclaration: `() => ${script}`
83
+ })
84
+ }
85
+ }
86
+
87
+ await browserio.url(url)
88
+ }
89
+ })
package/src/job.js CHANGED
@@ -132,6 +132,7 @@ function getCommand (cwd) {
132
132
  .option('-ccf, --coverage-check-functions <percent>', '[💻🔗] What % of functions must be covered', percent, 0)
133
133
  .option('-ccl, --coverage-check-lines <percent>', '[💻🔗] What % of lines must be covered', percent, 0)
134
134
  .option('-ccs, --coverage-check-statements <percent>', '[💻🔗] What % of statements must be covered', percent, 0)
135
+ .option('-crs, --coverage-remote-scanner <path>', '[💻🔗] Scan for files when all coverage is requested', '$/scan-ui5.js')
135
136
  .option('-s, --serve-only [flag]', '[💻🔗] Serve only', boolean, false)
136
137
 
137
138
  // Specific to legacy (and might be used with url if pointing to local project)
@@ -146,8 +147,8 @@ function getCommand (cwd) {
146
147
 
147
148
  // Specific to coverage in url mode (experimental)
148
149
  .option('-cp, --coverage-proxy [flag]', `[🔗] ${EXPERIMENTAL_OPTION} use internal proxy to instrument remote files`, boolean, false)
149
- .option('-cpi, --coverage-proxy-include <regexp>', `[🔗] ${EXPERIMENTAL_OPTION} urls to instrument for coverage`, regex, regex('.*'))
150
- .option('-cpe, --coverage-proxy-exclude <regexp>', `[🔗] ${EXPERIMENTAL_OPTION} urls to ignore for coverage`, regex, regex('/((test-)?resources|tests?)/.*'))
150
+ .option('-cpi, --coverage-proxy-include <regexp>', `[🔗] ${EXPERIMENTAL_OPTION} urls to instrument for coverage`, regex, '.*')
151
+ .option('-cpe, --coverage-proxy-exclude <regexp>', `[🔗] ${EXPERIMENTAL_OPTION} urls to ignore for coverage`, regex, '/((test-)?resources|tests?)/')
151
152
 
152
153
  .addOption(new Option('--debug-probe-only', DEBUG_OPTION, boolean).hideHelp())
153
154
  .addOption(new Option('--debug-keep-browser-open', DEBUG_OPTION, boolean).hideHelp())
@@ -219,7 +220,7 @@ function finalize (job) {
219
220
  function updateToAbsolute (member, from = job.cwd) {
220
221
  job[member] = toAbsolute(job[member], from)
221
222
  }
222
- 'browser,coverageSettings,progressPage'
223
+ 'browser,coverageSettings,coverageRemoteScanner,progressPage'
223
224
  .split(',')
224
225
  .forEach(setting => { job[setting] = checkDefault(job[setting]) })
225
226
  updateToAbsolute('cwd', job.initialCwd)
@@ -299,6 +300,8 @@ function finalize (job) {
299
300
  overrideDirIfNotSet('coverageReportDir', settings['report-dir'])
300
301
  overrideDirIfNotSet('coverageTempDir', settings['temp-dir'])
301
302
  overrideIfNotSet('coverageReporters', settings.reporter)
303
+
304
+ checkAccess({ path: job.coverageRemoteScanner, label: 'coverage remote scanner', file: true })
302
305
  }
303
306
 
304
307
  if (job.mode === 'url') {
package/src/output.js CHANGED
@@ -364,7 +364,7 @@ function build (job) {
364
364
  },
365
365
 
366
366
  packageNotLatest (name, latestVersion) {
367
- wrap(() => log(job, `/!\\ latest version of ${name} is ${latestVersion}`))()
367
+ wrap(() => log(job, `⚠️ [PKGVRS] latest version of ${name} is ${latestVersion}`))()
368
368
  },
369
369
 
370
370
  browserStart (url) {
@@ -472,7 +472,15 @@ function build (job) {
472
472
  }),
473
473
 
474
474
  instrumentationSkipped: wrap(() => {
475
- log(job, p80()`Skipping nyc instrumentation (--url)`)
475
+ log(job, p80()`⚠️ [SKPNYC] Skipping nyc instrumentation (--url)`)
476
+ }),
477
+
478
+ assumingOneOrigin: wrap(() => {
479
+ log(job, p80()`⚠️ [COVORG] Considering only one origin`)
480
+ }),
481
+
482
+ noInfoForAllCoverage: wrap(() => {
483
+ log(job, p80()`⚠️ [COVALL] Unable to process all coverage, report might be incomplete`)
476
484
  }),
477
485
 
478
486
  endpointError: wrap(({ api, url, data, error }) => {
@@ -548,7 +556,7 @@ function build (job) {
548
556
  }),
549
557
 
550
558
  unhandled: wrap(() => {
551
- warn(job, p80()`Some requests are not handled properly, check the unhandled.txt report for more info`)
559
+ warn(job, p80()`⚠️ [UNHAND] Some requests are not handled properly, check the unhandled.txt report for more info`)
552
560
  }),
553
561
 
554
562
  reportGeneratorFailed: wrap((generator, exitCode, buffers) => {
package/src/reserve.js CHANGED
@@ -13,7 +13,8 @@ module.exports = async job => check({
13
13
  ...job.mappings ?? [],
14
14
  ...job.serveOnly ? [] : endpoints(job),
15
15
  ...ui5(job),
16
- ...await coverage(job), {
16
+ ...job.serveOnly ? [] : await coverage(job),
17
+ {
17
18
  // Project mapping
18
19
  match: /^\/(.*)/,
19
20
  file: join(job.webapp, '$1'),