diff --git a/README.md b/README.md index 74c7fb7a..6627faf1 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ You may also use : | libs | | Folder(s) containing dependent libraries *(relative to `cwd`)*.
Might be used multiple times, two syntaxes are supported : | | cache | `''` | Cache UI5 resources locally in the given folder *(empty to disable)* | | webapp | `'webapp'` | base folder of the web application *(relative to `cwd`)* | +| testsuite | `'test/testsuite.qunit.html'` | path / URL to the testsuite file *(relative to `webapp`)* | | pageFilter | `''` | [regexp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) to select which pages to execute | | pageParams | `''` | Parameters added to each page URL.
For instance : `'sap-ui-theme=sap_belize&sap-ui-debug=true'` | | pageTimeout | `0` | Limit the page execution time (ms), fails the page if it takes longer than the timeout (`0` to disable the timeout) | diff --git a/__mocks__/fs.js b/__mocks__/fs.js new file mode 100644 index 00000000..7ef05150 --- /dev/null +++ b/__mocks__/fs.js @@ -0,0 +1,14 @@ +const fs = jest.requireActual('fs') + +module.exports = { + ...fs, + writeFile (path, content, options, callback) { + // This version is used only in unhandled + callback() + }, + accessSync: path => { + if (path.includes('$NOT_EXISTING$')) { + throw new Error() + } + } +} diff --git a/__mocks__/setup.js b/__mocks__/setup.js new file mode 100644 index 00000000..88b96295 --- /dev/null +++ b/__mocks__/setup.js @@ -0,0 +1,11 @@ +jest.mock('child_process') +jest.mock('fs') + +const EventEmitter = require('events') +const mockedOutput = new EventEmitter() + +const output = jest.requireActual('../src/output') +Object.keys(output).forEach(name => { + mockedOutput[name] = function (...args) { this.emit(name, ...args) } +}) +jest.mock('../src/output', () => mockedOutput) diff --git a/__tests__/src/browser.js b/__tests__/src/browser.js index cdc5abab..701db6b0 100644 --- a/__tests__/src/browser.js +++ b/__tests__/src/browser.js @@ -1,17 +1,3 @@ -jest.mock('child_process') -jest.mock('../../src/output', () => { - const EventEmitter = require('events') - class Output extends EventEmitter { - browserStart (...args) { this.emit('browserStart', ...args) } - browserStopped (...args) { this.emit('browserStopped', ...args) } - browserCapabilities (...args) { this.emit('browserCapabilities', ...args) } - browserTimeout (...args) { this.emit('browserTimeout', ...args) } - browserRetry (...args) { this.emit('browserRetry', ...args) } - browserClosed (...args) { this.emit('browserClosed', ...args) } - monitor (...args) { this.emit('monitor', ...args) } - } - return new Output() -}) const output = require('../../src/output') const { join } = require('path') const { _hook: hook } = require('child_process') diff --git a/__tests__/src/coverage.js b/__tests__/src/coverage.js index 5fee56cb..9300b859 100644 --- a/__tests__/src/coverage.js +++ b/__tests__/src/coverage.js @@ -1,10 +1,3 @@ -jest.mock('child_process') -jest.mock('../../src/output', () => { - return { - nyc: jest.fn(), - monitor: jest.fn() - } -}) const { join } = require('path') const jobFactory = require('../../src/job') const { _hook: hook } = require('child_process') diff --git a/__tests__/src/job.js b/__tests__/src/job.js index 15418362..0f2bfbb4 100644 --- a/__tests__/src/job.js +++ b/__tests__/src/job.js @@ -1,8 +1,3 @@ -jest.mock('../../src/output', () => { - return { - unexpectedOptionValue: jest.fn() - } -}) const { dirname, join } = require('path') const jobFactory = require('../../src/job') const cwd = '/test/project' @@ -124,6 +119,28 @@ describe('src/job', () => { expect(job.ui5).toStrictEqual('https://ui5.sap.com') }) + describe('Path parameters validation', () => { + it('webapp', () => { + const cwd = join(__dirname, '../cwd') + expect(() => jobFactory.fromCmdLine(cwd, [0, 0, '-webapp:$NOT_EXISTING$'])).toThrow() + }) + + it('browser', () => { + const cwd = join(__dirname, '../cwd') + expect(() => jobFactory.fromCmdLine(cwd, [0, 0, '-browser:$NOT_EXISTING$/cmd.js'])).toThrow() + }) + + it('testsuite', () => { + const cwd = join(__dirname, '../cwd') + expect(() => jobFactory.fromCmdLine(cwd, [0, 0, '-testsuite:$NOT_EXISTING$/testsuite.html'])).toThrow() + }) + + it('lib', () => { + const cwd = join(__dirname, '../cwd') + expect(() => jobFactory.fromCmdLine(cwd, [0, 0, '-libs:c=$NOT_EXISTING$/c'])).toThrow() + }) + }) + afterAll(() => { expect(log.mock.calls.length).toStrictEqual(0) expect(warn.mock.calls.length).toStrictEqual(0) diff --git a/__tests__/src/simulate.js b/__tests__/src/simulate.js index e9c7d95b..a5fc8f53 100644 --- a/__tests__/src/simulate.js +++ b/__tests__/src/simulate.js @@ -1,20 +1,3 @@ -jest.mock('child_process') -jest.mock('../../src/output', () => { - return { - nyc: jest.fn(), - monitor: jest.fn(), - browserStart: jest.fn(), - browserStopped: jest.fn(), - endpoint: jest.fn(), - endpointError: jest.fn(), - timeSpent: jest.fn(), - globalTimeout: jest.fn(), - failFast: jest.fn(), - noTestPageFound: jest.fn(), - failedToCacheUI5resource: jest.fn(), - results: jest.fn() - } -}) const { join } = require('path') const { mock } = require('reserve') const jobFactory = require('../../src/job') diff --git a/__tests__/src/unhandled.js b/__tests__/src/unhandled.js index f1e75275..c17aac20 100644 --- a/__tests__/src/unhandled.js +++ b/__tests__/src/unhandled.js @@ -1,18 +1,4 @@ -jest.mock('../../src/output', () => { - return { - unhandled: jest.fn() - } -}) const output = require('../../src/output') -jest.mock('fs', () => { - return { - writeFile: jest.fn(), - promises: { - stat: jest.fn(), - mkdir: jest.fn() - } - } -}) const jobFactory = require('../../src/job') const mappingFactory = require('../../src/unhandled') @@ -22,12 +8,23 @@ describe('src/unhandled', () => { let error let unhandled + let unhandledCall = 0 + + function incUnhandledCall () { + ++unhandledCall + } + beforeAll(() => { log = jest.spyOn(console, 'log').mockImplementation() warn = jest.spyOn(console, 'warn').mockImplementation() error = jest.spyOn(console, 'error').mockImplementation() + output.on('unhandled', incUnhandledCall) + }) + + beforeEach(() => { const job = jobFactory.fromCmdLine('/', []) unhandled = mappingFactory(job)[0].custom + unhandledCall = 0 }) const expectedIgnores = [ @@ -39,7 +36,7 @@ describe('src/unhandled', () => { expectedIgnores.forEach(url => { it(`does not log known GET patterns (${url})`, () => { expect(unhandled({ method: 'GET', url })).toStrictEqual(404) - expect(output.unhandled.mock.calls.length).toStrictEqual(0) + expect(unhandledCall).toStrictEqual(0) }) }) @@ -47,19 +44,32 @@ describe('src/unhandled', () => { 'any-mock-data-file.json', 'sourceFile.js' ] - expectedWarnings.forEach((url, index) => { + expectedWarnings.forEach(url => { it(`warns about 404 GET (${url})`, () => { expect(unhandled({ method: 'GET', url, headers: { referer: 'http://localhost:3475/test.html' } })).toStrictEqual(404) - expect(output.unhandled.mock.calls.length).toStrictEqual(1) + expect(unhandledCall).toStrictEqual(1) + }) + }) + it('Warns only once', () => { + expectedWarnings.forEach(url => { + expect(unhandled({ method: 'GET', url, headers: { referer: 'http://localhost:3475/test.html' } })).toStrictEqual(404) }) + expect(unhandledCall).toStrictEqual(1) }) it('logs errors for any other verb', () => { expect(unhandled({ method: 'POST', url: '/any_url', headers: { referer: 'http://localhost:3475/test.html' } })).toStrictEqual(500) - expect(output.unhandled.mock.calls.length).toStrictEqual(1) + expect(unhandledCall).toStrictEqual(1) + }) + + it('logs errors only once', () => { + expect(unhandled({ method: 'POST', url: '/any_url', headers: { referer: 'http://localhost:3475/test.html' } })).toStrictEqual(500) + expect(unhandled({ method: 'POST', url: '/any_other_url', headers: { referer: 'http://localhost:3475/test.html' } })).toStrictEqual(500) + expect(unhandledCall).toStrictEqual(1) }) afterAll(() => { + output.off('unhandled', incUnhandledCall) expect(log.mock.calls.length).toStrictEqual(0) expect(warn.mock.calls.length).toStrictEqual(0) expect(error.mock.calls.length).toStrictEqual(0) diff --git a/index.js b/index.js index dfc37e3d..271f2c4c 100644 --- a/index.js +++ b/index.js @@ -69,4 +69,4 @@ async function main () { }) } -main() +main().catch(reason => output.genericError(reason)) diff --git a/package-lock.json b/package-lock.json index 4b84e68b..bb05a33a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25 +1,25 @@ { "name": "ui5-test-runner", - "version": "1.1.2", + "version": "1.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ui5-test-runner", - "version": "1.1.2", + "version": "1.1.3", "license": "MIT", "dependencies": { - "mime": "^2.5.2", + "mime": "^3.0.0", "nyc": "^15.1.0", - "puppeteer": "^10.4.0", - "reserve": "^1.11.7" + "puppeteer": "^11.0.0", + "reserve": "^1.12.1" }, "bin": { "ui5-test-runner": "index.js" }, "devDependencies": { "jest": "^27.3.1", - "nock": "^13.1.4", + "nock": "^13.2.1", "standard": "^16.0.4" }, "engines": { @@ -2036,9 +2036,9 @@ } }, "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dependencies": { "ms": "2.1.2" }, @@ -6232,14 +6232,14 @@ } }, "node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "bin": { "mime": "cli.js" }, "engines": { - "node": ">=4.0.0" + "node": ">=10.0.0" } }, "node_modules/mime-db": { @@ -6288,16 +6288,10 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/ms": { "version": "2.1.2", @@ -6311,9 +6305,9 @@ "dev": true }, "node_modules/nock": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.1.4.tgz", - "integrity": "sha512-hr5+mknLpIbTOXifB13lx9mAKF1zQPUCMh53Galx79ic5opvNOd55jiB0iGCp2xqh+hwnFbNE/ddBKHsJNQrbw==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.1.tgz", + "integrity": "sha512-CoHAabbqq/xZEknubuyQMjq6Lfi5b7RtK6SoNK6m40lebGp3yiMagWtIoYaw2s9sISD7wPuCfwFpivVHX/35RA==", "dev": true, "dependencies": { "debug": "^4.1.0", @@ -6326,13 +6320,35 @@ } }, "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7017,7 +7033,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -7085,34 +7100,46 @@ } }, "node_modules/puppeteer": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-10.4.0.tgz", - "integrity": "sha512-2cP8mBoqnu5gzAVpbZ0fRaobBWZM8GEUF4I1F6WbgHrKV/rz7SX8PG2wMymZgD0wo0UBlg2FBPNxlF/xlqW6+w==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-11.0.0.tgz", + "integrity": "sha512-6rPFqN1ABjn4shgOICGDBITTRV09EjXVqhDERBDKwCLz0UyBxeeBH6Ay0vQUJ84VACmlxwzOIzVEJXThcF3aNg==", "hasInstallScript": true, "dependencies": { - "debug": "4.3.1", + "debug": "4.3.2", "devtools-protocol": "0.0.901419", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.1", + "node-fetch": "2.6.5", "pkg-dir": "4.2.0", - "progress": "2.0.1", + "progress": "2.0.3", "proxy-from-env": "1.1.0", "rimraf": "3.0.2", - "tar-fs": "2.0.0", - "unbzip2-stream": "1.3.3", - "ws": "7.4.6" + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.2.3" }, "engines": { "node": ">=10.18.1" } }, - "node_modules/puppeteer/node_modules/progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", + "node_modules/puppeteer/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", "engines": { - "node": ">=0.4.0" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/react-is": { @@ -7290,9 +7317,9 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "node_modules/reserve": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/reserve/-/reserve-1.11.7.tgz", - "integrity": "sha512-SDzr6dR+fIIZ9eqxXQRhclb4mpOqqY4wMKeehYfplj1MeOCPsF/skzr8Eo/dmNZK8ijuF3PMMvYQJzoV9bfzNQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/reserve/-/reserve-1.12.1.tgz", + "integrity": "sha512-JxnVNNgWwV7FYPIKC2JgJbaVfuiJsFV90Z6fUK3KB86zvGH6cyEdIbScr4c8n0ZXxOmISnaTj4Yb3+M8tTFPZA==", "bin": { "reserve": "index.js" }, @@ -7890,14 +7917,14 @@ "dev": true }, "node_modules/tar-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", - "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dependencies": { "chownr": "^1.1.1", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" } }, "node_modules/tar-stream": { @@ -8099,9 +8126,9 @@ } }, "node_modules/unbzip2-stream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -8353,6 +8380,7 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -10033,9 +10061,9 @@ } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { "ms": "2.1.2" } @@ -13121,9 +13149,9 @@ } }, "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" }, "mime-db": { "version": "1.50.0", @@ -13159,13 +13187,10 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "ms": { "version": "2.1.2", @@ -13179,9 +13204,9 @@ "dev": true }, "nock": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.1.4.tgz", - "integrity": "sha512-hr5+mknLpIbTOXifB13lx9mAKF1zQPUCMh53Galx79ic5opvNOd55jiB0iGCp2xqh+hwnFbNE/ddBKHsJNQrbw==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.1.tgz", + "integrity": "sha512-CoHAabbqq/xZEknubuyQMjq6Lfi5b7RtK6SoNK6m40lebGp3yiMagWtIoYaw2s9sISD7wPuCfwFpivVHX/35RA==", "dev": true, "requires": { "debug": "^4.1.0", @@ -13191,9 +13216,33 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } }, "node-int64": { "version": "0.4.0", @@ -13709,8 +13758,7 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "prompts": { "version": "2.4.2", @@ -13766,28 +13814,29 @@ "dev": true }, "puppeteer": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-10.4.0.tgz", - "integrity": "sha512-2cP8mBoqnu5gzAVpbZ0fRaobBWZM8GEUF4I1F6WbgHrKV/rz7SX8PG2wMymZgD0wo0UBlg2FBPNxlF/xlqW6+w==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-11.0.0.tgz", + "integrity": "sha512-6rPFqN1ABjn4shgOICGDBITTRV09EjXVqhDERBDKwCLz0UyBxeeBH6Ay0vQUJ84VACmlxwzOIzVEJXThcF3aNg==", "requires": { - "debug": "4.3.1", + "debug": "4.3.2", "devtools-protocol": "0.0.901419", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.1", + "node-fetch": "2.6.5", "pkg-dir": "4.2.0", - "progress": "2.0.1", + "progress": "2.0.3", "proxy-from-env": "1.1.0", "rimraf": "3.0.2", - "tar-fs": "2.0.0", - "unbzip2-stream": "1.3.3", - "ws": "7.4.6" + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.2.3" }, "dependencies": { - "progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==" + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} } } }, @@ -13920,9 +13969,9 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "reserve": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/reserve/-/reserve-1.11.7.tgz", - "integrity": "sha512-SDzr6dR+fIIZ9eqxXQRhclb4mpOqqY4wMKeehYfplj1MeOCPsF/skzr8Eo/dmNZK8ijuF3PMMvYQJzoV9bfzNQ==" + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/reserve/-/reserve-1.12.1.tgz", + "integrity": "sha512-JxnVNNgWwV7FYPIKC2JgJbaVfuiJsFV90Z6fUK3KB86zvGH6cyEdIbScr4c8n0ZXxOmISnaTj4Yb3+M8tTFPZA==" }, "resolve": { "version": "1.20.0", @@ -14360,14 +14409,14 @@ } }, "tar-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", - "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "requires": { "chownr": "^1.1.1", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" } }, "tar-stream": { @@ -14529,9 +14578,9 @@ } }, "unbzip2-stream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "requires": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -14741,6 +14790,7 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, "requires": {} }, "xdg-basedir": { diff --git a/package.json b/package.json index 587d0af1..b04c32de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui5-test-runner", - "version": "1.1.2", + "version": "1.1.3", "description": "Standalone test runner for UI5", "main": "index.js", "files": [ @@ -39,14 +39,14 @@ }, "homepage": "https://github.com/ArnaudBuchholz/ui5-test-runner#readme", "dependencies": { - "mime": "^2.5.2", + "mime": "^3.0.0", "nyc": "^15.1.0", - "puppeteer": "^10.4.0", - "reserve": "^1.11.7" + "puppeteer": "^11.0.0", + "reserve": "^1.12.1" }, "devDependencies": { "jest": "^27.3.1", - "nock": "^13.1.4", + "nock": "^13.2.1", "standard": "^16.0.4" }, "standard": { @@ -58,6 +58,9 @@ ] }, "jest": { + "setupFilesAfterEnv": [ + "./__mocks__/setup.js" + ], "collectCoverage": true, "collectCoverageFrom": [ "src/*.js" diff --git a/src/coverage.js b/src/coverage.js index 0f44087e..32dd587b 100644 --- a/src/coverage.js +++ b/src/coverage.js @@ -44,6 +44,15 @@ async function instrument (job) { await createDir(join(job.covTempDir, 'settings')) const settings = JSON.parse((await readFile(job.covSettings)).toString()) settings.cwd = job.cwd + if (!settings.exclude) { + settings.exclude = [] + } + settings.exclude.push(join(job.covTempDir, '**')) + if (job.cache) { + settings.exclude.push(join(job.cache, '**')) + } + settings.exclude.push(join(job.tstReportDir, '**')) + settings.exclude.push(join(job.covReportDir, '**')) await writeFile(job.nycSettingsPath, JSON.stringify(settings)) await nyc('instrument', job.webapp, join(job.covTempDir, 'instrumented'), '--nycrc-path', job.nycSettingsPath) } diff --git a/src/endpoints.js b/src/endpoints.js index 3e7311cb..3f5f47f0 100644 --- a/src/endpoints.js +++ b/src/endpoints.js @@ -130,7 +130,7 @@ module.exports = job => { job.testPages[url] = page }) }, { - // Endpoint to receive QUnit.testDone + // Endpoint to receive QUnit.log match: '^/_/QUnit/log', custom: synchronousEndpoint(async (url, report) => { const page = job.testPages[url] diff --git a/src/job.js b/src/job.js index 6cfa9b8c..b4478da5 100644 --- a/src/job.js +++ b/src/job.js @@ -1,5 +1,6 @@ 'use strict' +const { accessSync } = require('fs') const { join, isAbsolute } = require('path') const output = require('./output') @@ -12,6 +13,7 @@ function allocate (cwd) { libs: [], cache: '', webapp: 'webapp', + testsuite: 'test/testsuite.qunit.html', pageFilter: '', pageParams: '', pageTimeout: 0, @@ -37,6 +39,14 @@ function allocate (cwd) { } } +function checkAccess (path, label) { + try { + accessSync(path) + } catch (error) { + throw new Error(`Unable to access ${label}, check your settings`) + } +} + function finalize (job) { Object.keys(job) .filter(name => name.startsWith('!')) @@ -57,9 +67,15 @@ function finalize (job) { 'webapp,browser,tstReportDir,covSettings,covTempDir,covReportDir' .split(',') .forEach(setting => updateToAbsolute(setting)) + checkAccess(job.webapp, 'webapp folder') + checkAccess(job.browser, 'browser command') + + const testsuitePath = toAbsolute(job.testsuite, job.webapp) + checkAccess(testsuitePath, 'testsuite') job.libs.forEach(libMapping => { libMapping.source = toAbsolute(libMapping.source) + checkAccess(libMapping.source, `lib mapping of ${libMapping.relative}`) }) if (job.parallel <= 0) { diff --git a/src/output.js b/src/output.js index 2c00177d..b30ad093 100644 --- a/src/output.js +++ b/src/output.js @@ -188,7 +188,7 @@ module.exports = { console.error(`Unable to cache '${path}' (status ${statusCode})`) }, genericError (error) { - console.error('An unexpected error occurred', error) + console.error('An unexpected error occurred :', error.message || error) }, unhandled () { console.warn('Some requests are not handled properly, check the unhandled.txt report for more info') diff --git a/src/tests.js b/src/tests.js index 1e9acbb4..f0b9217e 100644 --- a/src/tests.js +++ b/src/tests.js @@ -26,7 +26,7 @@ async function extractTestPages (job) { await saveJob(job) job.status = 'Extracting test pages' job.testPageUrls = [] - await start(job, '/test/testsuite.qunit.html') + await start(job, '/' + job.testsuite) if (job.testPageUrls.length === 0) { output.noTestPageFound() job.failed = true