From 2160789f602648c077a720632b85437e0bd53381 Mon Sep 17 00:00:00 2001 From: Florian Vogt Date: Fri, 19 Aug 2022 11:10:10 +0200 Subject: [PATCH] [INTERNAL] use eslint-plugin-ava and cleanup test-suite --- .eslintrc.js | 10 +- package-lock.json | 271 ++++++ package.json | 1 + test/lib/server/acceptRemoteConnections.js | 17 +- test/lib/server/h2.js | 17 +- test/lib/server/main.js | 822 +++++++++--------- .../server/middleware/MiddlewareManager.js | 114 +-- test/lib/server/middleware/MiddlewareUtil.js | 26 +- .../server/middleware/middlewareRepository.js | 6 +- test/lib/server/middleware/nonReadRequests.js | 2 +- test/lib/server/middleware/serveIndex.js | 219 +++-- test/lib/server/middleware/serveResources.js | 261 +++--- test/lib/server/middleware/serveThemes.js | 4 + test/lib/server/middleware/testRunner.js | 2 +- test/lib/server/middleware/versionInfo.js | 2 +- test/lib/server/ports.js | 257 +++--- test/lib/server/sslUtil.js | 48 +- 17 files changed, 1158 insertions(+), 921 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b1b5dfca..a802f3d4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,9 +3,10 @@ module.exports = { "node": true, "es2021": true }, - "extends": ["eslint:recommended", "google"], + "extends": ["eslint:recommended", "plugin:ava/recommended", "google"], "plugins": [ - "jsdoc" + "jsdoc", + "ava" ], "rules": { "indent": [ @@ -64,7 +65,10 @@ module.exports = { "jsdoc/require-returns": 0, "jsdoc/require-returns-description": 0, "jsdoc/require-returns-type": 2, - "jsdoc/valid-types": 0 + "jsdoc/valid-types": 0, + // ava/assertion-arguments reports concatenated strings in a assertion message as an issue + // See: https://github.com/avajs/eslint-plugin-ava/issues/332 + "ava/assertion-arguments": 0 }, "settings": { "jsdoc": { diff --git a/package-lock.json b/package-lock.json index 53849b12..5ffa292e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "docdash": "^1.2.0", "eslint": "^8.7.0", "eslint-config-google": "^0.14.0", + "eslint-plugin-ava": "^13.0.2", "eslint-plugin-jsdoc": "^37.6.3", "jsdoc": "^3.6.7", "mock-require": "^3.0.3", @@ -3228,6 +3229,18 @@ "once": "^1.4.0" } }, + "node_modules/enhance-visitors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", + "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", + "dev": true, + "dependencies": { + "lodash": "^4.13.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -3479,6 +3492,119 @@ "eslint": ">=5.16.0" } }, + "node_modules/eslint-plugin-ava": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-ava/-/eslint-plugin-ava-13.2.0.tgz", + "integrity": "sha512-i5B5izsEdERKQLruk1nIWzTTE7C26/ju8qQf7JeyRv32XT2lRMW0zMFZNhIrEf5/5VvpSz2rqrV7UcjClGbKsw==", + "dev": true, + "dependencies": { + "enhance-visitors": "^1.0.0", + "eslint-utils": "^3.0.0", + "espree": "^9.0.0", + "espurify": "^2.1.1", + "import-modules": "^2.1.0", + "micro-spelling-correcter": "^1.1.1", + "pkg-dir": "^5.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=12.22 <13 || >=14.17 <15 || >=16.4" + }, + "peerDependencies": { + "eslint": ">=7.22.0" + } + }, + "node_modules/eslint-plugin-ava/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-ava/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-ava/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-ava/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-ava/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-ava/node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-ava/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/eslint-plugin-jsdoc": { "version": "37.9.7", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.9.7.tgz", @@ -3623,6 +3749,12 @@ "node": ">=4" } }, + "node_modules/espurify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true + }, "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -4845,6 +4977,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5937,6 +6081,12 @@ "node": ">= 0.6" } }, + "node_modules/micro-spelling-correcter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -9856,6 +10006,18 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.3.1.tgz", "integrity": "sha512-7RbCXegyu6DykWPWU0YEtW8gFJH8KBL2d5l2fqB0XpkH0Y9rk59YSSWpzEv7yNJBGAouPc67h3kkq0CZkpBdFw==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -12371,6 +12533,15 @@ "once": "^1.4.0" } }, + "enhance-visitors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", + "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", + "dev": true, + "requires": { + "lodash": "^4.13.1" + } + }, "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -12608,6 +12779,82 @@ "dev": true, "requires": {} }, + "eslint-plugin-ava": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-ava/-/eslint-plugin-ava-13.2.0.tgz", + "integrity": "sha512-i5B5izsEdERKQLruk1nIWzTTE7C26/ju8qQf7JeyRv32XT2lRMW0zMFZNhIrEf5/5VvpSz2rqrV7UcjClGbKsw==", + "dev": true, + "requires": { + "enhance-visitors": "^1.0.0", + "eslint-utils": "^3.0.0", + "espree": "^9.0.0", + "espurify": "^2.1.1", + "import-modules": "^2.1.0", + "micro-spelling-correcter": "^1.1.1", + "pkg-dir": "^5.0.0", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, "eslint-plugin-jsdoc": { "version": "37.9.7", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.9.7.tgz", @@ -12680,6 +12927,12 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "espurify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true + }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -13652,6 +13905,12 @@ "resolve-cwd": "^3.0.0" } }, + "import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -14492,6 +14751,12 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, + "micro-spelling-correcter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -17591,6 +17856,12 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.3.1.tgz", "integrity": "sha512-7RbCXegyu6DykWPWU0YEtW8gFJH8KBL2d5l2fqB0XpkH0Y9rk59YSSWpzEv7yNJBGAouPc67h3kkq0CZkpBdFw==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index af9db07d..85682e8d 100644 --- a/package.json +++ b/package.json @@ -138,6 +138,7 @@ "eslint": "^8.7.0", "eslint-config-google": "^0.14.0", "eslint-plugin-jsdoc": "^37.6.3", + "eslint-plugin-ava": "^13.0.2", "jsdoc": "^3.6.7", "mock-require": "^3.0.3", "nyc": "^15.1.0", diff --git a/test/lib/server/acceptRemoteConnections.js b/test/lib/server/acceptRemoteConnections.js index 705f095a..d0dda8e0 100644 --- a/test/lib/server/acceptRemoteConnections.js +++ b/test/lib/server/acceptRemoteConnections.js @@ -33,13 +33,12 @@ test.after(() => { }); }); -test("Get resource from application.a (/index.html) with enabled remote connection", (t) => { - return request.get("/index.html").then((res) => { - if (res.error) { - t.fail(res.error.text); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /html/, "Correct content type"); - t.regex(res.text, /Application A<\/title>/, "Correct response"); - }); +test("Get resource from application.a (/index.html) with enabled remote connection", async (t) => { + const res = await request.get("/index.html"); + if (res.error) { + t.fail(res.error.text); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /html/, "Correct content type"); + t.regex(res.text, /<title>Application A<\/title>/, "Correct response"); }); diff --git a/test/lib/server/h2.js b/test/lib/server/h2.js index 728ec330..4517b67c 100644 --- a/test/lib/server/h2.js +++ b/test/lib/server/h2.js @@ -41,13 +41,12 @@ test.after(() => { }); }); -test("Get resource from application.a (/index.html)", (t) => { - return request.get("/index.html").then((res) => { - if (res.error) { - t.fail(res.error.text); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /html/, "Correct content type"); - t.regex(res.text, /<title>Application A<\/title>/, "Correct response"); - }); +test("Get resource from application.a (/index.html)", async (t) => { + const res = await request.get("/index.html"); + if (res.error) { + t.fail(res.error.text); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /html/, "Correct content type"); + t.regex(res.text, /<title>Application A<\/title>/, "Correct response"); }); diff --git a/test/lib/server/main.js b/test/lib/server/main.js index 8eebc277..6dcac237 100644 --- a/test/lib/server/main.js +++ b/test/lib/server/main.js @@ -31,250 +31,234 @@ test.after.always(() => { }); }); -test("Get resource from application.a (/index.html)", (t) => { - return request.get("/index.html").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /html/, "Correct content type"); - t.regex(res.text, /<title>Application A<\/title>/, "Correct response"); - }); +test("Get resource from application.a (/index.html)", async (t) => { + const res = await request.get("/index.html"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /html/, "Correct content type"); + t.regex(res.text, /<title>Application A<\/title>/, "Correct response"); }); -test("Get resource from application.a with not replaced version placeholder(/versionTest.html)", (t) => { - return request.get("/versionTest.html").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /html/, "Correct content type"); - t.regex(res.text, /<title>Not replaced: \${version}<\/title>/, "Correct response"); - }); +test("Get resource from application.a with not replaced version placeholder(/versionTest.html)", async (t) => { + const res = await request.get("/versionTest.html"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /html/, "Correct content type"); + t.regex(res.text, /<title>Not replaced: \${version}<\/title>/, "Correct response"); }); -test("Get resource from application.a with replaced version placeholder (/versionTest.js)", (t) => { - return request.get("/versionTest.js").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /application\/javascript/, "Correct content type"); - t.deepEqual(res.text, "console.log(`1.0.0`);\n", "Correct response"); - }); +test("Get resource from application.a with replaced version placeholder (/versionTest.js)", async (t) => { + const res = await request.get("/versionTest.js"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /application\/javascript/, "Correct content type"); + t.is(res.text, "console.log(`1.0.0`);\n", "Correct response"); }); -test("Get resource from application.a (/i18n/i18n.properties) with correct content-type", (t) => { - return request.get("/i18n/i18n.properties").then((res) => { - if (res.error) { - throw new Error(res.error.text); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.headers["content-type"], "application/octet-stream", "Correct content type"); - t.deepEqual(res.body.toString(), "showHelloButtonText=Say Hello!", "Correct response"); - }); +test("Get resource from application.a (/i18n/i18n.properties) with correct content-type", async (t) => { + const res = await request.get("/i18n/i18n.properties"); + if (res.error) { + throw new Error(res.error.text); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.headers["content-type"], "application/octet-stream", "Correct content type"); + t.is(res.body.toString(), "showHelloButtonText=Say Hello!", "Correct response"); }); -test("Get resource from application.a (/i18n/i18n_de.properties) with correct content-type'", (t) => { - return request.get("/i18n/i18n_de.properties") - .responseType("arraybuffer") - .then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.headers["content-type"], "application/octet-stream", - "Correct content type"); - - t.deepEqual(res.body.toString(), "showHelloButtonText=Say \\u00e4!", "Correct response"); - // Because it took so long to figure this out I keep the below line. It is equivalent to the deepEqual above - // t.deepEqual(res.body.toString("latin1"), - // Buffer.from("showHelloButtonText=Say \u00e4!", "latin1").toString("latin1"), - // "Correct response"); - }); +test("Get resource from application.a (/i18n/i18n_de.properties) with correct content-type'", async (t) => { + const res = await request.get("/i18n/i18n_de.properties").responseType("arraybuffer"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.headers["content-type"], "application/octet-stream", + "Correct content type"); + t.is(res.body.toString(), "showHelloButtonText=Say \\u00e4!", "Correct response"); + // Because it took so long to figure this out I keep the below line. It is equivalent to the "is" above + // t.is(res.body.toString("latin1"), + // Buffer.from("showHelloButtonText=Say \u00e4!", "latin1").toString("latin1"), + // "Correct response"); }); -test("Get resource from library.a (/resources/library/a/.library)", (t) => { - return request.get("/resources/library/a/.library").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - }); +test("Get resource from library.a (/resources/library/a/.library)", async (t) => { + const res = await request.get("/resources/library/a/.library"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); }); -test("Get resource from library.b (/resources/library/b/.library)", (t) => { - return request.get("/resources/library/b/.library").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - }); +test("Get resource from library.b (/resources/library/b/.library)", async (t) => { + const res = await request.get("/resources/library/b/.library"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); }); -test("Get resource from library.c (/resources/library/c/.library)", (t) => { - return request.get("/resources/library/c/.library").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - }); +test("Get resource from library.c (/resources/library/c/.library)", async (t) => { + const res = await request.get("/resources/library/c/.library"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); }); -test("Get resource from library.d (/resources/library/d/.library)", (t) => { - return request.get("/resources/library/d/.library").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - }); +test("Get resource from library.d (/resources/library/d/.library)", async (t) => { + const res = await request.get("/resources/library/d/.library"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); }); -test("Get app_pages from discovery middleware (/discovery/app_pages)", (t) => { - return request.get("/discovery/app_pages").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.body, { - "app_pages": [ - { - "entry": "index.html" - }, - { - "entry": "versionTest.html" - } - ] - }, "Correct response"); - }); +test("Get app_pages from discovery middleware (/discovery/app_pages)", async (t) => { + const res = await request.get("/discovery/app_pages"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.deepEqual(res.body, { + "app_pages": [ + { + "entry": "index.html" + }, + { + "entry": "versionTest.html" + } + ] + }, "Correct response"); }); -test("Get all_libs from discovery middleware (/discovery/all_libs)", (t) => { - return request.get("/discovery/all_libs").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.body, { - "all_libs": [ - { - "entry": "library/a" - }, - { - "entry": "library/b" - }, - { - "entry": "library/c" - }, - { - "entry": "library/d" - } - ] - }, "Correct response"); - }); +test("Get all_libs from discovery middleware (/discovery/all_libs)", async (t) => { + const res = await request.get("/discovery/all_libs"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.deepEqual(res.body, { + "all_libs": [ + { + "entry": "library/a" + }, + { + "entry": "library/b" + }, + { + "entry": "library/c" + }, + { + "entry": "library/d" + } + ] + }, "Correct response"); }); -test("Get all_tests from discovery middleware (/discovery/all_tests)", (t) => { - return request.get("/discovery/all_tests").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.body, { - "all_tests": [ - { - "lib": "library.a", - "name": "Test.html", - "url": "../library/a/Test.html" - }, - { - "lib": "library.b", - "name": "Test.html", - "url": "../library/b/Test.html" - }, - { - "lib": "library.d", - "name": "Test.html", - "url": "../library/d/Test.html" - } - ] - }, "Correct response"); - }); +test("Get all_tests from discovery middleware (/discovery/all_tests)", async (t) => { + const res = await request.get("/discovery/all_tests"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.deepEqual(res.body, { + "all_tests": [ + { + "lib": "library.a", + "name": "Test.html", + "url": "../library/a/Test.html" + }, + { + "lib": "library.b", + "name": "Test.html", + "url": "../library/b/Test.html" + }, + { + "lib": "library.d", + "name": "Test.html", + "url": "../library/d/Test.html" + } + ] + }, "Correct response"); }); -test("Get sap-ui-version.json from versionInfo middleware (/resources/sap-ui-version.json)", (t) => { - return request.get("/resources/sap-ui-version.json").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - - const buildTimestamp = res.body.buildTimestamp; - t.deepEqual(res.body, { - "name": "application.a", - "version": "1.0.0", - "buildTimestamp": buildTimestamp, - "scmRevision": "", - "libraries": [ - { - name: "library.a", - manifestHints: { - dependencies: { - libs: { - "library.d": {} - } +test("Get sap-ui-version.json from versionInfo middleware (/resources/sap-ui-version.json)", async (t) => { + const res = await request.get("/resources/sap-ui-version.json"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + + const buildTimestamp = res.body.buildTimestamp; + t.deepEqual(res.body, { + "name": "application.a", + "version": "1.0.0", + "buildTimestamp": buildTimestamp, + "scmRevision": "", + "libraries": [ + { + name: "library.a", + manifestHints: { + dependencies: { + libs: { + "library.d": {} } - }, - version: "1.0.0", - buildTimestamp, - scmRevision: "" + } }, - { - name: "library.b", - manifestHints: { - dependencies: { - libs: { - "library.d": {} - } + version: "1.0.0", + buildTimestamp, + scmRevision: "" + }, + { + name: "library.b", + manifestHints: { + dependencies: { + libs: { + "library.d": {} } - }, - version: "1.0.0", - buildTimestamp, - scmRevision: "" + } }, - { - name: "library.c", - manifestHints: { - dependencies: { - libs: { - "library.d": {} - } + version: "1.0.0", + buildTimestamp, + scmRevision: "" + }, + { + name: "library.c", + manifestHints: { + dependencies: { + libs: { + "library.d": {} } - }, - version: "1.0.0", - buildTimestamp, - scmRevision: "" + } }, - { - name: "library.d", - version: "1.0.0", - buildTimestamp, - scmRevision: "" - } - ] - }, "Correct response"); - }); + version: "1.0.0", + buildTimestamp, + scmRevision: "" + }, + { + name: "library.d", + version: "1.0.0", + buildTimestamp, + scmRevision: "" + } + ] + }, "Correct response"); }); -test("Get library.css from theme middleware (/resources/library/a/themes/base/library.css)", (t) => { - return request.get("/resources/library/a/themes/base/library.css").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /css/, "Correct content type"); - t.deepEqual(res.text, `.library-a-foo { +test("Get library.css from theme middleware (/resources/library/a/themes/base/library.css)", async (t) => { + const res = await request.get("/resources/library/a/themes/base/library.css"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /css/, "Correct content type"); + t.is(res.text, `.library-a-foo { color: #fafad2; padding: 1px 2px 3px 4px; } @@ -282,17 +266,16 @@ test("Get library.css from theme middleware (/resources/library/a/themes/base/li /* Inline theming parameters */ #sap-ui-theme-library\\.a{background-image:url('data:text/plain;utf-8,%7B%22libraryAColor1%22%3A%22%23fafad2%22%7D')} `, "Correct response"); - }); }); -test("Get library-RTL.css from theme middleware (/resources/library/a/themes/base/library-RTL.css)", (t) => { - return request.get("/resources/library/a/themes/base/library-RTL.css").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /css/, "Correct content type"); - t.deepEqual(res.text, `.library-a-foo { +test("Get library-RTL.css from theme middleware (/resources/library/a/themes/base/library-RTL.css)", async (t) => { + const res = await request.get("/resources/library/a/themes/base/library-RTL.css"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /css/, "Correct content type"); + t.is(res.text, `.library-a-foo { color: #fafad2; padding: 1px 4px 3px 2px; } @@ -300,86 +283,81 @@ test("Get library-RTL.css from theme middleware (/resources/library/a/themes/bas /* Inline theming parameters */ #sap-ui-theme-library\\.a{background-image:url('data:text/plain;utf-8,%7B%22libraryAColor1%22%3A%22%23fafad2%22%7D')} `, "Correct response"); - }); }); test("Get library-parameters.json from theme middleware (/resources/library/a/themes/base/library-parameters.json)", - (t) => { - return request.get("/resources/library/a/themes/base/library-parameters.json").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /json/, "Correct content type"); - t.deepEqual(res.body, { - libraryAColor1: "#fafad2" - }, "Correct response"); - }); + async (t) => { + const res = await request.get("/resources/library/a/themes/base/library-parameters.json"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /json/, "Correct content type"); + t.deepEqual(res.body, { + libraryAColor1: "#fafad2" + }, "Correct response"); }); test("Get css_variables.source.less from theme middleware (/resources/library/a/themes/base/css_variables.source.less)", - (t) => { - return request.get("/resources/library/a/themes/base/css_variables.source.less").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /less/, "Correct content type"); - t.deepEqual(res.text, `@libraryAColor1: #fafad2; + async (t) => { + const res = await request.get("/resources/library/a/themes/base/css_variables.source.less"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /less/, "Correct content type"); + t.is(res.text, `@libraryAColor1: #fafad2; :root { --libraryAColor1: @libraryAColor1; } `, "Correct response"); - }); }); -test("Get css_variables.css from theme middleware (/resources/library/a/themes/base/css_variables.css)", (t) => { - return request.get("/resources/library/a/themes/base/css_variables.css").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /css/, "Correct content type"); - t.deepEqual(res.text, `:root { +test("Get css_variables.css from theme middleware (/resources/library/a/themes/base/css_variables.css)", async (t) => { + const res = await request.get("/resources/library/a/themes/base/css_variables.css"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /css/, "Correct content type"); + t.is(res.text, `:root { --libraryAColor1: #fafad2; } /* Inline theming parameters */ #sap-ui-theme-library\\.a{background-image:url('data:text/plain;utf-8,%7B%22libraryAColor1%22%3A%22%23fafad2%22%7D')} `, "Correct response"); - }); }); -test("Get library_skeleton.css from theme middleware (/resources/library/a/themes/base/library_skeleton.css)", (t) => { - return request.get("/resources/library/a/themes/base/library_skeleton.css").then((res) => { +test("Get library_skeleton.css from theme middleware (/resources/library/a/themes/base/library_skeleton.css)", + async (t) => { + const res = await request.get("/resources/library/a/themes/base/library_skeleton.css"); if (res.error) { throw new Error(res.error); } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.statusCode, 200, "Correct HTTP status code"); t.regex(res.headers["content-type"], /css/, "Correct content type"); - t.deepEqual(res.text, `.library-a-foo { + t.is(res.text, `.library-a-foo { color: var(--libraryAColor1); padding: 1px 2px 3px 4px; } `, "Correct response"); }); -}); test("Get library_skeleton-RTL.css from theme middleware (/resources/library/a/themes/base/library_skeleton-RTL.css)", - (t) => { - return request.get("/resources/library/a/themes/base/library_skeleton-RTL.css").then((res) => { - if (res.error) { - throw new Error(res.error); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.regex(res.headers["content-type"], /css/, "Correct content type"); - t.deepEqual(res.text, `.library-a-foo { + async (t) => { + const res = await request.get("/resources/library/a/themes/base/library_skeleton-RTL.css"); + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + t.regex(res.headers["content-type"], /css/, "Correct content type"); + t.is(res.text, `.library-a-foo { color: var(--libraryAColor1); padding: 1px 4px 3px 2px; } `, "Correct response"); - }); }); test("Stop server", async (t) => { @@ -390,38 +368,38 @@ test("Stop server", async (t) => { cwd: "./test/fixtures/application.a" }); - return server.serve(graph, { + const serveResult = await server.serve(graph, { port: port - }).then((serveResult) => { - return request.get("/resources/library/a/themes/base/library-parameters.json").then((res) => { - if (res.error) { - throw new Error(res.error); + }); + + const res = await request.get("/resources/library/a/themes/base/library-parameters.json"); + + if (res.error) { + throw new Error(res.error); + } + t.is(res.statusCode, 200, "Correct HTTP status code"); + + await new Promise((resolve, reject) => { + serveResult.close((error) => { + if (error) { + reject(error); + } else { + t.pass("Server closing"); + resolve(); } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - return serveResult; - }); - }).then((serveResult) => { - return new Promise((resolve, reject) => { - serveResult.close((error) => { - if (error) { - reject(error); - } else { - t.pass("Server closing"); - resolve(); - } - }); - }); - }).then(() => { - return request.get("/resources/library/a/themes/base/library-parameters.json").then(() => { - t.fail("Server was not closed!"); - }).catch(() => { - t.pass("Server was closed properly."); }); }); + + try { + await request.get("/resources/library/a/themes/base/library-parameters.json"); + t.fail("Server was not closed!"); + } catch { + t.pass("Server was closed properly."); + } }); -test("CSP (defaults)", (t) => { - return Promise.all([ +test("CSP (defaults)", async (t) => { + await Promise.all([ request.get("/index.html").then((res) => { t.is(res.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); @@ -492,98 +470,96 @@ test("CSP (defaults)", (t) => { test("CSP (sap policies)", async (t) => { const port = 3400; const request = supertest(`http://localhost:${port}`); - let localServeResult; const graph = await generateProjectGraph({ cwd: "./test/fixtures/application.a" }); - return server.serve(graph, { + const serveResult = await server.serve(graph, { port, sendSAPTargetCSP: true, simpleIndex: false - }).then((serveResult) => { - localServeResult = serveResult; - return Promise.all([ - request.get("/index.html").then((res) => { - t.is(res.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should contain the 1st default policy"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1").then((res) => { - t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); - t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1:report-only").then((res) => { - t.is(res.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2").then((res) => { - t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); - t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, - "header should should have the expected content"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only").then((res) => { - t.is(res.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should have the expected content"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;").then((res) => { - t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); - t.regex(res.headers["content-security-policy"], /default-src\s+http:\s*;/, - "header should contain the configured policy"); - t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:report-only").then((res) => { - t.is(res.headers["content-security-policy"], undefined, - "response must not have enforcing csp header"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, - "header should contain the configured policy"); - t.regex(res.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }), - request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:ro").then((res) => { - t.is(res.headers["content-security-policy"], undefined, - "response must not have enforcing csp header"); - t.truthy(res.headers["content-security-policy-report-only"], - "response should have report-only csp header"); - t.regex(res.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, - "header should contain the configured policy"); - t.regex(res.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); - }) - ]); - }).then(() => { - return new Promise((resolve, reject) => { - localServeResult.close((error) => { - if (error) { - reject(error); - } else { - t.pass("Server closing"); - resolve(); - } - }); + }); + + const [result1, result2, result3, result4, result5, result6, result7, result8] = await Promise.all([ + request.get("/index.html"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1:report-only"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only"), + request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;"), + request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:report-only"), + request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:ro") + ]); + + t.is(result1.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); + t.truthy(result1.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result1.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, + "header should contain the 1st default policy"); + t.regex(result1.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.truthy(result2.headers["content-security-policy"], "response should have enforcing csp header"); + t.regex(result2.headers["content-security-policy"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, + "header should should have the expected content"); + t.truthy(result2.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result2.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.is(result3.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); + t.truthy(result3.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result3.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, + "header should should have the expected content"); + t.regex(result3.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.truthy(result4.headers["content-security-policy"], "response should have enforcing csp header"); + t.regex(result4.headers["content-security-policy"], /script-src\s+'self'\s*;/, + "header should should have the expected content"); + t.regex(result4.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.is(result5.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); + t.truthy(result5.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result5.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should have the expected content"); + + t.truthy(result6.headers["content-security-policy"], "response should have enforcing csp header"); + t.regex(result6.headers["content-security-policy"], /default-src\s+http:\s*;/, + "header should contain the configured policy"); + t.regex(result6.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.is(result7.headers["content-security-policy"], undefined, + "response must not have enforcing csp header"); + t.truthy(result7.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result7.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, + "header should contain the configured policy"); + t.regex(result7.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + t.is(result8.headers["content-security-policy"], undefined, + "response must not have enforcing csp header"); + t.truthy(result8.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result8.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, + "header should contain the configured policy"); + t.regex(result8.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, + "header should contain the 2nd default policy"); + + await new Promise((resolve, reject) => { + serveResult.close((error) => { + if (error) { + reject(error); + } else { + t.pass("Server closing"); + resolve(); + } }); }); }); @@ -591,55 +567,53 @@ test("CSP (sap policies)", async (t) => { test("CSP serveCSPReports", async (t) => { const port = 3450; const request = supertest(`http://localhost:${port}`); - let localServeResult; const graph = await generateProjectGraph({ cwd: "./test/fixtures/application.a" }); - return server.serve(graph, { + const serveResult = await server.serve(graph, { port, serveCSPReports: true, simpleIndex: false - }).then((serveResult) => { - localServeResult = serveResult; - const cspReport = { - "csp-report": { - "document-uri": "https://otherserver:8080/index.html", - "referrer": "", - "violated-directive": "script-src-elem", - "effective-directive": "script-src-elem", - "original-policy": "default-src 'self' myserver:443; report-uri /report-csp-violation", - "disposition": "report", - "blocked-uri": "inline", - "line-number": 17, - "source-file": "https://otherserver:8080/index.html", - "status-code": 0, - "script-sample": "" + }); + + const cspReport = { + "csp-report": { + "document-uri": "https://otherserver:8080/index.html", + "referrer": "", + "violated-directive": "script-src-elem", + "effective-directive": "script-src-elem", + "original-policy": "default-src 'self' myserver:443; report-uri /report-csp-violation", + "disposition": "report", + "blocked-uri": "inline", + "line-number": 17, + "source-file": "https://otherserver:8080/index.html", + "status-code": 0, + "script-sample": "" + } + }; + + await request.post("/.ui5/csp/report.csplog") + .set("Content-Type", "application/csp-report") + // to allow setting the content type the argument for sending must be a string + .send(JSON.stringify(cspReport)) + .expect(200); + + const res = await request.get("/.ui5/csp/csp-reports.json"); + + t.true(typeof res.body === "object", "the body is an object"); + t.true(Array.isArray(res.body["csp-reports"]), "csp-reports is an array"); + t.is(res.body["csp-reports"].length, 1, "one csp report in result"); + + await new Promise((resolve, reject) => { + serveResult.close((error) => { + if (error) { + reject(error); + } else { + t.pass("Server closing"); + resolve(); } - }; - return request.post("/.ui5/csp/report.csplog") - .set("Content-Type", "application/csp-report") - // to allow setting the content type the argument for sending must be a string - .send(JSON.stringify(cspReport)) - .expect(200); - }).then(() => { - return request.get("/.ui5/csp/csp-reports.json") - .then((res) => { - t.true(typeof res.body === "object", "the body is an object"); - t.true(Array.isArray(res.body["csp-reports"]), "csp-reports is an array"); - t.is(res.body["csp-reports"].length, 1, "one csp report in result"); - }); - }).then(() => { - return new Promise((resolve, reject) => { - localServeResult.close((error) => { - if (error) { - reject(error); - } else { - t.pass("Server closing"); - resolve(); - } - }); }); }); }); @@ -685,31 +659,31 @@ test("CSP with ignore paths", async (t) => { }); }); -test("Get index of resources", (t) => { - return Promise.all([ +test("Get index of resources", async (t) => { + await Promise.all([ request.get("").then((res) => { - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.statusCode, 200, "Correct HTTP status code"); t.is(res.headers["content-type"], "text/html; charset=utf-8", "Correct content type"); t.is(/<title>(.*)<\/title>/i.exec(res.text)[1], "Index of /", "Found correct title"); - t.deepEqual(res.text.match(/<li/g).length, 9, "Found correct amount of <li> elements"); + t.is(res.text.match(/<li/g).length, 9, "Found correct amount of <li> elements"); }), request.get("/resources").then((res) => { - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.statusCode, 200, "Correct HTTP status code"); t.is(res.headers["content-type"], "text/html; charset=utf-8", "Correct content type"); t.is(/<title>(.*)<\/title>/i.exec(res.text)[1], "Index of /resources", "Found correct title"); - t.deepEqual(res.text.match(/<li/g).length, 2, "Found correct amount of <li> elements"); + t.is(res.text.match(/<li/g).length, 2, "Found correct amount of <li> elements"); }), request.get("/resources/").then((res) => { - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); + t.is(res.statusCode, 200, "Correct HTTP status code"); t.is(res.headers["content-type"], "text/html; charset=utf-8", "Correct content type"); t.is(/<title>(.*)<\/title>/i.exec(res.text)[1], "Index of /resources/", "Found correct title"); - t.deepEqual(res.text.match(/<li/g).length, 2, "Found correct amount of <li> elements"); + t.is(res.text.match(/<li/g).length, 2, "Found correct amount of <li> elements"); }), request.get("/not-existing-folder").then((res) => { - t.deepEqual(res.statusCode, 404, "Correct HTTP status code"); + t.is(res.statusCode, 404, "Correct HTTP status code"); t.is(res.headers["content-type"], "text/html; charset=utf-8", "Correct content type"); t.is(/<title>(.*)<\/title>/i.exec(res.text)[1], "Error", "Found correct title"); - t.deepEqual(res.text.match(/<pre/g).length, 1, "Found correct amount of <pre> elements"); + t.is(res.text.match(/<pre/g).length, 1, "Found correct amount of <pre> elements"); }) ]); }); diff --git a/test/lib/server/middleware/MiddlewareManager.js b/test/lib/server/middleware/MiddlewareManager.js index cbcb86f5..baae86a5 100644 --- a/test/lib/server/middleware/MiddlewareManager.js +++ b/test/lib/server/middleware/MiddlewareManager.js @@ -3,18 +3,18 @@ const sinon = require("sinon"); const MiddlewareManager = require("../../../../lib/middleware/MiddlewareManager"); const middlewareRepository = require("../../../../lib/middleware/middlewareRepository"); -test("Missing parameters", async (t) => { +test("Missing parameters", (t) => { const err = t.throws(() => { new MiddlewareManager({ graph: {}, resources: {} }); }); - t.deepEqual(err.message, "[MiddlewareManager]: One or more mandatory parameters not provided", + t.is(err.message, "[MiddlewareManager]: One or more mandatory parameters not provided", "Threw error with correct message"); }); -test("Correct parameters", async (t) => { +test("Correct parameters", (t) => { t.notThrows(() => { new MiddlewareManager({ graph: {}, @@ -51,11 +51,11 @@ test("applyMiddleware", async (t) => { }; await middlewareManager.applyMiddleware(app); - t.deepEqual(addStandardMiddlewareStub.callCount, 1, "addStandardMiddleware got called once"); - t.deepEqual(addCustomMiddlewareStub.callCount, 1, "addCustomMiddleware got called once"); - t.deepEqual(appUseStub.callCount, 1, "app.use got called once"); - t.deepEqual(appUseStub.getCall(0).args[0], "/myMountPath", "app.use got called with correct mount path parameter"); - t.deepEqual(appUseStub.getCall(0).args[1], "myMiddleware", "app.use got called with correct middleware parameter"); + t.is(addStandardMiddlewareStub.callCount, 1, "addStandardMiddleware got called once"); + t.is(addCustomMiddlewareStub.callCount, 1, "addCustomMiddleware got called once"); + t.is(appUseStub.callCount, 1, "app.use got called once"); + t.is(appUseStub.getCall(0).args[0], "/myMountPath", "app.use got called with correct mount path parameter"); + t.is(appUseStub.getCall(0).args[1], "myMiddleware", "app.use got called with correct middleware parameter"); }); test("addMiddleware: Adding already added middleware produces unique middleware name", async (t) => { @@ -78,13 +78,13 @@ test("addMiddleware: Adding already added middleware produces unique middleware mountPath: "/goose" }); t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map with unique name"); - t.deepEqual(middlewareManager.middleware["serveIndex"].mountPath, "/pony", + t.is(middlewareManager.middleware["serveIndex"].mountPath, "/pony", "Middleware got added correct mount path"); t.truthy(middlewareManager.middleware["serveIndex--1"], "Middleware got added to internal map with unique name"); - t.deepEqual(middlewareManager.middleware["serveIndex--1"].mountPath, "/seagull", + t.is(middlewareManager.middleware["serveIndex--1"].mountPath, "/seagull", "Middleware got added correct mount path"); t.truthy(middlewareManager.middleware["serveIndex--2"], "Middleware got added to internal map with unique name"); - t.deepEqual(middlewareManager.middleware["serveIndex--2"].mountPath, "/goose", + t.is(middlewareManager.middleware["serveIndex--2"].mountPath, "/goose", "Middleware got added correct mount path"); t.deepEqual(middlewareManager.middlewareExecutionOrder, [ @@ -109,7 +109,7 @@ test("addMiddleware: Adding middleware already added to middlewareExecutionOrder const err = await t.throwsAsync(() => { return middlewareManager.addMiddleware("serveIndex"); }); - t.deepEqual(err.message, + t.is(err.message, "Middleware serveIndex already added to execution order. This should not happen.", "Rejected with correct error message"); }); @@ -129,11 +129,11 @@ test("addMiddleware: Add middleware", async (t) => { await middlewareManager.addMiddleware("serveIndex"); // Add middleware to test for t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map"); t.truthy(middlewareManager.middleware["serveIndex"].middleware, "Middleware module is given"); - t.deepEqual(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); + t.is(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); - t.deepEqual(middlewareManager.middlewareExecutionOrder.length, 2, + t.is(middlewareManager.middlewareExecutionOrder.length, 2, "Two middleware got added to middleware execution order"); - t.deepEqual(middlewareManager.middlewareExecutionOrder[1], "serveIndex", + t.is(middlewareManager.middlewareExecutionOrder[1], "serveIndex", "Last added middleware was added to the end of middleware execution order array"); }); @@ -155,11 +155,11 @@ test("addMiddleware: Add middleware with beforeMiddleware and mountPath paramete }); t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map"); t.truthy(middlewareManager.middleware["serveIndex"].middleware, "Middleware module is given"); - t.deepEqual(middlewareManager.middleware["serveIndex"].mountPath, "/pony", "Correct mount path set"); + t.is(middlewareManager.middleware["serveIndex"].mountPath, "/pony", "Correct mount path set"); - t.deepEqual(middlewareManager.middlewareExecutionOrder.length, 2, + t.is(middlewareManager.middlewareExecutionOrder.length, 2, "Two middleware got added to middleware execution order"); - t.deepEqual(middlewareManager.middlewareExecutionOrder[0], "serveIndex", + t.is(middlewareManager.middlewareExecutionOrder[0], "serveIndex", "Middleware was inserted at correct position of middleware execution order array"); }); @@ -181,11 +181,11 @@ test("addMiddleware: Add middleware with afterMiddleware parameter", async (t) = }); t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map"); t.truthy(middlewareManager.middleware["serveIndex"].middleware, "Middleware module is given"); - t.deepEqual(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); + t.is(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); - t.deepEqual(middlewareManager.middlewareExecutionOrder.length, 3, + t.is(middlewareManager.middlewareExecutionOrder.length, 3, "Three middleware got added to middleware execution order"); - t.deepEqual(middlewareManager.middlewareExecutionOrder[1], "serveIndex", + t.is(middlewareManager.middlewareExecutionOrder[1], "serveIndex", "Middleware was inserted at correct position of middleware execution order array"); }); @@ -206,10 +206,10 @@ test("addMiddleware: Add middleware with invalid afterMiddleware parameter", asy afterMiddleware: "🦆" }); }); - t.deepEqual(err.message, "Could not find middleware 🦆, referenced by custom middleware serveIndex"); + t.is(err.message, "Could not find middleware 🦆, referenced by custom middleware serveIndex"); t.falsy(middlewareManager.middleware["serveIndex"], "Middleware did not get added to internal map"); - t.deepEqual(middlewareManager.middlewareExecutionOrder.length, 1, + t.is(middlewareManager.middlewareExecutionOrder.length, 1, "No new middleware got added to middleware execution order array"); }); @@ -229,10 +229,10 @@ test("addMiddleware: Add middleware with rapperCallback parameter", async (t) => await middlewareManager.addMiddleware("serveIndex", { // Add middleware to test for wrapperCallback: wrapperCallbackStub }); - t.deepEqual(wrapperCallbackStub.callCount, 1, "Wrapper callback got called once"); + t.is(wrapperCallbackStub.callCount, 1, "Wrapper callback got called once"); t.deepEqual(wrapperCallbackStub.getCall(0).args[0], serveIndexMiddlewareInfo, "Wrapper callback got called with correct module"); - t.deepEqual(moduleStub.callCount, 1, "Wrapper callback got called once"); + t.is(moduleStub.callCount, 1, "Wrapper callback got called once"); t.deepEqual(moduleStub.getCall(0).args[0].resources, { all: "I", rootProject: "like", @@ -240,13 +240,13 @@ test("addMiddleware: Add middleware with rapperCallback parameter", async (t) => }, "Wrapper callback got called with correct arguments"); t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map"); - t.deepEqual(middlewareManager.middleware["serveIndex"].middleware, "🍅", + t.is(middlewareManager.middleware["serveIndex"].middleware, "🍅", "Middleware module is given"); - t.deepEqual(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); + t.is(middlewareManager.middleware["serveIndex"].mountPath, "/", "Correct default mount path set"); - t.deepEqual(middlewareManager.middlewareExecutionOrder.length, 1, + t.is(middlewareManager.middlewareExecutionOrder.length, 1, "One middleware got added to middleware execution order"); - t.deepEqual(middlewareManager.middlewareExecutionOrder[0], "serveIndex", + t.is(middlewareManager.middlewareExecutionOrder[0], "serveIndex", "Middleware was inserted at correct position of middleware execution order array"); }); @@ -266,7 +266,7 @@ test("addMiddleware: Add middleware with async wrapperCallback", async (t) => { }); t.truthy(middlewareManager.middleware["serveIndex"], "Middleware got added to internal map"); - t.deepEqual(middlewareManager.middleware["serveIndex"].middleware, "🍅", + t.is(middlewareManager.middleware["serveIndex"].middleware, "🍅", "Middleware module is given"); }); @@ -282,7 +282,7 @@ test("addStandardMiddleware: Adds standard middleware in correct order", async ( const addMiddlewareStub = sinon.stub(middlewareManager, "addMiddleware").resolves(); await middlewareManager.addStandardMiddleware(); - t.deepEqual(addMiddlewareStub.callCount, 11, "Expected count of middleware got added"); + t.is(addMiddlewareStub.callCount, 11, "Expected count of middleware got added"); const addedMiddlewareNames = []; for (let i = 0; i < addMiddlewareStub.callCount; i++) { addedMiddlewareNames.push(addMiddlewareStub.getCall(i).args[0]); @@ -322,7 +322,7 @@ test("addCustomMiddleware: No custom middleware defined", async (t) => { const addMiddlewareStub = sinon.stub(middlewareManager, "addMiddleware").resolves(); await middlewareManager.addCustomMiddleware(); - t.deepEqual(addMiddlewareStub.callCount, 0, "addMiddleware was not called"); + t.is(addMiddlewareStub.callCount, 0, "addMiddleware was not called"); }); test("addCustomMiddleware: Custom middleware got added", async (t) => { @@ -352,25 +352,25 @@ test("addCustomMiddleware: Custom middleware got added", async (t) => { const addMiddlewareStub = sinon.stub(middlewareManager, "addMiddleware").resolves(); await middlewareManager.addCustomMiddleware(); - t.deepEqual(addMiddlewareStub.callCount, 2, "addMiddleware was called twice"); - t.deepEqual(addMiddlewareStub.getCall(0).args[0], "my custom middleware A", + t.is(addMiddlewareStub.callCount, 2, "addMiddleware was called twice"); + t.is(addMiddlewareStub.getCall(0).args[0], "my custom middleware A", "addMiddleware was called with correct middleware name"); const middlewareOptionsA = addMiddlewareStub.getCall(0).args[1]; - t.deepEqual(middlewareOptionsA.mountPath, "/pony", + t.is(middlewareOptionsA.mountPath, "/pony", "addMiddleware was called with correct mountPath option"); - t.deepEqual(middlewareOptionsA.beforeMiddleware, "cors", + t.is(middlewareOptionsA.beforeMiddleware, "cors", "addMiddleware was called with correct beforeMiddleware option"); - t.deepEqual(middlewareOptionsA.afterMiddleware, undefined, + t.is(middlewareOptionsA.afterMiddleware, undefined, "addMiddleware was called with correct afterMiddleware option"); - t.deepEqual(addMiddlewareStub.getCall(1).args[0], "my custom middleware B", + t.is(addMiddlewareStub.getCall(1).args[0], "my custom middleware B", "addMiddleware was called with correct middleware name"); const middlewareOptionsB = addMiddlewareStub.getCall(1).args[1]; - t.deepEqual(middlewareOptionsB.mountPath, undefined, + t.is(middlewareOptionsB.mountPath, undefined, "addMiddleware was called with correct mountPath option"); - t.deepEqual(middlewareOptionsB.beforeMiddleware, undefined, + t.is(middlewareOptionsB.beforeMiddleware, undefined, "addMiddleware was called with correct beforeMiddleware option"); - t.deepEqual(middlewareOptionsB.afterMiddleware, "my custom middleware A", + t.is(middlewareOptionsB.afterMiddleware, "my custom middleware A", "addMiddleware was called with correct afterMiddleware option"); }); @@ -398,8 +398,8 @@ test("addCustomMiddleware: No special handling for custom middleware with duplic const addMiddlewareStub = sinon.stub(middlewareManager, "addMiddleware").resolves(); await middlewareManager.addCustomMiddleware(); - t.deepEqual(addMiddlewareStub.callCount, 1, "addMiddleware was called once"); - t.deepEqual(addMiddlewareStub.getCall(0).args[0], "my custom middleware A", + t.is(addMiddlewareStub.callCount, 1, "addMiddleware was called once"); + t.is(addMiddlewareStub.getCall(0).args[0], "my custom middleware A", "addMiddleware was called with correct middleware name"); }); @@ -426,7 +426,7 @@ test("addCustomMiddleware: Missing name configuration", async (t) => { return middlewareManager.addCustomMiddleware(); }); - t.deepEqual(err.message, "Missing name for custom middleware definition of project my project at index 0", + t.is(err.message, "Missing name for custom middleware definition of project my project at index 0", "Rejected with correct error message"); }); @@ -521,7 +521,7 @@ test("addCustomMiddleware", async (t) => { const addMiddlewareStub = sinon.stub(middlewareManager, "addMiddleware").resolves(); await middlewareManager.addCustomMiddleware(); - t.deepEqual(addMiddlewareStub.callCount, 1, "addMiddleware was called once"); + t.is(addMiddlewareStub.callCount, 1, "addMiddleware was called once"); const customMiddleware = addMiddlewareStub.getCall(0).args[1].customMiddleware; const middlewareUtil = { @@ -532,11 +532,11 @@ test("addCustomMiddleware", async (t) => { middlewareUtil }); - t.deepEqual(res, "ok", "Wrapper callback returned expected value"); + t.is(res, "ok", "Wrapper callback returned expected value"); t.is(middlewareUtil.getInterface.callCount, 1, "middlewareUtil.getInterface got called once"); - t.deepEqual(middlewareUtil.getInterface.getCall(0).args[0], "2.6", + t.is(middlewareUtil.getInterface.getCall(0).args[0], "2.6", "middlewareUtil.getInterface got called correct arguments"); - t.deepEqual(middlewareModuleStub.callCount, 1, "Middleware module got called once"); + t.is(middlewareModuleStub.callCount, 1, "Middleware module got called once"); t.deepEqual(middlewareModuleStub.getCall(0).args[0], { resources: "resources", options: { @@ -574,9 +574,9 @@ test("addStandardMiddleware: CSP middleware configured correctly (default)", asy }; const middlewareWrapper = wrapperCallback(middlewareModuleInfo); const res = middlewareWrapper(); - t.deepEqual(res, "ok", "Wrapper callback returned expected value"); - t.deepEqual(middlewareModuleStub.callCount, 1, "Middleware module got called once"); - t.deepEqual(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", + t.is(res, "ok", "Wrapper callback returned expected value"); + t.is(middlewareModuleStub.callCount, 1, "Middleware module got called once"); + t.is(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", "CSP middleware module got called with correct first argument"); t.deepEqual(middlewareModuleStub.getCall(0).args[1], { allowDynamicPolicyDefinition: true, @@ -624,9 +624,9 @@ test("addStandardMiddleware: CSP middleware configured correctly (enabled)", asy }; const middlewareWrapper = wrapperCallback(middlewareModuleInfo); const res = middlewareWrapper(); - t.deepEqual(res, "ok", "Wrapper callback returned expected value"); - t.deepEqual(middlewareModuleStub.callCount, 1, "Middleware module got called once"); - t.deepEqual(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", + t.is(res, "ok", "Wrapper callback returned expected value"); + t.is(middlewareModuleStub.callCount, 1, "Middleware module got called once"); + t.is(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", "CSP middleware module got called with correct first argument"); t.deepEqual(middlewareModuleStub.getCall(0).args[1], { allowDynamicPolicyDefinition: true, @@ -688,9 +688,9 @@ test("addStandardMiddleware: CSP middleware configured correctly (custom)", asyn }; const middlewareWrapper = wrapperCallback(middlewareModuleInfo); const res = middlewareWrapper(); - t.deepEqual(res, "ok", "Wrapper callback returned expected value"); - t.deepEqual(middlewareModuleStub.callCount, 1, "Middleware module got called once"); - t.deepEqual(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", + t.is(res, "ok", "Wrapper callback returned expected value"); + t.is(middlewareModuleStub.callCount, 1, "Middleware module got called once"); + t.is(middlewareModuleStub.getCall(0).args[0], "sap-ui-xx-csp-policy", "CSP middleware module got called with correct first argument"); t.deepEqual(middlewareModuleStub.getCall(0).args[1], { allowDynamicPolicyDefinition: true, diff --git a/test/lib/server/middleware/MiddlewareUtil.js b/test/lib/server/middleware/MiddlewareUtil.js index cc8e07a2..b2954391 100644 --- a/test/lib/server/middleware/MiddlewareUtil.js +++ b/test/lib/server/middleware/MiddlewareUtil.js @@ -8,7 +8,7 @@ test.afterEach.always((t) => { mock.stopAll(); }); -test.serial("getPathname", async (t) => { +test.serial("getPathname", (t) => { const middlewareUtil = new MiddlewareUtil(); const parseurlStub = sinon.stub().returns({pathname: "path%20name"}); mock("parseurl", parseurlStub); @@ -19,7 +19,7 @@ test.serial("getPathname", async (t) => { t.is(pathname, "path name", "Correct pathname returned"); }); -test.serial("getMimeInfo", async (t) => { +test.serial("getMimeInfo", (t) => { const middlewareUtil = new MiddlewareUtil(); const mime = require("mime-types"); const lookupStub = sinon.stub(mime, "lookup").returns("mytype"); @@ -38,7 +38,7 @@ test.serial("getMimeInfo", async (t) => { }, "Correct pathname returned"); }); -test.serial("getMimeInfo: unknown type", async (t) => { +test.serial("getMimeInfo: unknown type", (t) => { const middlewareUtil = new MiddlewareUtil(); const mime = require("mime-types"); const lookupStub = sinon.stub(mime, "lookup"); @@ -57,7 +57,7 @@ test.serial("getMimeInfo: unknown type", async (t) => { }, "Correct pathname returned"); }); -test("getInterface: specVersion 1.0", async (t) => { +test("getInterface: specVersion 1.0", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("1.0"); @@ -65,7 +65,7 @@ test("getInterface: specVersion 1.0", async (t) => { t.is(interfacedMiddlewareUtil, undefined, "no interface provided"); }); -test("getInterface: specVersion 2.0", async (t) => { +test("getInterface: specVersion 2.0", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.0"); @@ -79,7 +79,7 @@ test("getInterface: specVersion 2.0", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.1", async (t) => { +test("getInterface: specVersion 2.1", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.1"); @@ -93,7 +93,7 @@ test("getInterface: specVersion 2.1", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.2", async (t) => { +test("getInterface: specVersion 2.2", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.2"); @@ -107,7 +107,7 @@ test("getInterface: specVersion 2.2", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.3", async (t) => { +test("getInterface: specVersion 2.3", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.3"); @@ -121,7 +121,7 @@ test("getInterface: specVersion 2.3", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.4", async (t) => { +test("getInterface: specVersion 2.4", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.4"); @@ -135,7 +135,7 @@ test("getInterface: specVersion 2.4", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.5", async (t) => { +test("getInterface: specVersion 2.5", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.5"); @@ -149,7 +149,7 @@ test("getInterface: specVersion 2.5", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion 2.6", async (t) => { +test("getInterface: specVersion 2.6", (t) => { const middlewareUtil = new MiddlewareUtil(); const interfacedMiddlewareUtil = middlewareUtil.getInterface("2.6"); @@ -163,7 +163,7 @@ test("getInterface: specVersion 2.6", async (t) => { t.is(typeof interfacedMiddlewareUtil.getMimeInfo, "function", "function getMimeInfo is provided"); }); -test("getInterface: specVersion undefined", async (t) => { +test("getInterface: specVersion undefined", (t) => { const middlewareUtil = new MiddlewareUtil(); const err = t.throws(() => { @@ -174,7 +174,7 @@ test("getInterface: specVersion undefined", async (t) => { "Throw with correct error message"); }); -test("getInterface: specVersion unknown", async (t) => { +test("getInterface: specVersion unknown", (t) => { const middlewareUtil = new MiddlewareUtil(); const err = t.throws(() => { middlewareUtil.getInterface("1.5"); diff --git a/test/lib/server/middleware/middlewareRepository.js b/test/lib/server/middleware/middlewareRepository.js index e33b356c..2f08534d 100644 --- a/test/lib/server/middleware/middlewareRepository.js +++ b/test/lib/server/middleware/middlewareRepository.js @@ -1,7 +1,7 @@ const test = require("ava"); const middlewareRepository = require("../../../../lib/middleware/middlewareRepository"); -test("getMiddleware", async (t) => { +test("getMiddleware", (t) => { const cspModule = require("../../../../lib/middleware/csp"); const res = middlewareRepository.getMiddleware("csp"); t.deepEqual(res, { @@ -9,10 +9,10 @@ test("getMiddleware", async (t) => { }, "Returned correct middleware module"); }); -test("getMiddleware: Unknown middleware", async (t) => { +test("getMiddleware: Unknown middleware", (t) => { const err = t.throws(() => { middlewareRepository.getMiddleware("🐬"); }); - t.deepEqual(err.message, "middlewareRepository: Unknown Middleware 🐬", + t.is(err.message, "middlewareRepository: Unknown Middleware 🐬", "Threw error with correct message"); }); diff --git a/test/lib/server/middleware/nonReadRequests.js b/test/lib/server/middleware/nonReadRequests.js index c9b6ce96..bef04745 100644 --- a/test/lib/server/middleware/nonReadRequests.js +++ b/test/lib/server/middleware/nonReadRequests.js @@ -31,7 +31,7 @@ test("Non read requests results in status 404 and an error message", (t) => { res = { statusCode: 200, end: function(message) { - t.deepEqual(res.statusCode, 404, "Status should be 404"); + t.is(res.statusCode, 404, "Status should be 404"); t.deepEqual(message, "Cannot " + method + " /somePath", "Finished with error message."); } }; diff --git a/test/lib/server/middleware/serveIndex.js b/test/lib/server/middleware/serveIndex.js index f06bd078..cffca6d9 100644 --- a/test/lib/server/middleware/serveIndex.js +++ b/test/lib/server/middleware/serveIndex.js @@ -2,7 +2,7 @@ const test = require("ava"); const resourceFactory = require("@ui5/fs").resourceFactory; const MiddlewareUtil = require("../../../../lib/middleware/MiddlewareUtil"); -test.serial("serveIndex default", (t) => { +test.serial("serveIndex default", async (t) => { t.plan(4); const serveIndexMiddleware = require("../../../../lib/middleware/serveIndex"); const writeResource = function(writer, path, buffer) { @@ -19,58 +19,57 @@ test.serial("serveIndex default", (t) => { const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); - return Promise.all([ + await Promise.all([ writeResource(readerWriter, "/myFile1.meh", Buffer.alloc(1024)), // KB writeResource(readerWriter, "/myFile2.js", Buffer.alloc(1024 * 1024)), // MB writeResource(readerWriter, "/myFile3.properties", Buffer.alloc(1024 * 1024 * 1024)), // GB writeResource(readerWriter, "/.myFile4", Buffer.alloc(1024)), // hidden 1 KB - ]).then(() => { - const middleware = serveIndexMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - } - }); + ]); + const middleware = serveIndexMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + } + }); - return new Promise((resolve, reject) => { - const req = { - url: "/" - }; - const res = { - writeHead: function(status, contentType) { - }, - end: function(content) { - t.regex(content, - RegExp( - "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + + await new Promise((resolve, reject) => { + const req = { + url: "/" + }; + const res = { + writeHead: function(status, contentType) { + }, + end: function(content) { + t.regex(content, + RegExp( + "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + "title=\"myFile1.meh\"><span class=\"name\">myFile1.meh</span><span class=\"size\">" + "1.00 KB</span>")); - t.regex(content, - RegExp( - "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + + t.regex(content, + RegExp( + "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + "title=\"myFile2.js\"><span class=\"name\">myFile2.js</span><span class=\"size\">" + "1.00 MB</span>")); - t.regex(content, - RegExp( - "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + + t.regex(content, + RegExp( + "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + "title=\"myFile3.properties\"><span class=\"name\">myFile3.properties</span>" + "<span class=\"size\">1.00 GB</span>")); - t.regex(content, - RegExp( - "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" title=\".myFile4\">" + + t.regex(content, + RegExp( + "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" title=\".myFile4\">" + "<span class=\"name\">.myFile4</span><span class=\"size\">1.00 KB</span>")); - resolve(); - }, - }; - const next = function(err) { - reject(new Error(`Next callback called with error: ${err.message}`)); - }; - middleware(req, res, next); - }); + resolve(); + }, + }; + const next = function(err) { + reject(new Error(`Next callback called with error: ${err.message}`)); + }; + middleware(req, res, next); }); }); -test.serial("serveIndex no hidden", (t) => { +test.serial("serveIndex no hidden", async (t) => { t.plan(4); const serveIndexMiddleware = require("../../../../lib/middleware/serveIndex"); const writeResource = function(writer, path, buffer) { @@ -87,61 +86,60 @@ test.serial("serveIndex no hidden", (t) => { const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); - return Promise.all([ + await Promise.all([ writeResource(readerWriter, "/myFile1.meh", Buffer.alloc(1024)), // KB writeResource(readerWriter, "/myFile2.js", Buffer.alloc(1024 * 1024)), // MB writeResource(readerWriter, "/myFile3.properties", Buffer.alloc(1024 * 1024 * 1024)), // GB writeResource(readerWriter, "/.myFile4", Buffer.alloc(1024)), // hidden 1 KB - ]).then(() => { - const middleware = serveIndexMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - }, - simpleIndex: false, - showHidden: false - }); + ]); + const middleware = serveIndexMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + }, + simpleIndex: false, + showHidden: false + }); - return new Promise((resolve, reject) => { - const req = { - url: "/" - }; - const res = { - writeHead: function(status, contentType) { - }, - end: function(content) { - t.regex(content, - RegExp( - "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + + await new Promise((resolve, reject) => { + const req = { + url: "/" + }; + const res = { + writeHead: function(status, contentType) { + }, + end: function(content) { + t.regex(content, + RegExp( + "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + "title=\"myFile1.meh\"><span class=\"name\">myFile1.meh</span>" + "<span class=\"size\">1.00 KB</span>")); - t.regex(content, - RegExp( - "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + + t.regex(content, + RegExp( + "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + "title=\"myFile2.js\"><span class=\"name\">myFile2.js</span>" + "<span class=\"size\">1.00 MB</span>")); - t.regex(content, - RegExp( - "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + + t.regex(content, + RegExp( + "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + "title=\"myFile3.properties\"><span class=\"name\">myFile3.properties</span>" + "<span class=\"size\">1.00 GB</span>")); - t.notRegex(content, - RegExp( - "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" " + + t.notRegex(content, + RegExp( + "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" " + "title=\".myFile4\"><span class=\"name\">.myFile4</span>" + "<span class=\"size\">1.00 KB</span>")); - resolve(); - }, - }; - const next = function(err) { - reject(new Error(`Next callback called with error: ${err.message}`)); - }; - middleware(req, res, next); - }); + resolve(); + }, + }; + const next = function(err) { + reject(new Error(`Next callback called with error: ${err.message}`)); + }; + middleware(req, res, next); }); }); -test.serial("serveIndex no details", (t) => { +test.serial("serveIndex no details", async (t) => { t.plan(4); const serveIndexMiddleware = require("../../../../lib/middleware/serveIndex"); const writeResource = function(writer, path, buffer) { @@ -158,52 +156,51 @@ test.serial("serveIndex no details", (t) => { const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); - return Promise.all([ + await Promise.all([ writeResource(readerWriter, "/myFile1.meh", Buffer.alloc(1024)), // KB writeResource(readerWriter, "/myFile2.js", Buffer.alloc(1024 * 1024)), // MB writeResource(readerWriter, "/myFile3.properties", Buffer.alloc(1024 * 1024 * 1024)), // GB writeResource(readerWriter, "/.myFile4", Buffer.alloc(1024)), // hidden 1 KB - ]).then(() => { - const middleware = serveIndexMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - }, - simpleIndex: true, - showHidden: true - }); + ]); + const middleware = serveIndexMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + }, + simpleIndex: true, + showHidden: true + }); - return new Promise((resolve, reject) => { - const req = { - url: "/" - }; - const res = { - writeHead: function(status, contentType) { - }, - end: function(content) { - t.regex(content, RegExp( - "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + + await new Promise((resolve, reject) => { + const req = { + url: "/" + }; + const res = { + writeHead: function(status, contentType) { + }, + end: function(content) { + t.regex(content, RegExp( + "<li><a href=\"/myFile1.meh\" class=\"icon icon icon-meh icon-default\" " + "title=\"myFile1.meh\"><span class=\"name\">myFile1.meh</span>" + "<span class=\"size\">1.00 KB</span>")); - t.regex(content, RegExp( - "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + + t.regex(content, RegExp( + "<li><a href=\"/myFile2.js\" class=\"icon icon icon-js icon-application-javascript\" " + "title=\"myFile2.js\"><span class=\"name\">myFile2.js</span>" + "<span class=\"size\">1.00 MB</span>")); - t.regex(content, RegExp( - "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + + t.regex(content, RegExp( + "<li><a href=\"/myFile3.properties\" class=\"icon icon icon-properties icon-default\" " + "title=\"myFile3.properties\"><span class=\"name\">myFile3.properties</span>" + "<span class=\"size\">1.00 GB</span>")); - t.regex(content, RegExp( - "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" " + + t.regex(content, RegExp( + "<li><a href=\"/.myFile4\" class=\"icon icon icon- icon-default\" " + "title=\".myFile4\"><span class=\"name\">.myFile4</span><span class=\"size\">1.00 KB</span>")); - resolve(); - }, - }; - const next = function(err) { - reject(new Error(`Next callback called with error: ${err.message}`)); - }; - middleware(req, res, next); - }); + resolve(); + }, + }; + const next = function(err) { + reject(new Error(`Next callback called with error: ${err.message}`)); + }; + middleware(req, res, next); }); }); diff --git a/test/lib/server/middleware/serveResources.js b/test/lib/server/middleware/serveResources.js index 19da0864..5fe52a28 100644 --- a/test/lib/server/middleware/serveResources.js +++ b/test/lib/server/middleware/serveResources.js @@ -1,3 +1,7 @@ +/* eslint-disable ava/no-unknown-modifiers */ +/* Test modifier `cb` was deprecated with ava version +3 and removed with ava version 4. Therefore, tests using `cb` has to be rewritten, when upgrade to ava version 4 */ + const test = require("ava"); const sinon = require("sinon"); const mock = require("mock-require"); @@ -44,7 +48,7 @@ test.afterEach.always((t) => { sinon.restore(); }); -test.serial("Check if properties file is served properly", (t) => { +test.serial("Check if properties file is served properly", async (t) => { t.plan(4); const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); @@ -52,39 +56,39 @@ test.serial("Check if properties file is served properly", (t) => { getPropertiesFileSourceEncoding: () => "ISO-8859-1" }; - return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "latin1", project) - .then((resource) => { - const setStringSpy = sinon.spy(resource, "setString"); - const middleware = serveResourcesMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - } - }); + const resource = await writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, + "key=titel\nfame=straße", "latin1", project); + + const setStringSpy = sinon.spy(resource, "setString"); + const middleware = serveResourcesMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + } + }); - const response = fakeResponse; + const response = fakeResponse; - const setHeaderSpy = sinon.spy(response, "setHeader"); - const req = { - url: "/myFile3.properties", - headers: {} - }; - const next = function(err) { - throw new Error(`Next callback called with error: ${err.message}`); - }; - return middleware(req, response, next).then((o) => { - return resource.getString(); - }).then((content) => { - t.is(content, `key=titel + const setHeaderSpy = sinon.spy(response, "setHeader"); + const req = { + url: "/myFile3.properties", + headers: {} + }; + const next = function(err) { + throw new Error(`Next callback called with error: ${err.message}`); + }; + const content = await middleware(req, response, next).then((o) => { + return resource.getString(); + }); + + t.is(content, `key=titel fame=stra\\u00dfe`); - t.is(setHeaderSpy.callCount, 2); - t.is(setStringSpy.callCount, 1); - t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); - }); - }); + t.is(setHeaderSpy.callCount, 2); + t.is(setStringSpy.callCount, 1); + t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); }); -test.serial("Check if properties file is served properly with UTF-8", (t) => { +test.serial("Check if properties file is served properly with UTF-8", async (t) => { t.plan(4); const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); @@ -92,87 +96,86 @@ test.serial("Check if properties file is served properly with UTF-8", (t) => { getPropertiesFileSourceEncoding: () => "UTF-8" }; - return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8", project) - .then((resource) => { - const setStringSpy = sinon.spy(resource, "setString"); - const middleware = serveResourcesMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - } - }); + const resource = await writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, + "key=titel\nfame=straße", "utf8", project); + + const setStringSpy = sinon.spy(resource, "setString"); + const middleware = serveResourcesMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + } + }); - const response = fakeResponse; + const response = fakeResponse; - const setHeaderSpy = sinon.spy(response, "setHeader"); - const req = { - url: "/myFile3.properties", - headers: {} - }; - const next = function(err) { - throw new Error(`Next callback called with error: ${err.message}`); - }; - return middleware(req, response, next).then((o) => { - return resource.getString(); - }).then((content) => { - t.is(content, `key=titel + const setHeaderSpy = sinon.spy(response, "setHeader"); + const req = { + url: "/myFile3.properties", + headers: {} + }; + const next = function(err) { + throw new Error(`Next callback called with error: ${err.message}`); + }; + await middleware(req, response, next); + const content = await resource.getString(); + + t.is(content, `key=titel fame=stra\\u00dfe`); - t.is(setHeaderSpy.callCount, 2); - t.is(setStringSpy.callCount, 1); - t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); - }); - }); + t.is(setHeaderSpy.callCount, 2); + t.is(setStringSpy.callCount, 1); + t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); }); -test.serial("Check if properties file is served properly without property setting", (t) => { +test.serial("Check if properties file is served properly without property setting", async (t) => { t.plan(4); const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); - return writeResource(readerWriter, "/myFile3.properties", + const resource = await writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8" - ).then((resource) => { - const setStringSpy = sinon.spy(resource, "setString"); - const middleware = serveResourcesMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - } - }); + ); + const setStringSpy = sinon.spy(resource, "setString"); + const middleware = serveResourcesMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + } + }); - const response = fakeResponse; + const response = fakeResponse; - const setHeaderSpy = sinon.spy(response, "setHeader"); - const req = { - url: "/myFile3.properties", - headers: {} - }; - const next = function(err) { - throw new Error(`Next callback called with error: ${err.stack}`); - }; - return middleware(req, response, next).then((o) => { - return resource.getString(); - }).then((content) => { - t.is(content, `key=titel + const setHeaderSpy = sinon.spy(response, "setHeader"); + const req = { + url: "/myFile3.properties", + headers: {} + }; + const next = function(err) { + throw new Error(`Next callback called with error: ${err.stack}`); + }; + + await middleware(req, response, next); + const content = await resource.getString(); + + t.is(content, `key=titel fame=stra\\u00dfe`); - t.is(setHeaderSpy.callCount, 2); - t.is(setStringSpy.callCount, 1); - t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); - }); - }); + t.is(setHeaderSpy.callCount, 2); + t.is(setStringSpy.callCount, 1); + t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); }); -test.serial("Check if properties file is served properly without property setting but legacy spec version", (t) => { - t.plan(4); +test.serial("Check if properties file is served properly without property setting but legacy spec version", + async (t) => { + t.plan(4); - const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); - const project = { - getPropertiesFileSourceEncoding: () => "", - getSpecVersion: () => "1.1" - }; - return writeResource(readerWriter, "/myFile3.properties", - 1024 * 1024, "key=titel\nfame=straße", "latin1", project - ).then((resource) => { + const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); + const project = { + getPropertiesFileSourceEncoding: () => "", + getSpecVersion: () => "1.1" + }; + const resource = await writeResource(readerWriter, "/myFile3.properties", + 1024 * 1024, "key=titel\nfame=straße", "latin1", project + ); const setStringSpy = sinon.spy(resource, "setString"); const middleware = serveResourcesMiddleware({ middlewareUtil: new MiddlewareUtil(), @@ -191,19 +194,16 @@ test.serial("Check if properties file is served properly without property settin const next = function(err) { throw new Error(`Next callback called with error: ${err.stack}`); }; - return middleware(req, response, next).then((o) => { - return resource.getString(); - }).then((content) => { - t.is(content, `key=titel + await middleware(req, response, next); + const content = await resource.getString(); + t.is(content, `key=titel fame=stra\\u00dfe`); - t.is(setHeaderSpy.callCount, 2); - t.is(setStringSpy.callCount, 1); - t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); - }); + t.is(setHeaderSpy.callCount, 2); + t.is(setStringSpy.callCount, 1); + t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); }); -}); -test.serial("Check if properties file is served properly without property setting but spec version", (t) => { +test.serial("Check if properties file is served properly without property setting but spec version", async (t) => { t.plan(4); const readerWriter = resourceFactory.createAdapter({virBasePath: "/"}); @@ -211,37 +211,35 @@ test.serial("Check if properties file is served properly without property settin getPropertiesFileSourceEncoding: () => "", getSpecVersion: () => "2.0" }; - return writeResource(readerWriter, "/myFile3.properties", + const resource = await writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8", project - ).then((resource) => { - const setStringSpy = sinon.spy(resource, "setString"); - const middleware = serveResourcesMiddleware({ - middlewareUtil: new MiddlewareUtil(), - resources: { - all: readerWriter - } - }); + ); + const setStringSpy = sinon.spy(resource, "setString"); + const middleware = serveResourcesMiddleware({ + middlewareUtil: new MiddlewareUtil(), + resources: { + all: readerWriter + } + }); - const response = fakeResponse; + const response = fakeResponse; - const setHeaderSpy = sinon.spy(response, "setHeader"); - const req = { - url: "/myFile3.properties", - headers: {} - }; - const next = function(err) { - throw new Error(`Next callback called with error: ${err.stack}`); - }; - return middleware(req, response, next).then((o) => { - return resource.getString(); - }).then((content) => { - t.is(content, `key=titel + const setHeaderSpy = sinon.spy(response, "setHeader"); + const req = { + url: "/myFile3.properties", + headers: {} + }; + const next = function(err) { + throw new Error(`Next callback called with error: ${err.stack}`); + }; + await middleware(req, response, next); + const content = await resource.getString(); + + t.is(content, `key=titel fame=stra\\u00dfe`); - t.is(setHeaderSpy.callCount, 2); - t.is(setStringSpy.callCount, 1); - t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); - }); - }); + t.is(setHeaderSpy.callCount, 2); + t.is(setStringSpy.callCount, 1); + t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream"); }); test.serial("Check verbose logging", (t) => { @@ -402,6 +400,7 @@ test.serial.cb("Check if version replacement is done", (t) => { // Skip test in Node v8 as unicode handling of streams seems to be broken test.serial[ + // eslint-disable-next-line ava/no-unknown-modifiers process.version.startsWith("v8.") ? "skip" : "cb" ]("Check if utf8 characters are correctly processed in version replacement", (t) => { const utf8string = "Κυ"; diff --git a/test/lib/server/middleware/serveThemes.js b/test/lib/server/middleware/serveThemes.js index 22df8197..fa0218b2 100644 --- a/test/lib/server/middleware/serveThemes.js +++ b/test/lib/server/middleware/serveThemes.js @@ -1,3 +1,7 @@ +/* eslint-disable ava/no-unknown-modifiers */ +/* Test modifier `cb` was deprecated with ava version +3 and removed with ava version 4. Therefore, tests using `cb` has to be rewritten, when upgrade to ava version 4 */ + const test = require("ava"); const sinon = require("sinon"); const mock = require("mock-require"); diff --git a/test/lib/server/middleware/testRunner.js b/test/lib/server/middleware/testRunner.js index 93a3ae28..0899a221 100644 --- a/test/lib/server/middleware/testRunner.js +++ b/test/lib/server/middleware/testRunner.js @@ -118,5 +118,5 @@ test.serial("Request path variations that should *not* work", async (t) => { test.serial("Error should be thrown correctly", async (t) => { t.context.readFileStub.yieldsAsync(new Error("My Error")); const error = await t.throwsAsync(callMiddleware("/test-resources/sap/ui/qunit/testrunner.html")); - t.deepEqual(error.message, "My Error"); + t.is(error.message, "My Error"); }); diff --git a/test/lib/server/middleware/versionInfo.js b/test/lib/server/middleware/versionInfo.js index 42607438..ac3723f0 100644 --- a/test/lib/server/middleware/versionInfo.js +++ b/test/lib/server/middleware/versionInfo.js @@ -256,7 +256,7 @@ test.serial("test all inner API calls within middleware", async (t) => { t.is(versionInfoGeneratorOptions.libraryInfos[2].libraryManifest, "stubbed manifest 1"); t.is(endStub.callCount, 1); - t.deepEqual(endStub.getCall(0).args[0], "stubbed version info"); + t.is(endStub.getCall(0).args[0], "stubbed version info"); }); // test case taken from: ui5-builder/test/lib/tasks/generateVersionInfo.js diff --git a/test/lib/server/ports.js b/test/lib/server/ports.js index 1fbd19bc..a59666d3 100644 --- a/test/lib/server/ports.js +++ b/test/lib/server/ports.js @@ -40,81 +40,80 @@ test("Start server - Port is already taken and an error occurs", async (t) => { res.end(); }); - const startServer = new Promise((resolve) => { + await new Promise((resolve) => { nodeServer.on("listening", () => { resolve(); }); nodeServer.listen(port); - }).then(async () => { - const graph = await generateProjectGraph({ - cwd: "./test/fixtures/application.a" - }); - await server.serve(graph, { - port - }); }); - return t.throwsAsync(startServer).then((error) => { - t.deepEqual( - error.message, - "EADDRINUSE: Port 3360 is already in use.", - "Correct error message" - ); - t.deepEqual( - error.code, - "EADDRINUSE", - "Correct error code" - ); - t.deepEqual( - error.errno, - "EADDRINUSE", - "Correct error number" - ); - t.deepEqual( - error.address, - "localhost", - "Correct error address" - ); - t.deepEqual( - error.port, - 3360, - "Correct error port" - ); + const graph = await generateProjectGraph({ + cwd: "./test/fixtures/application.a" + }); + + const startServer = server.serve(graph, { + port }); + + const error = await t.throwsAsync(startServer); + t.is( + error.message, + "EADDRINUSE: Port 3360 is already in use.", + "Correct error message" + ); + t.is( + error.code, + "EADDRINUSE", + "Correct error code" + ); + t.is( + error.errno, + "EADDRINUSE", + "Correct error number" + ); + t.is( + error.address, + "localhost", + "Correct error address" + ); + t.is( + error.port, + 3360, + "Correct error port" + ); }); -test("Start server together with node server - Port is already taken and the next one is used", (t) => { +test("Start server together with node server - Port is already taken and the next one is used", async (t) => { t.plan(2); const port = 3370; const nextFoundPort = 3371; const nodeServer = http.createServer((req, res) => { res.end(); }); - return new Promise((resolve) => { + await new Promise((resolve) => { nodeServer.on("listening", () => { resolve(); }); nodeServer.listen(port); - }).then(async () => { - const graph = await generateProjectGraph({ - cwd: "./test/fixtures/application.a" - }); - const serve = await server.serve(graph, { - port, - changePortIfInUse: true - }); + }); - t.deepEqual(serve.port, nextFoundPort, "Resolves with correct port"); - const request = supertest(`http://localhost:${nextFoundPort}`); - return request.get("/index.html").then((res) => { - if (res.error) { - t.fail(res.error.text); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - nodeServer.close(); - serve.close(); - }); + const graph = await generateProjectGraph({ + cwd: "./test/fixtures/application.a" + }); + const serve = await server.serve(graph, { + port, + changePortIfInUse: true }); + + t.deepEqual(serve.port, nextFoundPort, "Resolves with correct port"); + const request = supertest(`http://localhost:${nextFoundPort}`); + const result = await request.get("/index.html"); + if (result.error) { + t.fail(result.error.text); + } + t.is(result.statusCode, 200, "Correct HTTP status code"); + nodeServer.close(); + serve.close(); }); test.serial("Start server - Port can not be determined and an error occurs", async (t) => { @@ -127,24 +126,22 @@ test.serial("Start server - Port can not be determined and an error occurs", asy }; const portScannerStub = sinon.stub(portscanner, "findAPortNotInUse").callsFake(portscannerFake); - const startServer = generateProjectGraph({ + const graph = await generateProjectGraph({ cwd: "./test/fixtures/application.a" - }).then((graph) => { - return server.serve(graph, { - port: 3990, - changePortIfInUse: true - }); }); - - return t.throwsAsync(startServer).then((error) => { - t.deepEqual(error.message, "testError", - "Server could not start, port is already taken and no other port is used."); - portScannerStub.restore(); + const startServer = server.serve(graph, { + port: 3990, + changePortIfInUse: true }); + + const error = await t.throwsAsync(startServer); + t.is(error.message, "testError", + "Server could not start, port is already taken and no other port is used."); + portScannerStub.restore(); }); -test("Start server - Port is already taken and an error occurs because no other port can be determined", (t) => { +test("Start server - Port is already taken and an error occurs because no other port can be determined", async (t) => { t.plan(6); const portStart = 4000; const portRange = 31; @@ -166,79 +163,75 @@ test("Start server - Port is already taken and an error occurs because no other })); } - const startServer = Promise.all(serversStart).then(() => { - return generateProjectGraph({ - cwd: "./test/fixtures/application.a" - }).then((graph) => { - return server.serve(graph, { - port: portStart, - changePortIfInUse: true - }); - }); + await Promise.all(serversStart); + const graph = await generateProjectGraph({ + cwd: "./test/fixtures/application.a" }); - return t.throwsAsync(startServer).then((error) => { - for (let i = 0; i < servers.length; i++) { - servers[i].close(); - } - t.deepEqual( - error.message, - "EADDRINUSE: Could not find available ports between 4000 and 4030.", - "Server could not start, port is already taken and no other port is used." - ); - t.deepEqual( - error.code, - "EADDRINUSE", - "Correct error code" - ); - t.deepEqual( - error.errno, - "EADDRINUSE", - "Correct error number" - ); - t.deepEqual( - error.address, - "localhost", - "Correct error address" - ); - t.deepEqual( - error.port, - 4030, - "Correct error port" - ); + + const startServer = server.serve(graph, { + port: portStart, + changePortIfInUse: true }); + + const error = await t.throwsAsync(startServer); + for (let i = 0; i < servers.length; i++) { + servers[i].close(); + } + t.is( + error.message, + "EADDRINUSE: Could not find available ports between 4000 and 4030.", + "Server could not start, port is already taken and no other port is used." + ); + t.is( + error.code, + "EADDRINUSE", + "Correct error code" + ); + t.is( + error.errno, + "EADDRINUSE", + "Correct error number" + ); + t.is( + error.address, + "localhost", + "Correct error address" + ); + t.is( + error.port, + 4030, + "Correct error port" + ); }); -test("Start server twice - Port is already taken and the next one is used", (t) => { +test("Start server twice - Port is already taken and the next one is used", async (t) => { t.plan(3); const port = 3380; const nextFoundPort = 3381; - return generateProjectGraph({ + const graph1 = await generateProjectGraph({ cwd: "./test/fixtures/application.a" - }).then((graph) => { - return server.serve(graph, { - port: port, - changePortIfInUse: true - }); - }).then((serveResult1) => { - t.deepEqual(serveResult1.port, port, "Resolves with correct port"); - return generateProjectGraph({ - cwd: "./test/fixtures/application.a" - }).then((graph) =>{ - return server.serve(graph, { - port: port, - changePortIfInUse: true - }).then((serveResult2) => { - t.deepEqual(serveResult2.port, nextFoundPort, "Resolves with correct port"); - const request = supertest(`http://localhost:${nextFoundPort}`); - return request.get("/index.html").then((res) => { - if (res.error) { - t.fail(res.error.text); - } - t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - serveResult1.close(); - serveResult2.close(); - }); - }); - }); }); + const serveResult1 = await server.serve(graph1, { + port: port, + changePortIfInUse: true + }); + t.deepEqual(serveResult1.port, port, "Resolves with correct port"); + + const graph2 = await generateProjectGraph({ + cwd: "./test/fixtures/application.a" + }); + const serveResult2 = await server.serve(graph2, { + port: port, + changePortIfInUse: true + }); + t.deepEqual(serveResult2.port, nextFoundPort, "Resolves with correct port"); + + const request = supertest(`http://localhost:${nextFoundPort}`); + const result = await request.get("/index.html"); + if (result.error) { + t.fail(result.error.text); + } + t.is(result.statusCode, 200, "Correct HTTP status code"); + serveResult1.close(); + serveResult2.close(); }); diff --git a/test/lib/server/sslUtil.js b/test/lib/server/sslUtil.js index d91b563f..731e7f86 100644 --- a/test/lib/server/sslUtil.js +++ b/test/lib/server/sslUtil.js @@ -16,20 +16,18 @@ function fileExists(filePath) { }); } -test("Get existing certificate", (t) => { +test("Get existing certificate", async (t) => { t.plan(2); const sslPath = path.join(process.cwd(), "./test/fixtures/ssl/"); - const result = sslUtil.getSslCertificate( + const result = await sslUtil.getSslCertificate( path.join(sslPath, "dummy.key"), path.join(sslPath, "dummy.crt"), ); - return result.then((res) => { - t.deepEqual(res.key.toString(), "dummy-key-file", "Key exists"); - t.deepEqual(res.cert.toString(), "dummy-crt-file", "Cert exists"); - }); + t.is(result.key.toString(), "dummy-key-file", "Key exists"); + t.is(result.cert.toString(), "dummy-crt-file", "Cert exists"); }); -test.serial("Create new certificate and install it", (t) => { +test.serial("Create new certificate and install it", async (t) => { t.plan(6); const sslKey = "abcd"; const sslCert = "defg"; @@ -45,7 +43,7 @@ test.serial("Create new certificate and install it", (t) => { }); mock("devcert-sanscache", function(name) { - t.deepEqual(name, "UI5Tooling", "Create certificate for UI5Tooling."); + t.is(name, "UI5Tooling", "Create certificate for UI5Tooling."); return Promise.resolve({ key: sslKey, cert: sslCert @@ -59,21 +57,19 @@ test.serial("Create new certificate and install it", (t) => { const sslPath = path.join(process.cwd(), "./test/tmp/ssl/"); const sslPathKey = path.join(sslPath, "someOtherServer1.key"); const sslPathCert = path.join(sslPath, "someOtherServer1.crt"); - const result = sslUtil.getSslCertificate(sslPathKey, sslPathCert); - return result.then((res) => { - t.deepEqual(res.key, sslKey, "Key should be returned"); - t.deepEqual(res.cert, sslCert, "Cert should be returned"); - }).then(() => { - return Promise.all([ - fileExists(sslPathKey), - fileExists(sslPathCert) - ]); - }).then((fileExistsResult) => { - t.deepEqual(fileExistsResult[0], true, "Key was created."); - t.deepEqual(fileExistsResult[1], true, "Cert was created."); - mock.stop("yesno"); - mock.stop("devcert-sanscache"); - }); + const result = await sslUtil.getSslCertificate(sslPathKey, sslPathCert); + t.deepEqual(result.key, sslKey, "Key should be returned"); + t.deepEqual(result.cert, sslCert, "Cert should be returned"); + + const fileExistsResult = await Promise.all([ + fileExists(sslPathKey), + fileExists(sslPathCert) + ]); + + t.is(fileExistsResult[0], true, "Key was created."); + t.is(fileExistsResult[1], true, "Cert was created."); + mock.stop("yesno"); + mock.stop("devcert-sanscache"); }); test.serial("Create new certificate and do not install it", (t) => { @@ -96,7 +92,7 @@ test.serial("Create new certificate and do not install it", (t) => { const sslPathCert = path.join(sslPath, "someOtherServer2.crt"); const result = sslUtil.getSslCertificate(sslPathKey, sslPathCert); return result.catch((error) => { - t.deepEqual( + t.is( error.message, "Certificate installation aborted! Please install the SSL certificate manually.", "Certificate install aborted." @@ -119,7 +115,7 @@ test.serial("Create new certificate not succeeded", async (t) => { }); mock("devcert-sanscache", function(name) { - t.deepEqual(name, "UI5Tooling", "Create certificate for UI5Tooling."); + t.is(name, "UI5Tooling", "Create certificate for UI5Tooling."); return Promise.resolve({ key: "aaa", cert: "bbb" @@ -141,7 +137,7 @@ test.serial("Create new certificate not succeeded", async (t) => { const sslPathKey = path.join(sslPath, "someOtherServer3.key"); const sslPathCert = path.join(sslPath, "someOtherServer3.crt"); const err = await t.throwsAsync(sslUtil.getSslCertificate(sslPathKey, sslPathCert)); - t.deepEqual(err.message, "some error", "Correct error thrown"); + t.is(err.message, "some error", "Correct error thrown"); mock.stop("yesno"); mock.stop("devcert-sanscache"); mock.stop("make-dir");