ui5-test-runner 6.0.0-beta.4 → 6.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 +20 -29
- package/dist/Command.js +52 -0
- package/dist/Npm.js +193 -43
- package/dist/browsers/RecoverableBrowserError.js +6 -0
- package/dist/browsers/chromeArguments.js +5 -0
- package/dist/browsers/chromeOptions.js +29 -0
- package/dist/browsers/consoleMessage.js +23 -0
- package/dist/browsers/factory.js +169 -4
- package/dist/browsers/networkResponse.js +15 -0
- package/dist/browsers/playwright.js +104 -0
- package/dist/browsers/puppeteer.js +55 -89
- package/dist/browsers/seleniumWebdriver.js +124 -0
- package/dist/browsers/webdriverio.js +85 -0
- package/dist/cli.js +18 -12
- package/dist/configuration/CommandLine.js +46 -26
- package/dist/configuration/ConfigurationValidator.js +132 -18
- package/dist/configuration/OptionValidationError.js +50 -2
- package/dist/configuration/derivations.js +8 -0
- package/dist/configuration/options.js +392 -23
- package/dist/configuration/validations.js +135 -0
- package/dist/configuration/validators/boolean.js +1 -1
- package/dist/configuration/validators/enumeration.js +7 -0
- package/dist/configuration/validators/fsEntry.js +12 -12
- package/dist/configuration/validators/index.js +8 -2
- package/dist/configuration/validators/integer.js +7 -1
- package/dist/configuration/validators/json.js +23 -0
- package/dist/configuration/validators/libraryMapping.js +28 -0
- package/dist/configuration/validators/percent.js +2 -2
- package/dist/configuration/validators/regexp.js +2 -2
- package/dist/configuration/validators/secret.js +8 -0
- package/dist/configuration/validators/string.js +1 -1
- package/dist/configuration/validators/timeout.js +2 -2
- package/dist/configuration/validators/url.js +3 -3
- package/dist/end.js +58 -0
- package/dist/if.js +22 -0
- package/dist/modes/Modes.js +2 -1
- package/dist/modes/batch/BatchItem.js +1 -0
- package/dist/modes/batch/batchTask.js +159 -0
- package/dist/modes/batch/index.js +98 -0
- package/dist/modes/batch/output.js +22 -0
- package/dist/modes/batch/report.js +45 -0
- package/dist/modes/batch/resolve.js +105 -0
- package/dist/modes/dumpConfig.js +6 -0
- package/dist/modes/execute.js +6 -5
- package/dist/modes/help.js +86 -2
- package/dist/modes/log/LogReader.js +3 -2
- package/dist/modes/log/LogStorage.js +31 -27
- package/dist/modes/log/index.js +39 -7
- package/dist/modes/log/{REserve.js → reserve.js} +25 -2
- package/dist/modes/mcp/IDocument.js +2 -0
- package/dist/modes/mcp/frontmatter.js +142 -0
- package/dist/modes/mcp/index.js +49 -0
- package/dist/modes/mcp/knowledgeBase.js +104 -0
- package/dist/modes/mcp/remoteKnowledgeBase.js +79 -0
- package/dist/modes/mcp/reserve.js +175 -0
- package/dist/modes/mcp/tools/getTopic.js +46 -0
- package/dist/modes/mcp/tools/index.js +6 -0
- package/dist/modes/mcp/tools/listTopics.js +14 -0
- package/dist/modes/test/PageContext.js +1 -0
- package/dist/modes/test/Server.js +99 -0
- package/dist/modes/test/browser.js +31 -17
- package/dist/modes/test/browserConfig.js +17 -0
- package/dist/modes/test/coverage/collect.js +38 -0
- package/dist/modes/test/coverage/index.js +3 -0
- package/dist/modes/test/coverage/instrument.js +70 -0
- package/dist/modes/test/coverage/nyc.js +15 -0
- package/dist/modes/test/coverage/report.js +71 -0
- package/dist/modes/test/coverage/settings.js +53 -0
- package/dist/modes/test/index.js +94 -34
- package/dist/modes/test/pageTask.js +293 -98
- package/dist/modes/test/report.js +20 -3
- package/dist/modes/test/reserve.js +76 -0
- package/dist/modes/test/screenshot.js +49 -0
- package/dist/platform/Crypto.js +9 -0
- package/dist/platform/Exit.js +33 -24
- package/dist/platform/FileSystem.js +6 -2
- package/dist/platform/Host.js +9 -1
- package/dist/platform/Http.js +54 -29
- package/dist/platform/Module.js +5 -0
- package/dist/platform/Path.js +5 -1
- package/dist/platform/Process.js +67 -13
- package/dist/platform/Terminal.js +12 -8
- package/dist/platform/Thread.js +1 -1
- package/dist/platform/Url.js +4 -0
- package/dist/platform/assert.js +13 -12
- package/dist/platform/environment.js +9 -18
- package/dist/platform/index.js +3 -0
- package/dist/platform/logger/CompressionContext.js +117 -0
- package/dist/platform/logger/allCompressed.js +8 -7
- package/dist/platform/logger/compress.js +29 -129
- package/dist/platform/logger/output/BaseLoggerOutput.js +49 -31
- package/dist/platform/logger/output/InteractiveLoggerOutput.js +1 -1
- package/dist/platform/logger/output/LlmLoggerOutput.js +29 -0
- package/dist/platform/logger/output/factory.js +5 -1
- package/dist/platform/logger/output.js +24 -6
- package/dist/platform/logger/toInternalLogAttributes.js +10 -11
- package/dist/platform/logger/traceFileName.js +1 -0
- package/dist/platform/logger.js +52 -21
- package/dist/platform/mock.js +124 -27
- package/dist/platform/version.js +1 -2
- package/dist/platform/workerBootstrap.js +1 -1
- package/dist/reports/initReportBuilder.js +18 -0
- package/dist/reports/junit.js +64 -0
- package/dist/reports/saveReport.js +10 -0
- package/dist/reports/textReport.js +92 -0
- package/dist/reserveLogger.js +22 -0
- package/dist/sendToParentProcess.js +6 -0
- package/dist/start.js +79 -0
- package/dist/types/ISecretValue.js +1 -0
- package/dist/types/SecretValue.js +15 -0
- package/dist/ui/agent.js +4 -2
- package/dist/ui/html-report.js +2 -2
- package/dist/ui/lib.js +1 -1
- package/dist/ui/log-viewer.js +1 -1
- package/dist/utils/node/Folder.js +2 -4
- package/dist/utils/node/FramedStreamReader.js +4 -5
- package/dist/utils/node/FramedStreamWriter.js +6 -5
- package/dist/utils/node/anonymize.js +11 -0
- package/dist/utils/node/timeout.js +11 -0
- package/dist/utils/shared/ProgressBar.js +1 -2
- package/dist/utils/shared/TestReportBuilder.js +11 -7
- package/dist/utils/shared/host.js +11 -0
- package/dist/utils/shared/object.js +12 -3
- package/dist/utils/shared/schema.js +20 -0
- package/dist/utils/shared/string.js +1 -0
- package/dist/utils/shared/toIError.js +3 -7
- package/dist/utils/shared/version.js +52 -0
- package/package.json +2 -78
- package/dist/configuration/validators/browser.js +0 -11
- package/dist/modes/test/REserve.js +0 -31
- package/dist/modes/test/server.js +0 -109
|
@@ -4,6 +4,7 @@ export const options = [
|
|
|
4
4
|
short: 'c',
|
|
5
5
|
type: 'fs-entry',
|
|
6
6
|
description: 'set working directory',
|
|
7
|
+
defaultLabel: 'current working directory',
|
|
7
8
|
default: process.cwd()
|
|
8
9
|
},
|
|
9
10
|
{
|
|
@@ -19,26 +20,131 @@ export const options = [
|
|
|
19
20
|
description: 'path of the testsuite file',
|
|
20
21
|
default: 'test/testsuite.qunit.html'
|
|
21
22
|
},
|
|
23
|
+
{
|
|
24
|
+
name: 'agentDetectionInterval',
|
|
25
|
+
type: 'timeout',
|
|
26
|
+
browserExposed: true,
|
|
27
|
+
description: 'initial polling interval when detecting a test framework after page load',
|
|
28
|
+
default: 100
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'agentDetectionMaxInterval',
|
|
32
|
+
type: 'timeout',
|
|
33
|
+
browserExposed: true,
|
|
34
|
+
description: 'maximum polling interval when detecting a test framework after page load',
|
|
35
|
+
default: 1000
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'agentDetectionTimeout',
|
|
39
|
+
type: 'timeout',
|
|
40
|
+
browserExposed: true,
|
|
41
|
+
description: 'maximum time to wait for a test framework to be detected after page load',
|
|
42
|
+
default: 5000
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'agentNoTestsTimeout',
|
|
46
|
+
type: 'timeout',
|
|
47
|
+
browserExposed: true,
|
|
48
|
+
description: 'time to wait after QUnit.done fires with no tests before declaring the page done',
|
|
49
|
+
default: 5000
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'agentScreenshotTimeout',
|
|
53
|
+
type: 'timeout',
|
|
54
|
+
browserExposed: true,
|
|
55
|
+
description: 'maximum time OPA waits for a pending screenshot before continuing',
|
|
56
|
+
default: 10_000
|
|
57
|
+
},
|
|
22
58
|
{
|
|
23
59
|
name: 'alternateNpmPath',
|
|
24
60
|
type: 'fs-entry',
|
|
25
|
-
|
|
61
|
+
batchForwarded: true,
|
|
62
|
+
description: 'additional path the runner searches for npm packages after the local and global locations'
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'batch',
|
|
66
|
+
type: 'string',
|
|
67
|
+
multiple: true,
|
|
68
|
+
description: 'batch item specification (folder, config file, or regex pattern)'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'batchId',
|
|
72
|
+
type: 'string',
|
|
73
|
+
description: 'identifier for the batch item'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'batchLabel',
|
|
77
|
+
type: 'string',
|
|
78
|
+
description: 'display label for the batch item'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'batchOutput',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
description: 'print output.txt for every batch item after execution, in alphabetical batch-id order'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'batchTimeout',
|
|
87
|
+
short: 'bt',
|
|
88
|
+
type: 'timeout',
|
|
89
|
+
description: 'fails a batch item if it takes longer than this timeout'
|
|
26
90
|
},
|
|
27
91
|
{
|
|
28
92
|
name: 'browser',
|
|
29
93
|
short: 'b',
|
|
30
|
-
type: '
|
|
31
|
-
|
|
32
|
-
|
|
94
|
+
type: 'enumeration',
|
|
95
|
+
typeModifiers: new Set(['chrome', 'chromium', 'firefox', 'webkit', 'edge', 'safari']),
|
|
96
|
+
batchForwarded: true,
|
|
97
|
+
description: 'browser selection (per driver)'
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'browserBasicAuthPassword',
|
|
101
|
+
type: 'secret',
|
|
102
|
+
description: 'password for HTTP basic authentication'
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'browserBasicAuthUsername',
|
|
106
|
+
type: 'string',
|
|
107
|
+
description: 'username for HTTP basic authentication'
|
|
33
108
|
},
|
|
34
109
|
{
|
|
35
|
-
name: '
|
|
110
|
+
name: 'browserDevice',
|
|
111
|
+
type: 'string',
|
|
112
|
+
batchForwarded: true,
|
|
113
|
+
description: 'emulate a Puppeteer-known device — sets the viewport, user agent, and touch support, overriding browser viewport width and height'
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'browserOptions',
|
|
117
|
+
type: 'json',
|
|
118
|
+
batchForwarded: true,
|
|
119
|
+
description: 'browser-specific options (JSON)',
|
|
120
|
+
default: {}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'browserViewportHeight',
|
|
124
|
+
short: 'H',
|
|
125
|
+
type: 'integer',
|
|
126
|
+
typeModifiers: new Set(['positive', 'non-zero']),
|
|
127
|
+
description: 'height of the browser viewport in pixels',
|
|
128
|
+
default: 1080
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'browserViewportWidth',
|
|
132
|
+
short: 'W',
|
|
133
|
+
type: 'integer',
|
|
134
|
+
typeModifiers: new Set(['positive', 'non-zero']),
|
|
135
|
+
description: 'width of the browser viewport in pixels',
|
|
136
|
+
default: 1920
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'browserVisible',
|
|
140
|
+
short: 'V',
|
|
36
141
|
type: 'boolean',
|
|
37
|
-
description: '
|
|
142
|
+
description: 'control if the browser should be visible during the tests'
|
|
38
143
|
},
|
|
39
144
|
{
|
|
40
145
|
name: 'ci',
|
|
41
146
|
type: 'boolean',
|
|
147
|
+
batchForwarded: true,
|
|
42
148
|
description: 'forces CI mode (no interactive output)',
|
|
43
149
|
default: !process.stdout.isTTY
|
|
44
150
|
},
|
|
@@ -49,21 +155,137 @@ export const options = [
|
|
|
49
155
|
description: 'read options from a configuration file',
|
|
50
156
|
default: 'ui5-test-runner.json'
|
|
51
157
|
},
|
|
158
|
+
{
|
|
159
|
+
name: 'coverage',
|
|
160
|
+
type: 'boolean',
|
|
161
|
+
description: 'enable code coverage'
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'coverageCheckBranches',
|
|
165
|
+
short: 'ccb',
|
|
166
|
+
type: 'percent',
|
|
167
|
+
description: 'minimum branch coverage threshold (0 = no check)',
|
|
168
|
+
default: 0
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'coverageCheckFunctions',
|
|
172
|
+
short: 'ccf',
|
|
173
|
+
type: 'percent',
|
|
174
|
+
description: 'minimum function coverage threshold (0 = no check)',
|
|
175
|
+
default: 0
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'coverageCheckLines',
|
|
179
|
+
short: 'ccl',
|
|
180
|
+
type: 'percent',
|
|
181
|
+
description: 'minimum line coverage threshold (0 = no check)',
|
|
182
|
+
default: 0
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: 'coverageCheckStatements',
|
|
186
|
+
short: 'ccs',
|
|
187
|
+
type: 'percent',
|
|
188
|
+
description: 'minimum statement coverage threshold (0 = no check)',
|
|
189
|
+
default: 0
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'coverageRemoteInstrument',
|
|
193
|
+
type: 'regexp',
|
|
194
|
+
multiple: true,
|
|
195
|
+
browserExposed: true,
|
|
196
|
+
description: 'resources sub-paths to instrument for coverage in remote mode'
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'coverageReportDir',
|
|
200
|
+
short: 'crd',
|
|
201
|
+
type: 'fs-entry',
|
|
202
|
+
typeModifiers: new Set(['overwrite']),
|
|
203
|
+
description: 'directory for the final coverage report',
|
|
204
|
+
default: 'coverage'
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'coverageReporters',
|
|
208
|
+
short: 'cr',
|
|
209
|
+
type: 'string',
|
|
210
|
+
multiple: true,
|
|
211
|
+
description: 'istanbul-lib-report reporters to use',
|
|
212
|
+
default: ['lcov', 'cobertura']
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: 'coverageSettings',
|
|
216
|
+
short: 'cs',
|
|
217
|
+
type: 'fs-entry',
|
|
218
|
+
typeModifiers: new Set(['file', 'safe-default']),
|
|
219
|
+
description: 'path to the Istanbul configuration file (.nycrc.json)',
|
|
220
|
+
default: '.nycrc.json'
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'coverageSourceDir',
|
|
224
|
+
type: 'fs-entry',
|
|
225
|
+
typeModifiers: new Set(['safe-default']),
|
|
226
|
+
description: 'directory containing the source files used for coverage reporting'
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
name: 'coverageTempDir',
|
|
230
|
+
short: 'ctd',
|
|
231
|
+
type: 'fs-entry',
|
|
232
|
+
typeModifiers: new Set(['overwrite']),
|
|
233
|
+
description: 'temporary directory for coverage data',
|
|
234
|
+
default: '.nyc_output'
|
|
235
|
+
},
|
|
52
236
|
{
|
|
53
237
|
name: 'debugKeepBrowserOpen',
|
|
54
238
|
type: 'boolean',
|
|
55
239
|
description: 'keeps the browser open after the tests completed'
|
|
56
240
|
},
|
|
241
|
+
{
|
|
242
|
+
name: 'debugLog',
|
|
243
|
+
type: 'string',
|
|
244
|
+
multiple: true,
|
|
245
|
+
description: 'output debug logs for given sources'
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'debugMcpLocalDocs',
|
|
249
|
+
type: 'boolean',
|
|
250
|
+
description: 'use local docs/ directory instead of fetching from GitHub (development only)'
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'driver',
|
|
254
|
+
short: 'd',
|
|
255
|
+
type: 'enumeration',
|
|
256
|
+
typeModifiers: new Set(['puppeteer', 'playwright', 'webdriverio', 'selenium-webdriver']),
|
|
257
|
+
browserExposed: true,
|
|
258
|
+
batchForwarded: true,
|
|
259
|
+
description: 'driver selection',
|
|
260
|
+
default: 'puppeteer'
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'dumpConfig',
|
|
264
|
+
type: 'boolean',
|
|
265
|
+
description: 'dump the resolved configuration as JSON and exit'
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: 'end',
|
|
269
|
+
type: 'string',
|
|
270
|
+
description: 'command to be executed after the tests'
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: 'endTimeout',
|
|
274
|
+
type: 'timeout',
|
|
275
|
+
description: 'maximum waiting time for the end command to execute'
|
|
276
|
+
},
|
|
57
277
|
{
|
|
58
278
|
name: 'failFast',
|
|
59
279
|
short: 'f',
|
|
60
280
|
type: 'boolean',
|
|
281
|
+
batchForwarded: true,
|
|
61
282
|
description: 'stop the whole execution after the first failing page'
|
|
62
283
|
},
|
|
63
284
|
{
|
|
64
285
|
name: 'failOpaFast',
|
|
65
286
|
short: 'fo',
|
|
66
287
|
type: 'boolean',
|
|
288
|
+
batchForwarded: true,
|
|
67
289
|
description: 'stop the OPA page execution after the first failing test'
|
|
68
290
|
},
|
|
69
291
|
{
|
|
@@ -75,41 +297,94 @@ export const options = [
|
|
|
75
297
|
{
|
|
76
298
|
name: 'help',
|
|
77
299
|
type: 'boolean',
|
|
78
|
-
description: 'display
|
|
300
|
+
description: 'display the list of available options and exit'
|
|
79
301
|
},
|
|
80
302
|
{
|
|
81
|
-
name: '
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
description: 'keep the server alive'
|
|
303
|
+
name: 'if',
|
|
304
|
+
type: 'string',
|
|
305
|
+
description: 'skip execution if the expression evaluates to falsy'
|
|
85
306
|
},
|
|
86
307
|
{
|
|
87
|
-
name: '
|
|
308
|
+
name: 'junitXmlFilename',
|
|
88
309
|
type: 'string',
|
|
89
|
-
description: '
|
|
90
|
-
default: '
|
|
310
|
+
description: 'filename for the JUnit XML report saved in the report directory',
|
|
311
|
+
default: 'junit.xml'
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: 'lib',
|
|
315
|
+
type: 'library-mapping',
|
|
316
|
+
multiple: true,
|
|
317
|
+
description: 'map a UI5 resources sub-folder to a local source folder, used in legacy mode to serve custom libraries'
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: 'llm',
|
|
321
|
+
type: 'boolean',
|
|
322
|
+
batchForwarded: true,
|
|
323
|
+
description: 'forces LLM-friendly output (compact, no color, severity-tagged)'
|
|
91
324
|
},
|
|
92
325
|
{
|
|
93
326
|
name: 'log',
|
|
94
327
|
type: 'fs-entry',
|
|
95
328
|
typeModifiers: new Set(['file']),
|
|
96
|
-
description: '
|
|
329
|
+
description: 'path to a .logz trace file produced by a previous run; activates log viewer mode'
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: 'logDump',
|
|
333
|
+
type: 'boolean',
|
|
334
|
+
description: 'dump all traces to stdout instead of opening a browser (requires --log)'
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: 'logFilter',
|
|
338
|
+
short: 'lf',
|
|
339
|
+
type: 'string',
|
|
340
|
+
description: 'JavaScript expression (using punyexpr) to filter logs for dumping with --log-dump'
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: 'mcp',
|
|
344
|
+
type: 'boolean',
|
|
345
|
+
description: 'start a documentation-only MCP server that lets an MCP client answer questions about ui5-test-runner'
|
|
97
346
|
},
|
|
98
347
|
{
|
|
99
|
-
name: '
|
|
100
|
-
short: 'l',
|
|
348
|
+
name: 'noBanner',
|
|
101
349
|
type: 'boolean',
|
|
102
|
-
description: '
|
|
350
|
+
description: 'do not display the startup banner (logo) and environment information'
|
|
103
351
|
},
|
|
104
352
|
{
|
|
105
353
|
name: 'noNpmInstall',
|
|
106
354
|
type: 'boolean',
|
|
355
|
+
batchForwarded: true,
|
|
107
356
|
description: 'prevent any NPM install'
|
|
108
357
|
},
|
|
358
|
+
{
|
|
359
|
+
name: 'npmAllowInstallScripts',
|
|
360
|
+
type: 'boolean',
|
|
361
|
+
batchForwarded: true,
|
|
362
|
+
description: 'allow postinstall scripts when installing missing packages'
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: 'npmInstall',
|
|
366
|
+
type: 'string',
|
|
367
|
+
description: 'npm install strategy for missing packages',
|
|
368
|
+
default: 'global'
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
name: 'npmInstallMinReleaseAge',
|
|
372
|
+
type: 'integer',
|
|
373
|
+
typeModifiers: new Set(['positive']),
|
|
374
|
+
batchForwarded: true,
|
|
375
|
+
description: 'minimum release age (in days) required before installing a package',
|
|
376
|
+
default: 3
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
name: 'npmInstallPrefix',
|
|
380
|
+
type: 'fs-entry',
|
|
381
|
+
description: 'path used as --prefix when npmInstall is set to prefix'
|
|
382
|
+
},
|
|
109
383
|
{
|
|
110
384
|
name: 'outputInterval',
|
|
111
385
|
short: 'oi',
|
|
112
386
|
type: 'timeout',
|
|
387
|
+
batchForwarded: true,
|
|
113
388
|
description: 'interval for reporting progress on non interactive output (CI/CD)',
|
|
114
389
|
default: 30_000
|
|
115
390
|
},
|
|
@@ -117,31 +392,38 @@ export const options = [
|
|
|
117
392
|
name: 'pageFilter',
|
|
118
393
|
short: 'pf',
|
|
119
394
|
type: 'regexp',
|
|
395
|
+
batchForwarded: true,
|
|
120
396
|
description: 'filter pages to execute'
|
|
121
397
|
},
|
|
122
398
|
{
|
|
123
399
|
name: 'pageParams',
|
|
124
400
|
short: 'pp',
|
|
125
401
|
type: 'string',
|
|
402
|
+
batchForwarded: true,
|
|
126
403
|
description: 'add parameters to page URL'
|
|
127
404
|
},
|
|
128
405
|
{
|
|
129
406
|
name: 'pageTimeout',
|
|
130
407
|
short: 'pt',
|
|
131
408
|
type: 'timeout',
|
|
409
|
+
batchForwarded: true,
|
|
132
410
|
description: 'fails a page if it takes longer than this timeout'
|
|
133
411
|
},
|
|
134
412
|
{
|
|
135
413
|
name: 'parallel',
|
|
136
414
|
short: 'p',
|
|
137
415
|
type: 'integer',
|
|
416
|
+
typeModifiers: new Set(['positive', 'non-zero']),
|
|
417
|
+
browserExposed: true,
|
|
418
|
+
batchForwarded: true,
|
|
138
419
|
description: 'number of parallel executions',
|
|
139
420
|
default: 2
|
|
140
421
|
},
|
|
141
422
|
{
|
|
142
423
|
name: 'port',
|
|
143
424
|
type: 'integer',
|
|
144
|
-
|
|
425
|
+
typeModifiers: new Set(['positive']),
|
|
426
|
+
description: 'Port the local web server listens on; 0 allocates a free port automatically'
|
|
145
427
|
},
|
|
146
428
|
{
|
|
147
429
|
name: 'reportDir',
|
|
@@ -151,16 +433,74 @@ export const options = [
|
|
|
151
433
|
description: 'directory to output test reports',
|
|
152
434
|
default: 'report'
|
|
153
435
|
},
|
|
436
|
+
{
|
|
437
|
+
name: 'screenshot',
|
|
438
|
+
type: 'boolean',
|
|
439
|
+
browserExposed: true,
|
|
440
|
+
batchForwarded: true,
|
|
441
|
+
description: 'take a screenshot after every OPA assertion'
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: 'screenshotOnFailure',
|
|
445
|
+
type: 'boolean',
|
|
446
|
+
batchForwarded: true,
|
|
447
|
+
description: 'take a screenshot when a test fails',
|
|
448
|
+
default: true
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
name: 'screenshotTimeout',
|
|
452
|
+
type: 'timeout',
|
|
453
|
+
batchForwarded: true,
|
|
454
|
+
description: 'maximum time allowed to take a screenshot',
|
|
455
|
+
default: 5000
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: 'seleniumApiTimeout',
|
|
459
|
+
type: 'timeout',
|
|
460
|
+
description: 'fails a page if a selenium webdriver api call does not respond within this timeout, indicating a dead session',
|
|
461
|
+
default: 10_000
|
|
462
|
+
},
|
|
154
463
|
{
|
|
155
464
|
name: 'serveOnly',
|
|
156
465
|
short: 's',
|
|
157
466
|
type: 'boolean',
|
|
158
|
-
description: 'serve
|
|
467
|
+
description: 'start the legacy web server and serve the application without running any tests'
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
name: 'splitOpa',
|
|
471
|
+
short: 'so',
|
|
472
|
+
type: 'boolean',
|
|
473
|
+
browserExposed: true,
|
|
474
|
+
batchForwarded: true,
|
|
475
|
+
description: 'split OPA tests by QUnit module, creating one test page per module'
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
name: 'start',
|
|
479
|
+
type: 'string',
|
|
480
|
+
description: 'command to be executed before the tests'
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: 'startTimeout',
|
|
484
|
+
type: 'timeout',
|
|
485
|
+
description: 'maximum waiting time for the start command to become ready',
|
|
486
|
+
default: 30_000
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: 'startWaitMethod',
|
|
490
|
+
type: 'string',
|
|
491
|
+
description: 'HTTP method used when polling the startWaitUrl',
|
|
492
|
+
default: 'GET'
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: 'startWaitUrl',
|
|
496
|
+
type: 'url',
|
|
497
|
+
description: 'URL to poll after the start command is executed'
|
|
159
498
|
},
|
|
160
499
|
{
|
|
161
500
|
name: 'ui5',
|
|
162
501
|
type: 'url',
|
|
163
|
-
|
|
502
|
+
batchForwarded: true,
|
|
503
|
+
description: 'URL of the UI5 CDN used in legacy mode to serve the UI5 framework resources',
|
|
164
504
|
default: 'https://ui5.sap.com'
|
|
165
505
|
},
|
|
166
506
|
{
|
|
@@ -174,18 +514,47 @@ export const options = [
|
|
|
174
514
|
name: 'version',
|
|
175
515
|
type: 'boolean',
|
|
176
516
|
description: 'display version'
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
name: 'watch',
|
|
520
|
+
type: 'boolean',
|
|
521
|
+
description: 'watch for file changes and automatically reload'
|
|
177
522
|
}
|
|
178
523
|
];
|
|
179
524
|
export const defaults = {
|
|
180
|
-
|
|
525
|
+
agentDetectionInterval: 100,
|
|
526
|
+
agentDetectionMaxInterval: 1000,
|
|
527
|
+
agentDetectionTimeout: 5000,
|
|
528
|
+
agentNoTestsTimeout: 5000,
|
|
529
|
+
agentScreenshotTimeout: 10_000,
|
|
530
|
+
browserOptions: {},
|
|
531
|
+
browserViewportHeight: 1080,
|
|
532
|
+
browserViewportWidth: 1920,
|
|
181
533
|
ci: !process.stdout.isTTY,
|
|
182
534
|
config: 'ui5-test-runner.json',
|
|
535
|
+
coverageCheckBranches: 0,
|
|
536
|
+
coverageCheckFunctions: 0,
|
|
537
|
+
coverageCheckLines: 0,
|
|
538
|
+
coverageCheckStatements: 0,
|
|
539
|
+
coverageReportDir: 'coverage',
|
|
540
|
+
coverageReporters: ['lcov', 'cobertura'],
|
|
541
|
+
coverageSettings: '.nycrc.json',
|
|
542
|
+
coverageTempDir: '.nyc_output',
|
|
183
543
|
cwd: process.cwd(),
|
|
184
|
-
|
|
544
|
+
driver: 'puppeteer',
|
|
545
|
+
junitXmlFilename: 'junit.xml',
|
|
546
|
+
npmInstall: 'global',
|
|
547
|
+
npmInstallMinReleaseAge: 3,
|
|
185
548
|
outputInterval: 30_000,
|
|
186
549
|
parallel: 2,
|
|
187
550
|
reportDir: 'report',
|
|
551
|
+
screenshotOnFailure: true,
|
|
552
|
+
screenshotTimeout: 5000,
|
|
553
|
+
seleniumApiTimeout: 10_000,
|
|
554
|
+
startTimeout: 30_000,
|
|
555
|
+
startWaitMethod: 'GET',
|
|
188
556
|
testsuite: 'test/testsuite.qunit.html',
|
|
189
557
|
ui5: 'https://ui5.sap.com',
|
|
190
558
|
webapp: 'webapp'
|
|
191
559
|
};
|
|
560
|
+
export const sensitiveKeys = new Set(['browserBasicAuthPassword']);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { punyexpr } from 'punyexpr';
|
|
2
|
+
import { indexedOptions } from './indexedOptions.js';
|
|
3
|
+
import { OptionValidationError } from './OptionValidationError.js';
|
|
4
|
+
export const validations = [
|
|
5
|
+
(configuration) => {
|
|
6
|
+
if (Object.hasOwn(configuration, 'browser') &&
|
|
7
|
+
!punyexpr("(driver !== 'puppeteer' || browser === 'chrome' || browser === 'firefox')")(configuration)) {
|
|
8
|
+
throw OptionValidationError.createValidationError(indexedOptions.browser, 'browser is not supported by puppeteer (chrome, firefox)');
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
(configuration) => {
|
|
12
|
+
if (Object.hasOwn(configuration, 'browser') &&
|
|
13
|
+
!punyexpr("(driver !== 'playwright' || browser === 'chromium' || browser === 'firefox' || browser === 'webkit')")(configuration)) {
|
|
14
|
+
throw OptionValidationError.createValidationError(indexedOptions.browser, 'browser is not supported by playwright (chromium, firefox, webkit)');
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
(configuration) => {
|
|
18
|
+
if (Object.hasOwn(configuration, 'browser') &&
|
|
19
|
+
!punyexpr("(driver !== 'webdriverio' || browser === 'chrome' || browser === 'firefox' || browser === 'edge' || browser === 'safari')")(configuration)) {
|
|
20
|
+
throw OptionValidationError.createValidationError(indexedOptions.browser, 'browser is not supported by webdriverio (chrome, firefox, edge, safari)');
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
(configuration) => {
|
|
24
|
+
if (Object.hasOwn(configuration, 'browser') &&
|
|
25
|
+
!punyexpr("(driver !== 'selenium-webdriver' || browser === 'chrome' || browser === 'firefox' || browser === 'edge' || browser === 'safari')")(configuration)) {
|
|
26
|
+
throw OptionValidationError.createValidationError(indexedOptions.browser, 'browser is not supported by selenium-webdriver (chrome, firefox, edge, safari)');
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
(configuration) => {
|
|
30
|
+
if (Object.hasOwn(configuration, 'browserBasicAuthPassword') &&
|
|
31
|
+
!punyexpr("(driver === 'puppeteer' || driver === 'playwright')")(configuration)) {
|
|
32
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserBasicAuthPassword, 'browserBasicAuthPassword is only supported with puppeteer and playwright drivers');
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
(configuration) => {
|
|
36
|
+
if (Object.hasOwn(configuration, 'browserBasicAuthPassword') &&
|
|
37
|
+
!punyexpr('(browserBasicAuthUsername !== undefined)')(configuration)) {
|
|
38
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserBasicAuthPassword, 'browserBasicAuthPassword requires browserBasicAuthUsername');
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
(configuration) => {
|
|
42
|
+
if (Object.hasOwn(configuration, 'browserBasicAuthUsername') &&
|
|
43
|
+
!punyexpr("(driver === 'puppeteer' || driver === 'playwright')")(configuration)) {
|
|
44
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserBasicAuthUsername, 'browserBasicAuthUsername is only supported with puppeteer and playwright drivers');
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
(configuration) => {
|
|
48
|
+
if (Object.hasOwn(configuration, 'browserBasicAuthUsername') &&
|
|
49
|
+
!punyexpr('(browserBasicAuthPassword !== undefined)')(configuration)) {
|
|
50
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserBasicAuthUsername, 'browserBasicAuthUsername requires browserBasicAuthPassword');
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
(configuration) => {
|
|
54
|
+
if (Object.hasOwn(configuration, 'browserDevice') && !punyexpr("(driver === 'puppeteer')")(configuration)) {
|
|
55
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserDevice, 'browserDevice is only supported with the puppeteer driver');
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
(configuration) => {
|
|
59
|
+
if (Object.hasOwn(configuration, 'browserDevice') &&
|
|
60
|
+
!punyexpr("(browser === undefined || browser === 'chrome')")(configuration)) {
|
|
61
|
+
throw OptionValidationError.createValidationError(indexedOptions.browserDevice, 'browserDevice requires the chrome browser');
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
(configuration) => {
|
|
65
|
+
if (Object.hasOwn(configuration, 'coverage') &&
|
|
66
|
+
!punyexpr("(!coverage || webapp !== '' || coverageSourceDir !== '')")(configuration)) {
|
|
67
|
+
throw OptionValidationError.createValidationError(indexedOptions.coverage, 'at least one of webapp or coverageSourceDir must be set');
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
(configuration) => {
|
|
71
|
+
if (Object.hasOwn(configuration, 'debugMcpLocalDocs') &&
|
|
72
|
+
!punyexpr("(!debugMcpLocalDocs || mode === 'mcp')")(configuration)) {
|
|
73
|
+
throw OptionValidationError.createValidationError(indexedOptions.debugMcpLocalDocs, 'this option requires --mcp');
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
(configuration) => {
|
|
77
|
+
if (Object.hasOwn(configuration, 'dumpConfig') && !punyexpr("(mode === 'dumpConfig')")(configuration)) {
|
|
78
|
+
throw OptionValidationError.createValidationError(indexedOptions.dumpConfig, 'this option cannot be combined with other mode options');
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
(configuration) => {
|
|
82
|
+
if (Object.hasOwn(configuration, 'help') && !punyexpr("(mode === 'help')")(configuration)) {
|
|
83
|
+
throw OptionValidationError.createValidationError(indexedOptions.help, 'this option cannot be combined with other mode options');
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
(configuration) => {
|
|
87
|
+
if (Object.hasOwn(configuration, 'log') && !punyexpr("(mode === 'log')")(configuration)) {
|
|
88
|
+
throw OptionValidationError.createValidationError(indexedOptions.log, 'this option cannot be combined with other mode options');
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
(configuration) => {
|
|
92
|
+
if (Object.hasOwn(configuration, 'logDump') && !punyexpr('(log !== undefined)')(configuration)) {
|
|
93
|
+
throw OptionValidationError.createValidationError(indexedOptions.logDump, 'requires log');
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
(configuration) => {
|
|
97
|
+
if (Object.hasOwn(configuration, 'logFilter') &&
|
|
98
|
+
!punyexpr('(log !== undefined) && (logDump !== undefined)')(configuration)) {
|
|
99
|
+
throw OptionValidationError.createValidationError(indexedOptions.logFilter, 'requires log and logDump');
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
(configuration) => {
|
|
103
|
+
if (Object.hasOwn(configuration, 'mcp') && !punyexpr("(mode === 'mcp')")(configuration)) {
|
|
104
|
+
throw OptionValidationError.createValidationError(indexedOptions.mcp, 'this option cannot be combined with other mode options');
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
(configuration) => {
|
|
108
|
+
if (Object.hasOwn(configuration, 'startTimeout') &&
|
|
109
|
+
!punyexpr('(start !== undefined) && (startWaitUrl !== undefined)')(configuration)) {
|
|
110
|
+
throw OptionValidationError.createValidationError(indexedOptions.startTimeout, 'requires start and startWaitUrl');
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
(configuration) => {
|
|
114
|
+
if (Object.hasOwn(configuration, 'startWaitMethod') &&
|
|
115
|
+
!punyexpr('(start !== undefined) && (startWaitUrl !== undefined)')(configuration)) {
|
|
116
|
+
throw OptionValidationError.createValidationError(indexedOptions.startWaitMethod, 'requires start and startWaitUrl');
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
(configuration) => {
|
|
120
|
+
if (Object.hasOwn(configuration, 'startWaitUrl') && !punyexpr('(start !== undefined)')(configuration)) {
|
|
121
|
+
throw OptionValidationError.createValidationError(indexedOptions.startWaitUrl, 'requires start');
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
(configuration) => {
|
|
125
|
+
if (Object.hasOwn(configuration, 'version') && !punyexpr("(mode === 'version')")(configuration)) {
|
|
126
|
+
throw OptionValidationError.createValidationError(indexedOptions.version, 'this option cannot be combined with other mode options');
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
(configuration) => {
|
|
130
|
+
if (Object.hasOwn(configuration, 'watch') &&
|
|
131
|
+
!punyexpr("(!watch || (mode === 'mcp' && debugMcpLocalDocs))")(configuration)) {
|
|
132
|
+
throw OptionValidationError.createValidationError(indexedOptions.watch, 'this option is valid only for --mcp with --debug-mcp-local-docs');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
];
|