ui5-test-runner 5.9.1 → 5.10.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/index.js +3 -4
- package/jest.config.json +1 -0
- package/package.json +9 -9
- package/src/browsers.js +5 -1
- package/src/clean.js +5 -12
- package/src/cors.js +2 -2
- package/src/coverage.js +1 -1
- package/src/defaults/puppeteer.js +11 -0
- package/src/defaults/report/decompress.js +19 -0
- package/src/defaults/report.js +27 -7
- package/src/defaults/scan-ui5.js +7 -1
- package/src/endpoints.js +32 -0
- package/src/handle.js +43 -0
- package/src/inject/jest2qunit.js +289 -0
- package/src/inject/post.js +42 -7
- package/src/inject/qunit-hooks.js +22 -15
- package/src/job.js +15 -4
- package/src/npm.js +3 -1
- package/src/output.js +55 -3
- package/src/reserve.js +1 -1
- package/src/start.js +58 -20
- package/src/tests.js +50 -8
- package/src/ui5.js +105 -102
package/src/inject/post.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const base = window['ui5-test-runner/base-host'] || ''
|
|
10
|
-
const
|
|
10
|
+
const probe = window['ui5-test-runner/probe'] || false
|
|
11
|
+
const batchSize = !probe && (window['ui5-test-runner/batch'] || 0)
|
|
11
12
|
|
|
12
13
|
let lastPost = Promise.resolve()
|
|
13
14
|
|
|
@@ -64,9 +65,10 @@
|
|
|
64
65
|
'circular:array': [].concat(value) // 'new' object
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
return
|
|
68
|
-
'circular:id': id
|
|
69
|
-
|
|
68
|
+
return {
|
|
69
|
+
'circular:id': id,
|
|
70
|
+
...value
|
|
71
|
+
}
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
return value
|
|
@@ -77,8 +79,26 @@
|
|
|
77
79
|
|
|
78
80
|
const xPageUrl = top.location.toString()
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
const nativeFetch = window.fetch
|
|
83
|
+
let request
|
|
84
|
+
if (nativeFetch) {
|
|
85
|
+
request = async function (url, data) {
|
|
86
|
+
const response = await nativeFetch(base + '/_/' + url, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: {
|
|
89
|
+
'x-page-url': xPageUrl,
|
|
90
|
+
'content-type': 'application/json'
|
|
91
|
+
},
|
|
92
|
+
body: stringify(data)
|
|
93
|
+
})
|
|
94
|
+
if (response.status !== 200) {
|
|
95
|
+
throw response.statusText
|
|
96
|
+
}
|
|
97
|
+
return response.text()
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
const XHR = window.XMLHttpRequest
|
|
101
|
+
request = function (url, data) {
|
|
82
102
|
return new Promise(function (resolve, reject) {
|
|
83
103
|
const xhr = new XHR()
|
|
84
104
|
xhr.addEventListener('load', () => {
|
|
@@ -94,7 +114,10 @@
|
|
|
94
114
|
xhr.send(json)
|
|
95
115
|
})
|
|
96
116
|
}
|
|
97
|
-
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function post (url, data) {
|
|
120
|
+
lastPost = lastPost.then(() => request(url, data))
|
|
98
121
|
if (!window.__unsafe__) {
|
|
99
122
|
lastPost = lastPost
|
|
100
123
|
.then(undefined, function (reason) {
|
|
@@ -103,4 +126,16 @@
|
|
|
103
126
|
}
|
|
104
127
|
return lastPost
|
|
105
128
|
}
|
|
129
|
+
|
|
130
|
+
const aggregatedData = []
|
|
131
|
+
|
|
132
|
+
function batch (url, data) {
|
|
133
|
+
aggregatedData.push([url, data])
|
|
134
|
+
if (url === 'QUnit/done' || aggregatedData.length === batchSize) {
|
|
135
|
+
post('QUnit/batch', [...aggregatedData])
|
|
136
|
+
aggregatedData.length = 0
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
window[MODULE] = batchSize ? batch : post
|
|
106
141
|
}())
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function installQUnitHooks () {
|
|
39
|
+
if (window !== window.top || window !== window.parent) {
|
|
40
|
+
return // Do not install in iframe
|
|
41
|
+
}
|
|
42
|
+
|
|
39
43
|
QUnit.begin(function (details) {
|
|
40
44
|
details.isOpa = isOpa()
|
|
41
45
|
return post('QUnit/begin', details)
|
|
@@ -47,21 +51,24 @@
|
|
|
47
51
|
|
|
48
52
|
QUnit.log(function (log) {
|
|
49
53
|
let ready = false
|
|
50
|
-
post('QUnit/log', extend(log))
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
const result = post('QUnit/log', extend(log))
|
|
55
|
+
if (result && result.then) {
|
|
56
|
+
result
|
|
57
|
+
.then(undefined, function () {
|
|
58
|
+
console.error('Failed to POST to QUnit/log (no timestamp)', log)
|
|
59
|
+
})
|
|
60
|
+
.then(function () {
|
|
61
|
+
ready = true
|
|
62
|
+
})
|
|
63
|
+
if (isOpa()) {
|
|
64
|
+
window.sap.ui.test.Opa5.prototype.waitFor({
|
|
65
|
+
timeout: 10,
|
|
66
|
+
autoWait: false, // Ignore interactable constraint
|
|
67
|
+
check: function () {
|
|
68
|
+
return ready
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
}
|
|
65
72
|
}
|
|
66
73
|
})
|
|
67
74
|
|
package/src/job.js
CHANGED
|
@@ -114,6 +114,8 @@ function getCommand (cwd) {
|
|
|
114
114
|
.option('--env <name=value...>', '[💻🔗🧪📡] Set environment variable', arrayOf(string))
|
|
115
115
|
.option('--localhost <host>', `[💻🔗🧪📡] ${DANGEROUS_OPTION} Hostname for legacy URLs and callbacks`, string, 'localhost')
|
|
116
116
|
.option('--ci [flag]', '[💻🔗🧪📡] CI mode (no interactive output)', boolean, false)
|
|
117
|
+
.option('--deep-probe [flag]', '[💻🔗🧪📡] Deep probe (recursive, slower)', boolean, false)
|
|
118
|
+
.option('--probe-parallel <count>', '[💻🔗🧪📡] Number of parallel probes (0 to use --parallel)', integer, 0)
|
|
117
119
|
|
|
118
120
|
// Common to legacy and url
|
|
119
121
|
.option('--webapp <path>', '[💻🔗] Base folder of the web application (relative to cwd)', 'webapp')
|
|
@@ -128,6 +130,8 @@ function getCommand (cwd) {
|
|
|
128
130
|
.option('-so, --split-opa [flag]', '[💻🔗📡] Split OPA tests using QUnit modules', boolean, false)
|
|
129
131
|
.option('-rg, --report-generator <path...>', '[💻🔗📡] Report generator paths (relative to cwd or use $/ for provided ones)', ['$/report.js'])
|
|
130
132
|
.option('--progress-page <path>', '[💻🔗📡] Progress page path (relative to cwd or use $/ for provided ones)', '$/report/default.html')
|
|
133
|
+
.option('--jest [flag]', `[💻🔗📡] ${EXPERIMENTAL_OPTION} Simulate jest environment`)
|
|
134
|
+
.option('--qunit-batch-size <size>', `[💻🔗📡] ${EXPERIMENTAL_OPTION} QUnit hooks batch size (disables screenshots)`, integer, 0)
|
|
131
135
|
|
|
132
136
|
.option('--coverage [flag]', '[💻🔗📡] Enable or disable code coverage', boolean)
|
|
133
137
|
.option('--no-coverage', '[💻🔗📡] Disable code coverage')
|
|
@@ -145,10 +149,11 @@ function getCommand (cwd) {
|
|
|
145
149
|
.option('-w, --watch [flag]', '[💻🔗] Monitor the webapp folder (or the one specified with --watch-folder) and re-execute tests on change', boolean, false)
|
|
146
150
|
.option('--watch-folder <path>', '[💻🔗] Folder to monitor with watch (enables --watch if not specified)', string)
|
|
147
151
|
|
|
148
|
-
.option('--start <command>', '[💻🔗] Start command (might be an NPM script or a shell command)', string)
|
|
152
|
+
.option('--start <command>', '[💻🔗] Start command (might be an NPM script or a shell command) ⚠️ the command is killed on tests completion', string)
|
|
149
153
|
.option('--start-wait-url <command>', '[💻🔗] URL to wait for (🔗 defaulted to first url)', url)
|
|
150
154
|
.option('--start-wait-method <method>', '[💻🔗] HTTP method to check the waited URL', 'GET')
|
|
151
|
-
|
|
155
|
+
|
|
156
|
+
.option('--start-timeout <timeout>', '[💻🔗] Maximum waiting time for the start command (based on when the first URL becomes available, also used for termination)', timeout, 5000)
|
|
152
157
|
|
|
153
158
|
.option('--end <script>', '[💻🔗] End script (will receive path to `job.js`)', string)
|
|
154
159
|
.option('--end-timeout <timeout>', '[💻🔗] Maximum waiting time for the end script', timeout, 15000)
|
|
@@ -178,6 +183,7 @@ function getCommand (cwd) {
|
|
|
178
183
|
.addOption(new Option('--debug-probe-only', DEBUG_OPTION, boolean).hideHelp())
|
|
179
184
|
.addOption(new Option('--debug-keep-browser-open', DEBUG_OPTION, boolean).hideHelp())
|
|
180
185
|
.addOption(new Option('--debug-memory', DEBUG_OPTION, boolean).hideHelp())
|
|
186
|
+
.addOption(new Option('--debug-handles', DEBUG_OPTION, boolean).hideHelp())
|
|
181
187
|
.addOption(new Option('--debug-keep-report', DEBUG_OPTION, boolean).hideHelp())
|
|
182
188
|
.addOption(new Option('--debug-capabilities-test <name>', DEBUG_OPTION).hideHelp())
|
|
183
189
|
.addOption(new Option('--debug-capabilities-no-timeout', DEBUG_OPTION, boolean).hideHelp())
|
|
@@ -214,7 +220,7 @@ function checkAccess ({ path, label, file /*, write */ }) {
|
|
|
214
220
|
// }
|
|
215
221
|
accessSync(path, mode)
|
|
216
222
|
} catch (error) {
|
|
217
|
-
throw new Error(`Unable to access ${label}, check your settings`)
|
|
223
|
+
throw new Error(`Unable to access ${label || path}, check your settings`)
|
|
218
224
|
}
|
|
219
225
|
const stat = statSync(path)
|
|
220
226
|
if (file) {
|
|
@@ -361,13 +367,18 @@ function finalize (job) {
|
|
|
361
367
|
|
|
362
368
|
if (job.mode === 'url') {
|
|
363
369
|
const port = job.port.toString()
|
|
364
|
-
job[$remoteOnLegacy] = job.url.every(url => {
|
|
370
|
+
job[$remoteOnLegacy] = job.url && job.url.every(url => {
|
|
365
371
|
// ignore host name since the machine might be exposed with any name
|
|
366
372
|
const parsedUrl = new URL(url)
|
|
367
373
|
return parsedUrl.port === port
|
|
368
374
|
})
|
|
369
375
|
}
|
|
370
376
|
|
|
377
|
+
if (job.qunitBatchSize) {
|
|
378
|
+
job.screenshot = false
|
|
379
|
+
job.screenshotOnFailure = false
|
|
380
|
+
}
|
|
381
|
+
|
|
371
382
|
job[$status] = 'Starting'
|
|
372
383
|
Object.defineProperty(job, 'status', {
|
|
373
384
|
get () {
|
package/src/npm.js
CHANGED
package/src/output.js
CHANGED
|
@@ -9,6 +9,8 @@ const {
|
|
|
9
9
|
$statusProgressTotal
|
|
10
10
|
} = require('./symbols')
|
|
11
11
|
const { filename, noop, pad } = require('./tools')
|
|
12
|
+
const os = require('os')
|
|
13
|
+
const { describeHandle } = require('./handle')
|
|
12
14
|
|
|
13
15
|
const $output = Symbol('output')
|
|
14
16
|
const $outputStart = Symbol('output-start')
|
|
@@ -134,6 +136,22 @@ function progress (job, cleanFirst = true) {
|
|
|
134
136
|
const fmt = size => `${(size / (1024 * 1024)).toFixed(2)}M`
|
|
135
137
|
sequence.push(`MEM r:${fmt(rss)}, h:${fmt(heapUsed)}/${fmt(heapTotal)}, x:${fmt(external)}, a:${fmt(arrayBuffers)}\n`)
|
|
136
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
|
+
}
|
|
137
155
|
if (job[$outputProgress]) {
|
|
138
156
|
output.lines += job[$outputProgress].length
|
|
139
157
|
job[$outputProgress].forEach(({ count, total, label }) => {
|
|
@@ -270,7 +288,24 @@ function build (job) {
|
|
|
270
288
|
|
|
271
289
|
version: wrap(() => {
|
|
272
290
|
const { name, version = 'dev' } = require(join(__dirname, '../package.json'))
|
|
273
|
-
log(job, p80()
|
|
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
|
+
}
|
|
274
309
|
if (job.debugDevMode) {
|
|
275
310
|
log(job, p80()`⚠️ Development mode ⚠️`)
|
|
276
311
|
}
|
|
@@ -422,7 +457,7 @@ function build (job) {
|
|
|
422
457
|
},
|
|
423
458
|
|
|
424
459
|
packageNotLatest (name, latestVersion) {
|
|
425
|
-
wrap(() => log(job, `⚠️ [PKGVRS]
|
|
460
|
+
wrap(() => log(job, `⚠️ [PKGVRS] Latest version of ${name} is ${latestVersion}`))()
|
|
426
461
|
},
|
|
427
462
|
|
|
428
463
|
emptyBrowserArg () {
|
|
@@ -430,7 +465,11 @@ function build (job) {
|
|
|
430
465
|
},
|
|
431
466
|
|
|
432
467
|
detectedLeakOfHandles () {
|
|
433
|
-
wrap(() => log(job, '⚠️ [HDLEAK]
|
|
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 terminate start command. This may cause issues with the shutdown'))()
|
|
434
473
|
},
|
|
435
474
|
|
|
436
475
|
browserStart (url) {
|
|
@@ -476,6 +515,10 @@ function build (job) {
|
|
|
476
515
|
browserIssue(job, { type: 'failed', url, code, dir })
|
|
477
516
|
}),
|
|
478
517
|
|
|
518
|
+
browserChildProcessError: wrap((url, { code }) => {
|
|
519
|
+
log(job, p80()`⚠️ [BRWCPE] Child process error ${code}: ${pad.lt(url)}`)
|
|
520
|
+
}),
|
|
521
|
+
|
|
479
522
|
skipIf: wrap(() => {
|
|
480
523
|
log(job, p80()`⚠️ [SKIPIF] Skipping execution (--if)`)
|
|
481
524
|
}),
|
|
@@ -640,6 +683,15 @@ function build (job) {
|
|
|
640
683
|
} else {
|
|
641
684
|
log(job, p`│ ${pad.w(error.toString())} │`)
|
|
642
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
|
+
}
|
|
643
695
|
log(job, p`└──────────${pad.x('─')}┘`)
|
|
644
696
|
}),
|
|
645
697
|
|
package/src/reserve.js
CHANGED
package/src/start.js
CHANGED
|
@@ -2,9 +2,7 @@ const { exec } = require('child_process')
|
|
|
2
2
|
const { stat, readFile } = require('fs/promises')
|
|
3
3
|
const { join } = require('path')
|
|
4
4
|
const { getOutput } = require('./output')
|
|
5
|
-
const
|
|
6
|
-
const { promisify } = require('util')
|
|
7
|
-
const psTree = promisify(psTreeNodeCb)
|
|
5
|
+
const pidtree = require('pidtree')
|
|
8
6
|
|
|
9
7
|
async function start (job) {
|
|
10
8
|
const { startWaitUrl: url, startWaitMethod: method } = job
|
|
@@ -40,23 +38,23 @@ async function start (job) {
|
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
let
|
|
41
|
+
let startProcessExited = false
|
|
44
42
|
output.debug('start', 'Starting command :', start)
|
|
45
|
-
const
|
|
43
|
+
const startProcess = exec(start, {
|
|
46
44
|
cwd: job.cwd,
|
|
47
45
|
windowsHide: true
|
|
48
46
|
})
|
|
49
|
-
|
|
50
|
-
output.debug('start', '
|
|
51
|
-
|
|
47
|
+
startProcess.on('close', () => {
|
|
48
|
+
output.debug('start', 'Start command process exited')
|
|
49
|
+
startProcessExited = true
|
|
52
50
|
})
|
|
53
|
-
output.monitor(
|
|
51
|
+
output.monitor(startProcess)
|
|
54
52
|
|
|
55
53
|
job.status = 'Waiting for URL to be reachable'
|
|
56
54
|
|
|
57
55
|
const begin = Date.now()
|
|
58
56
|
// eslint-disable-next-line no-unmodified-loop-condition
|
|
59
|
-
while (!
|
|
57
|
+
while (!startProcessExited && Date.now() - begin <= job.startTimeout) {
|
|
60
58
|
try {
|
|
61
59
|
const response = await fetch(url, { method })
|
|
62
60
|
output.debug('start', url, response.status)
|
|
@@ -69,20 +67,60 @@ async function start (job) {
|
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
if (
|
|
73
|
-
throw new Error(`Start command failed with exit code ${
|
|
70
|
+
if (startProcessExited) {
|
|
71
|
+
throw new Error(`Start command failed with exit code ${startProcess.exitCode}`)
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
const stop = async () => {
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
job.status = 'Terminating start command'
|
|
76
|
+
const begin = new Date()
|
|
77
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
78
|
+
while (!startProcessExited && Date.now() - begin <= job.startTimeout) {
|
|
79
|
+
output.debug('start', `Getting start command ${startProcess.pid} child processes...`)
|
|
80
|
+
const childProcesses = await pidtree(startProcess.pid, { advanced: true })
|
|
81
|
+
output.debug('start', 'Child processes', JSON.stringify(childProcesses))
|
|
82
|
+
if (childProcesses.length === 0) {
|
|
83
|
+
try {
|
|
84
|
+
output.debug('start', 'Terminating start command')
|
|
85
|
+
process.kill(startProcess.pid, 'SIGKILL')
|
|
86
|
+
} catch (e) {
|
|
87
|
+
output.debug('start', 'Failed to terminate start command', startProcess.pid, ':', e)
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
const depth = {}
|
|
91
|
+
let deepest = 1
|
|
92
|
+
let deepless = childProcesses.length
|
|
93
|
+
while (deepless > 0) {
|
|
94
|
+
for (const { ppid, pid } of childProcesses) {
|
|
95
|
+
if (ppid === startProcess.pid) {
|
|
96
|
+
depth[pid] = 1
|
|
97
|
+
--deepless
|
|
98
|
+
} else {
|
|
99
|
+
const parentDepth = depth[ppid]
|
|
100
|
+
if (parentDepth !== undefined) {
|
|
101
|
+
depth[pid] = parentDepth + 1
|
|
102
|
+
deepest = Math.max(deepest, parentDepth + 1)
|
|
103
|
+
--deepless
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
output.debug('start', 'Child processes', JSON.stringify(depth), 'terminating', deepest)
|
|
109
|
+
for (const { pid } of childProcesses) {
|
|
110
|
+
if (depth[pid] === deepest) {
|
|
111
|
+
output.debug('start', 'Terminating start child process', pid)
|
|
112
|
+
try {
|
|
113
|
+
process.kill(pid, 'SIGKILL')
|
|
114
|
+
} catch (e) {
|
|
115
|
+
output.debug('start', 'Failed to terminate start child process', pid, ':', e)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
85
119
|
}
|
|
120
|
+
await new Promise(resolve => setTimeout(resolve, 250))
|
|
121
|
+
}
|
|
122
|
+
if (!startProcessExited) {
|
|
123
|
+
output.failedToTerminateStartCommand()
|
|
86
124
|
}
|
|
87
125
|
}
|
|
88
126
|
|
package/src/tests.js
CHANGED
|
@@ -48,9 +48,13 @@ async function probeUrl (job, url) {
|
|
|
48
48
|
let scripts
|
|
49
49
|
if (job.browserCapabilities.scripts) {
|
|
50
50
|
scripts = [
|
|
51
|
+
'(function () { window[\'ui5-test-runner/probe\'] = true }())',
|
|
51
52
|
'post.js',
|
|
52
53
|
'qunit-redirect.js'
|
|
53
54
|
]
|
|
55
|
+
if (job.jest) {
|
|
56
|
+
scripts.push('jest2qunit.js')
|
|
57
|
+
}
|
|
54
58
|
}
|
|
55
59
|
await start(job, url, scripts)
|
|
56
60
|
} catch (error) {
|
|
@@ -64,10 +68,19 @@ async function runTestPage (job, url) {
|
|
|
64
68
|
try {
|
|
65
69
|
let scripts
|
|
66
70
|
if (job.browserCapabilities.scripts) {
|
|
67
|
-
scripts = [
|
|
71
|
+
scripts = []
|
|
72
|
+
if (job.qunitBatchSize) {
|
|
73
|
+
scripts.push(
|
|
74
|
+
`(function () { window['ui5-test-runner/batch'] = ${job.qunitBatchSize} }())`
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
scripts.push(
|
|
68
78
|
'post.js',
|
|
69
79
|
'qunit-hooks.js'
|
|
70
|
-
|
|
80
|
+
)
|
|
81
|
+
if (job.jest) {
|
|
82
|
+
scripts.push('jest2qunit.js')
|
|
83
|
+
}
|
|
71
84
|
if (job.coverage && !job.coverageProxy) {
|
|
72
85
|
scripts.push(
|
|
73
86
|
'opa-iframe-coverage.js',
|
|
@@ -102,13 +115,42 @@ async function process (job) {
|
|
|
102
115
|
await save(job)
|
|
103
116
|
job.testPageUrls = []
|
|
104
117
|
|
|
118
|
+
let probingRound = 0
|
|
119
|
+
const parallel = job.probeParallel || job.parallel
|
|
120
|
+
const confirmedTestPageUrls = []
|
|
105
121
|
job.status = 'Probing urls'
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
do {
|
|
123
|
+
++probingRound
|
|
124
|
+
if (probingRound >= 2) {
|
|
125
|
+
if (job.testPageUrls.length === 0) {
|
|
126
|
+
break
|
|
127
|
+
}
|
|
128
|
+
job.status = `Probing urls (${probingRound})`
|
|
129
|
+
job.url = job.testPageUrls.filter(url => !confirmedTestPageUrls.includes(url))
|
|
130
|
+
if (job.url.length) {
|
|
131
|
+
job.testPageUrls = []
|
|
132
|
+
} else {
|
|
133
|
+
job.testPageUrls = confirmedTestPageUrls
|
|
134
|
+
break
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
await parallelize(task(job, probeUrl), job.url, parallel)
|
|
139
|
+
} catch (e) {
|
|
140
|
+
output.genericError(e)
|
|
141
|
+
job.failed = true
|
|
142
|
+
break
|
|
143
|
+
}
|
|
144
|
+
job.testPageUrls.forEach(url => {
|
|
145
|
+
if ((job.url.includes(url) && !confirmedTestPageUrls.includes(url)) ||
|
|
146
|
+
(url.includes('/resources/sap/ui/test/starter/Test.qunit.html?testsuite=') && url.includes('&test='))
|
|
147
|
+
) {
|
|
148
|
+
confirmedTestPageUrls.push(url)
|
|
149
|
+
getOutput(job).debug('probe', 'confirmed:', url)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
getOutput(job).debug('probe', 'from', job.url.length, 'to', job.testPageUrls.length, 'confirmed', confirmedTestPageUrls.length)
|
|
153
|
+
} while (job.deepProbe)
|
|
112
154
|
|
|
113
155
|
/* istanbul ignore else */
|
|
114
156
|
if (!job.debugProbeOnly && !job.failed) {
|