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/endpoints.js DELETED
@@ -1,219 +0,0 @@
1
- 'use strict'
2
-
3
- const { join, dirname, basename } = require('path')
4
- const { body } = require('reserve')
5
- const { extractPageUrl } = require('./tools')
6
- const { Request, Response } = require('reserve')
7
- const { getOutput } = require('./output')
8
- const { begin, testStart, log, testDone, done } = require('./qunit-hooks')
9
- const { addTestPages } = require('./add-test-pages')
10
- const { getJobProgress } = require('./get-job-progress')
11
- const { readFile } = require('fs/promises')
12
- const { TextEncoder } = require('util')
13
- const { resolveDependencyPath } = require('./npm.js')
14
-
15
- const punyexprBinPath = join(resolveDependencyPath('punyexpr'), 'dist/punyexpr.js')
16
- const punybindBinPath = join(resolveDependencyPath('punybind'), 'dist/punybind.js')
17
-
18
- module.exports = job => {
19
- async function endpointImpl (api, implementation, request) {
20
- const url = extractPageUrl(request.headers)
21
- const data = await body(request)
22
- try {
23
- await implementation.call(this, url, data)
24
- } catch (error) {
25
- getOutput(job).endpointError({ api, url, data, error })
26
- }
27
- }
28
-
29
- function synchronousEndpoint (api, implementation) {
30
- return async function (request, response) {
31
- await endpointImpl(api, implementation, request)
32
- response.writeHead(200)
33
- response.end()
34
- }
35
- }
36
-
37
- function endpoint (api, implementation) {
38
- return async function (request, response) {
39
- response.writeHead(200)
40
- response.end()
41
- await endpointImpl(api, implementation, request)
42
- }
43
- }
44
-
45
- async function getInjects (...names) {
46
- return '\n;\n' + (await Promise.all(names.map(name => readFile(join(__dirname, 'inject', `${name}.js`)))))
47
- .map(buffer => buffer.toString())
48
- .join('\n;\n')
49
- }
50
-
51
- function contentLength (content) {
52
- return new TextEncoder().encode(content).length
53
- }
54
-
55
- function sendScript (response, content) {
56
- response.writeHead(200, {
57
- 'content-type': 'text/javascript',
58
- 'content-length': contentLength(content),
59
- 'cache-control': 'no-store'
60
- })
61
- response.end(content)
62
- }
63
-
64
- return job.parallel
65
- ? [{
66
- // Substitute qunit-redirect to extract test pages
67
- match: '/resources/sap/ui/qunit/qunit-redirect.js',
68
- custom: async (request, response) => {
69
- sendScript(response, await getInjects('post', 'qunit-redirect'))
70
- }
71
- }, {
72
- // Endpoint to receive test pages
73
- match: '^/_/addTestPages',
74
- custom: endpoint('addTestPages', (url, pages) => addTestPages(job, url, pages))
75
- }, {
76
- // QUnit hooks
77
- match: '^/_/qunit-hooks.js',
78
- cwd: __dirname,
79
- file: 'inject/qunit-hooks.js',
80
- static: !job.debugDevMode
81
- }, {
82
- // Concatenate qunit.js source with hooks
83
- match: /\/thirdparty\/(qunit(?:-2)?(?:-dbg)?\.js)/,
84
- custom: async function (request, response, scriptName) {
85
- if (request.internal) {
86
- return // ignore to avoid infinite loop
87
- }
88
- const ui5Request = new Request('GET', request.url)
89
- ui5Request.internal = true
90
- const ui5Response = new Response()
91
- const [inject] = await Promise.all([
92
- getInjects('post', 'qunit-hooks'),
93
- this.configuration.dispatch(ui5Request, ui5Response)
94
- ])
95
- const hooksLength = contentLength(inject)
96
- const ui5Length = parseInt(ui5Response.headers['content-length'], 10)
97
- response.writeHead(ui5Response.statusCode, {
98
- ...ui5Response.headers,
99
- 'content-length': ui5Length + hooksLength,
100
- 'cache-control': 'no-store' // for debugging purpose
101
- })
102
- response.write(ui5Response.toString())
103
- response.end(inject)
104
- }
105
- }, {
106
- // Endpoint to receive QUnit.begin
107
- match: '^/_/QUnit/begin',
108
- custom: endpoint('QUnit/begin', (url, details) => begin(job, url, details))
109
- }, {
110
- // Endpoint to receive QUnit.testStart
111
- match: '^/_/QUnit/testStart',
112
- custom: endpoint('QUnit/testStart', (url, details) => testStart(job, url, details))
113
- }, {
114
- // Endpoint to receive QUnit.log
115
- match: '^/_/QUnit/log',
116
- custom: synchronousEndpoint('QUnit/log', async (url, report) => log(job, url, report))
117
- }, {
118
- // Endpoint to receive QUnit.testDone
119
- match: '^/_/QUnit/testDone',
120
- custom: synchronousEndpoint('QUnit/testDone', async (url, report) => testDone(job, url, report))
121
- }, {
122
- // Endpoint to receive QUnit.done
123
- match: '^/_/QUnit/done',
124
- custom: endpoint('QUnit/done', async (url, report) => done(job, url, report))
125
- }, {
126
- // Fast batch endpoint for QUnit (no screenshot)
127
- match: '^/_/QUnit/batch',
128
- custom: async (request, response) => {
129
- const url = extractPageUrl(request.headers)
130
- const data = await body(request)
131
- response.writeHead(200)
132
- response.end()
133
- try {
134
- for (const [hook, hookData] of data) {
135
- switch (hook) {
136
- case 'QUnit/begin':
137
- await begin(job, url, hookData)
138
- break
139
- case 'QUnit/testStart':
140
- await testStart(job, url, hookData)
141
- break
142
- case 'QUnit/log':
143
- await log(job, url, hookData)
144
- break
145
- case 'QUnit/testDone':
146
- await testDone(job, url, hookData)
147
- break
148
- case 'QUnit/done':
149
- await done(job, url, hookData)
150
- break
151
- }
152
- }
153
- } catch (error) {
154
- getOutput(job).endpointError({ api: 'QUnit/batch', url, data, error })
155
- }
156
- }
157
- }, {
158
- // UI to follow progress
159
- match: '^/_/progress.html',
160
- cwd: dirname(job.progressPage),
161
- file: basename(job.progressPage),
162
- static: !job.debugDevMode
163
- }, {
164
- // Report 'main' substituted for progress
165
- match: '^/_/report/main.js',
166
- cwd: __dirname,
167
- file: 'defaults/report/progress.js',
168
- static: !job.debugDevMode
169
- }, {
170
- // Other report resources
171
- match: '^/_/report/(.*)',
172
- cwd: __dirname,
173
- file: 'defaults/report/$1',
174
- static: !job.debugDevMode
175
- }, {
176
- // punybind
177
- match: '^/_/punybind.js',
178
- cwd: dirname(punybindBinPath),
179
- file: basename(punybindBinPath),
180
- static: !job.debugDevMode
181
- }, {
182
- // punyexpr
183
- match: '^/_/punyexpr.js',
184
- cwd: dirname(punyexprBinPath),
185
- file: basename(punyexprBinPath),
186
- static: !job.debugDevMode
187
- }, {
188
- // Endpoint to retry on progress
189
- method: 'INFO',
190
- match: '^/_/progress',
191
- custom: (request, response) => {
192
- response.writeHead(204)
193
- response.end()
194
- }
195
- }, {
196
- // Endpoint to follow progress
197
- match: '^/_/progress(?:\\?page=([^&]*)(?:&test=([^&]*))?)?',
198
- custom: (request, response, pageId, testId) => getJobProgress(job, request, response, pageId, testId)
199
- }, {
200
- // Endpoint to coverage files
201
- match: '^/_/coverage/(.*)',
202
- cwd: job.coverageReportDir,
203
- file: '$1',
204
- static: false
205
- }, {
206
- // Endpoint to report
207
- match: '^/_/report.html',
208
- cwd: __dirname,
209
- file: 'report.html',
210
- static: !job.debugDevMode
211
- }, {
212
- // Endpoint to report files
213
- match: '^/_/(.*)',
214
- cwd: job.reportDir,
215
- file: '$1',
216
- static: false
217
- }]
218
- : []
219
- }
package/src/error.js DELETED
@@ -1,54 +0,0 @@
1
- class UTRError extends Error {
2
- get code () { return this._code }
3
-
4
- constructor (error, details) {
5
- super()
6
- this.name = `UTRError:${error.name}`
7
- this._code = error.code
8
- if (details) {
9
- this.message = details
10
- } else {
11
- this.message = error.name
12
- }
13
- }
14
- }
15
-
16
- const errors = [{
17
- name: 'GENERIC'
18
- }, {
19
- name: 'NPM_FAILED'
20
- }, {
21
- name: 'MISSING_OR_INVALID_BROWSER_CAPABILITIES'
22
- }, {
23
- name: 'BROWSER_PROBE_FAILED'
24
- }, {
25
- name: 'BROWSER_FAILED'
26
- }, {
27
- name: 'BROWSER_SCREENSHOT_FAILED'
28
- }, {
29
- name: 'BROWSER_SCREENSHOT_TIMEOUT'
30
- }, {
31
- name: 'BROWSER_SCREENSHOT_NOT_SUPPORTED'
32
- }, {
33
- name: 'QUNIT_ERROR'
34
- }, {
35
- name: 'MODE_INCOMPATIBLE_OPTION'
36
- }, {
37
- name: 'BROWSER_MISS_SCRIPTS_CAPABILITY'
38
- }, {
39
- name: 'NPM_DEPENDENCY_NOT_FOUND'
40
- }, {
41
- name: 'NYC_FAILED'
42
- }]
43
-
44
- errors.forEach((error, index) => {
45
- error.code = -1 - index
46
- UTRError[`${error.name}_CODE`] = error.code
47
- UTRError[error.name] = function (details = '') {
48
- return new UTRError(error, details)
49
- }
50
- })
51
-
52
- module.exports = {
53
- UTRError
54
- }
@@ -1,78 +0,0 @@
1
- 'use strict'
2
-
3
- const { $proxifiedUrls } = require('./symbols')
4
-
5
- const send = (response, obj) => {
6
- let json
7
- if (typeof obj !== 'string') {
8
- json = JSON.stringify(obj, undefined, 2)
9
- } else {
10
- json = obj
11
- }
12
- const length = (new TextEncoder().encode(json)).length
13
- response.writeHead(200, {
14
- 'Content-Type': 'application/json',
15
- 'Content-Length': length
16
- })
17
- response.end(json)
18
- }
19
-
20
- const notFound = response => {
21
- response.writeHead(404)
22
- response.end()
23
- }
24
-
25
- module.exports = {
26
- async getJobProgress (job, request, response, pageId, testId) {
27
- if (pageId) {
28
- const url = Object.keys(job.qunitPages).find(pageUrl => job.qunitPages[pageUrl].id === pageId)
29
- if (!url) {
30
- return notFound(response)
31
- }
32
- const qunitPage = { url, ...job.qunitPages[url] }
33
- if (!testId) {
34
- return send(response, JSON.stringify(qunitPage, (key, value) => {
35
- if (key === 'logs') {
36
- return undefined
37
- }
38
- return value
39
- }, 2))
40
- }
41
- let test
42
- let moduleName
43
- qunitPage.modules.every(module => module.tests.every(candidate => {
44
- if (candidate.testId === testId) {
45
- moduleName = module.name
46
- test = candidate
47
- return false
48
- }
49
- return true
50
- }))
51
- if (!test) {
52
- return notFound(response)
53
- }
54
- return send(response, {
55
- url,
56
- pageId,
57
- module: moduleName,
58
- ...test
59
- })
60
- }
61
- send(response, JSON.stringify({
62
- ...job,
63
- status: job.status
64
- }, (key, value) => {
65
- if (key === 'qunitPages' && job[$proxifiedUrls]) {
66
- const unproxifiedQunitPages = {}
67
- for (const url of Object.keys(job.qunitPages)) {
68
- unproxifiedQunitPages[job[$proxifiedUrls][url] || url] = job.qunitPages[url]
69
- }
70
- return unproxifiedQunitPages
71
- }
72
- if (key === 'modules') {
73
- return undefined
74
- }
75
- return value
76
- }, 2))
77
- }
78
- }
package/src/handle.js DELETED
@@ -1,43 +0,0 @@
1
- const { ServerResponse, ClientRequest } = require('node:http')
2
-
3
- module.exports = {
4
- describeHandle (handle) {
5
- const className = handle && handle.constructor && handle.constructor.name
6
- let label = className
7
- if (['TLSSocket', 'Socket'].includes(className)) {
8
- if (handle._httpMessage instanceof ServerResponse) {
9
- const { method, url } = handle._httpMessage.req
10
- label += ` IncomingRequest ${method} ${url}`
11
- } else if (handle._httpMessage instanceof ClientRequest) {
12
- const { path, method, host, protocol } = handle._httpMessage
13
- label += ` ClientRequest ${method} ${protocol}//${host}${path}`
14
- } else if (handle.localAddress) {
15
- const { localAddress, localPort, remoteAddress, remotePort } = handle
16
- if (remoteAddress === undefined) {
17
- label += ` local ${localAddress}:${localPort}`
18
- } else {
19
- label += ` local ${localAddress}:${localPort} remote ${remoteAddress}:${remotePort}`
20
- }
21
- } else if (handle._handle) {
22
- const underlyingHandle = handle._handle
23
- const underlyingClassName = underlyingHandle && underlyingHandle.constructor && underlyingHandle.constructor.name
24
- label += ` <-> ${underlyingClassName || 'unknown'}`
25
- } else {
26
- label += ' unknown'
27
- }
28
- } else if (className === 'WriteStream') {
29
- const fd = ['stdin', 'stdout', 'stderr'][handle.fd] || `fd: ${handle.fd}`
30
- label += ` ${fd} ${handle.columns}x${handle.rows} isTTY: ${handle.isTTY}`
31
- } else if (className === 'Server') {
32
- label += ` connections: ${handle._connections} events: ${handle._eventsCount}`
33
- } else if (className === 'ChildProcess') {
34
- label += ` pid: ${handle.pid}`
35
- if (handle.spawnargs) {
36
- label += ` ${handle.spawnargs.map(value => ('' + value).replaceAll(/ /g, '␣'))}`
37
- } else {
38
- label += ' unknown'
39
- }
40
- }
41
- return { className, label }
42
- }
43
- }
package/src/if.js DELETED
@@ -1,10 +0,0 @@
1
- const { punyexpr } = require('punyexpr')
2
-
3
- function executeIf (job) {
4
- return punyexpr(job.if)({
5
- ...process.env,
6
- NODE_MAJOR_VERSION: parseInt(parseInt(process.version.match(/v(\d+)\./)[1]))
7
- })
8
- }
9
-
10
- module.exports = { executeIf }
@@ -1,289 +0,0 @@
1
- /* global sinon */
2
- (() => {
3
- class Jest2QUnitError extends SyntaxError {
4
- static throw (reason) {
5
- throw new Jest2QUnitError(reason)
6
- }
7
-
8
- constructor (reason) {
9
- super('jest2qunit failure : ' + reason)
10
- this.name = 'Jest2QUnitError'
11
- }
12
- }
13
-
14
- const $raw = Symbol('raw')
15
- const unproxify = (value) => value && (value[$raw] ?? value)
16
-
17
- const get = function (target, property) {
18
- if (target[property] !== undefined) {
19
- return target[property]
20
- }
21
- if (typeof property === 'symbol') {
22
- return undefined // otherwise returned previously
23
- }
24
- if (typeof this[property] === 'function') {
25
- return this[property](target)
26
- }
27
- Jest2QUnitError.throw(`${this._type}.${property} is missing`)
28
- }
29
-
30
- let _sinonSandbox
31
- const jestSpy = (sinonStub) => new Proxy(Object.assign(sinonStub, {
32
- [$raw]: sinonStub,
33
- mockImplementation (callback) { sinonStub.callsFake(callback); return this },
34
- mockImplementationOnce (callback) { sinonStub.onCall(0).callsFake(callback); return this },
35
- mockResolvedValue (value) { sinonStub.returns(Promise.resolve(value)); return this },
36
- mockResolvedValueOnce (value) { sinonStub.onCall(0).returns(Promise.resolve(value)); return this },
37
- mockRejectedValue (value) { sinonStub.returns(Promise.reject(value)); return this },
38
- mockRejectedValueOnce (value) { sinonStub.onCall(0).returns(Promise.reject(value)); return this },
39
- mockReturnValue (value) { sinonStub.returns(value); return this },
40
- mockReturnValueOnce (value) { sinonStub.onCall(0).returns(value); return this },
41
- mockRestore () { sinonStub.restore() },
42
- get mock () {
43
- return new Proxy({}, {
44
- _type: 'jestSpy.mock',
45
- get,
46
- calls () { return sinonStub.args },
47
- results () { return sinonStub.returnValues.map(value => ({ value })) }
48
- })
49
- }
50
- }), { _type: 'jestSpy', get })
51
-
52
- const jest = new Proxy({
53
- fn (impl) {
54
- const stub = jestSpy(_sinonSandbox.stub())
55
- if (impl) {
56
- stub.mockImplementation(impl)
57
- }
58
- return stub
59
- },
60
- spyOn (object, property) {
61
- const impl = object[property]
62
- if (impl[$raw]) { // already looks like a spy
63
- return impl
64
- }
65
- const spy = jestSpy(_sinonSandbox.stub(object, property))
66
- spy.mockImplementation(impl)
67
- return spy
68
- },
69
- clearAllMocks () { _sinonSandbox.resetHistory() }
70
- }, { _type: 'jest', get })
71
-
72
- const stringify = value => value === undefined
73
- ? 'undefined'
74
- : typeof value === 'function'
75
- ? Function.prototype.toString.call(value)
76
- : value && value instanceof RegExp
77
- ? value.toString()
78
- : JSON.stringify(value)
79
-
80
- const negate = method => method.startsWith('not')
81
- ? method.charAt(3).toLowerCase() + method.substring(4)
82
- : 'not' + method.charAt(0).toUpperCase() + method.substring(1)
83
-
84
- const expectQUnit = params => {
85
- let { label = 'expect(result)', not, method, assert = 'ok', value, compute, expected, expectedLabel = stringify(expected) } = params
86
- if (expected) {
87
- expected = unproxify(expected)
88
- }
89
- if (not) {
90
- assert = negate(assert)
91
- }
92
- const message = `${label}${not ? '.not' : ''}.${method}${!method.includes('(') ? '(' + expectedLabel + ')' : ''}`
93
- const parameters = []
94
- if ('expected' in params && !['ok', 'notOk'].includes(assert)) {
95
- parameters.push(expected)
96
- }
97
- parameters.push(message)
98
- return value && value.then
99
- ? value.then(resolvedValue => QUnit.assert[assert](compute ? compute(resolvedValue) : resolvedValue, ...parameters))
100
- : QUnit.assert[assert](compute ? compute(value) : value, ...parameters)
101
- }
102
-
103
- const expect = (value, label) => {
104
- value = unproxify(value)
105
- let not = false
106
- const proxy = new Proxy({
107
- toBe: (expected) => expectQUnit({ label, not, method: 'toBe', assert: 'equal', value, expected }),
108
- toBeDefined: () => expectQUnit({ label, not, method: 'toBeDefined()', assert: 'notStrictEqual', value, expected: undefined }),
109
- toBeUndefined: () => expectQUnit({ label, not, method: 'toBeUndefined()', assert: 'strictEqual', value, expected: undefined }),
110
- toBeNull: () => expectQUnit({ label, not, method: 'toBeNull()', assert: 'strictEqual', value, expected: null }),
111
- toBeNaN: () => expectQUnit({ label, not, method: 'toBeNaN()', value, compute: value => isNaN(value) }),
112
- toBeTruthy: () => expectQUnit({ label, not, method: 'toBeTruthy()', value }),
113
- toBeFalsy: () => expectQUnit({ label, not, method: 'toBeFalsy()', value, compute: value => !value }),
114
- toEqual: (expected) => expectQUnit({ label, not, method: 'toEqual', assert: 'deepEqual', value, expected }),
115
- toStrictEqual: (expected) => expectQUnit({ label, not, method: 'toStrictEqual', assert: 'deepEqual', value, expected }),
116
- toBeGreaterThan: (expected) => expectQUnit({ label, not, method: 'toBeGreaterThan', value, compute: value => value > expected, expected }),
117
- toBeGreaterThanOrEqual: (expected) => expectQUnit({ label, not, method: 'toBeGreaterThanOrEqual', value, compute: value => value >= expected, expected }),
118
- toBeLessThan: (expected) => expectQUnit({ label, not, method: 'toBeLessThan', value, compute: value => value < expected, expected }),
119
- toBeLessThanOrEqual: (expected) => expectQUnit({ label, not, method: 'toBeLessThanOrEqual', value, compute: value => value <= expected, expected }),
120
- toMatch: (expected) => expectQUnit({ label, not, method: 'toMatch', value, compute: value => expected.test(value), expected }),
121
- toContain: (expected) => expectQUnit({ label, not, method: 'toContain', value, compute: value => value.includes(expected), expected }),
122
- // TODO: handle
123
- toThrow: (expected) => expectQUnit({
124
- label,
125
- not,
126
- method: 'toThrow',
127
- value,
128
- compute: value => {
129
- try {
130
- value()
131
- return false
132
- } catch (e) {
133
- if (typeof expected === 'string') {
134
- return e.message === expected
135
- }
136
- if (expected instanceof RegExp) {
137
- return expected.test(e.message)
138
- }
139
- return true
140
- }
141
- },
142
- expected,
143
- expectedLabel: typeof expected === 'function' && expected.name ? expected.name : undefined
144
- }),
145
- toBeCloseTo: (expected, numDigits = 2) => {
146
- const factor = 10 ** numDigits
147
- const round = (x) => Math.floor(x * factor) / factor
148
- return expectQUnit({ label, not, method: 'toBeCloseTo', assert: 'strictEqual', value: round(value), expected: round(expected) })
149
- },
150
- // Not async
151
- toHaveBeenCalled: () => expectQUnit({ label, not, method: 'toHaveBeenCalled()', value, compute: value => value.called }),
152
- toHaveBeenCalledTimes: (n) => expectQUnit({ label, not, method: 'toHaveBeenCalledTimes', assert: 'strictEqual', value, compute: value => value.callCount, expected: n }),
153
- toHaveBeenCalledWith: (...args) => expectQUnit({ label, not, method: `toHaveBeenCalledWith(${args.map(stringify).join(', ')})`, value, compute: value => value.calledWith(...args) })
154
- }, {
155
- _type: 'expect',
156
- get,
157
- not () {
158
- not = !not
159
- return proxy
160
- },
161
- resolves () {
162
- if (not) {
163
- Jest2QUnitError.throw('expect.resolves cannot be negated')
164
- }
165
- if (typeof value.then !== 'function') {
166
- Jest2QUnitError.throw('expected value must be thenable')
167
- }
168
- return expect(value.then(value => value, reason => QUnit.assert.ok(false, reason)), 'expect(result).resolves')
169
- },
170
- rejects () {
171
- if (not) {
172
- Jest2QUnitError.throw('expect.resolves cannot be negated')
173
- }
174
- if (typeof value.then !== 'function') {
175
- Jest2QUnitError.throw('expected value must be thenable')
176
- }
177
- return expect(value.then(() => QUnit.assert.ok(false, 'Promise should not be fulfilled'), reason => reason), 'expect(result).rejects')
178
- }
179
- })
180
- return proxy
181
- }
182
-
183
- const rootDescribe = {}
184
- let currentDescribe = rootDescribe
185
-
186
- const bddApi = (type, data) => {
187
- if (!currentDescribe[type]) {
188
- currentDescribe[type] = []
189
- }
190
- currentDescribe[type].push(data)
191
- }
192
-
193
- const beforeAll = (callback) => bddApi('beforeAll', callback)
194
- const before = (callback) => bddApi('beforeAll', callback)
195
- const beforeEach = (callback) => bddApi('beforeEach', callback)
196
- const afterEach = (callback) => bddApi('afterEach', callback)
197
- const afterAll = (callback) => bddApi('afterAll', callback)
198
- const after = (callback) => bddApi('afterAll', callback)
199
- const it = (label, callback) => bddApi('it', { label, callback })
200
- it.only = (label, callback) => bddApi('it', { label, callback, only: true })
201
- it.skip = (label, callback) => bddApi('it', { label, callback, skip: true })
202
- it.todo = (label, callback) => bddApi('it', { label, callback, todo: true })
203
- const test = (label, callback) => bddApi('it', { label, callback })
204
- test.only = (label, callback) => bddApi('it', { label, callback, only: true })
205
- test.skip = (label, callback) => bddApi('it', { label, callback, skip: true })
206
- test.todo = (label, callback) => bddApi('it', { label, callback, todo: true })
207
-
208
- const $alreadyConvertedToQUnit = Symbol('alreadyConvertedToQUnit')
209
- const toQUnit = (describe) => {
210
- if (describe[$alreadyConvertedToQUnit]) {
211
- return
212
- }
213
- describe[$alreadyConvertedToQUnit] = true
214
- QUnit.module(describe.label ?? '(root)', function (hooks) {
215
- if (describe.beforeAll) {
216
- hooks.before(async () => Promise.all(describe.beforeAll.map(callback => callback())))
217
- }
218
- if (describe.beforeEach) {
219
- hooks.beforeEach(async () => Promise.all(describe.beforeEach.map(callback => callback())))
220
- }
221
- if (describe.afterEach) {
222
- hooks.afterEach(async () => Promise.all(describe.afterEach.map(callback => callback())))
223
- }
224
- if (describe.afterAll) {
225
- hooks.after(async () => Promise.all(describe.afterAll.map(callback => callback())))
226
- }
227
- if (describe.it) {
228
- for (const { label, callback, skip, todo, only } of describe.it) {
229
- if (todo) {
230
- QUnit.test('[todo] ' + label, (assert) => assert.expect(0))
231
- } else if (skip) {
232
- QUnit.test('[skip] ' + label, (assert) => assert.expect(0))
233
- } else if (only) {
234
- QUnit.only(label, callback)
235
- } else {
236
- QUnit.test(label, callback)
237
- }
238
- }
239
- }
240
- if (describe.describe) {
241
- for (const subDescribe of describe.describe) {
242
- toQUnit(subDescribe)
243
- }
244
- }
245
- })
246
- }
247
-
248
- const describe = (label, callback) => {
249
- QUnit.config.reorder = false // By default in Jest
250
- if (typeof sinon !== 'object') {
251
- Jest2QUnitError.throw('sinon is missing')
252
- }
253
- if (sinon.createSandbox === undefined) {
254
- Jest2QUnitError.throw('sinon 4 is expected')
255
- }
256
- _sinonSandbox = sinon.createSandbox()
257
-
258
- const parentDescribe = currentDescribe
259
- if (!parentDescribe.describe) {
260
- parentDescribe.describe = []
261
- }
262
- currentDescribe = {
263
- label
264
- }
265
- parentDescribe.describe.push(currentDescribe)
266
-
267
- callback()
268
-
269
- currentDescribe = parentDescribe
270
- if (currentDescribe === rootDescribe) {
271
- rootDescribe[$alreadyConvertedToQUnit] = false
272
- toQUnit(rootDescribe)
273
- }
274
- }
275
-
276
- Object.assign(globalThis, {
277
- jest,
278
- expect,
279
- beforeAll,
280
- before,
281
- beforeEach,
282
- afterEach,
283
- afterAll,
284
- after,
285
- it,
286
- test,
287
- describe
288
- })
289
- })()