diff --git a/package-lock.json b/package-lock.json index 28d030142..2b1ba4ab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,14 +57,13 @@ "xml2js": "^0.6.2" }, "devDependencies": { + "@cloudron/bail-reporter": "^1.1.0", "@eslint/js": "^10.0.1", "commander": "^14.0.3", "easy-table": "^1.2.0", "eslint": "^10.0.0", "eventsource": "^4.1.0", - "expect.js": "*", "globals": "^17.3.0", - "mocha": "^11.7.5", "nock": "^14.0.11", "ssh2": "^1.17.0" } @@ -1159,6 +1158,13 @@ "specificity": "bin/cli.js" } }, + "node_modules/@cloudron/bail-reporter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cloudron/bail-reporter/-/bail-reporter-1.1.0.tgz", + "integrity": "sha512-PK2VVEP/SJMfMGRgXijAWiV1fg4oV/QdaTu+Wox+ltxJyx2Vkp20dCKaphwpww8JvG1dcvIHxQ8pZbC0VVdUgQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@cloudron/connect-lastmile": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@cloudron/connect-lastmile/-/connect-lastmile-3.0.0.tgz", @@ -1933,109 +1939,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@js-sdsl/ordered-map": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", @@ -2373,17 +2276,6 @@ "node": ">=20.0.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -3396,11 +3288,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, "node_modules/arrify": { "version": "2.0.1", "license": "MIT", @@ -3623,11 +3510,6 @@ "concat-map": "0.0.1" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "dev": true, - "license": "ISC" - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -3712,48 +3594,6 @@ "node": ">=6" } }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -4349,16 +4189,6 @@ ], "license": "MIT" }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dijkstrajs": { "version": "1.0.1", "license": "MIT" @@ -4459,13 +4289,6 @@ "stream-shift": "^1.0.2" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, "node_modules/easy-table": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", @@ -4925,10 +4748,6 @@ "node": ">=20.0.0" } }, - "node_modules/expect.js": { - "version": "0.3.1", - "dev": true - }, "node_modules/express": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", @@ -5259,14 +5078,6 @@ "node": ">=8" } }, - "node_modules/flat": { - "version": "5.0.2", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -5288,23 +5099,6 @@ "dev": true, "license": "ISC" }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -5678,14 +5472,6 @@ "node": ">=14.0.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -5710,14 +5496,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, "node_modules/html-encoding-sniffer": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", @@ -5921,24 +5699,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -5988,17 +5748,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -6010,22 +5759,6 @@ "version": "0.1.2", "license": "MIT" }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jake": { "version": "10.9.4", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", @@ -6052,17 +5785,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsdom": { "version": "28.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", @@ -6523,21 +6245,6 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -6657,16 +6364,6 @@ "version": "1.2.5", "license": "MIT" }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mkdirp": { "version": "0.5.5", "license": "MIT", @@ -6683,158 +6380,6 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "license": "MIT" }, - "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -7226,13 +6771,6 @@ "node": ">=6" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, "node_modules/parse-database-url": { "version": "0.3.0", "license": "MIT", @@ -7290,30 +6828,6 @@ "version": "1.0.6", "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -7578,16 +7092,6 @@ "node": ">= 0.8" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7687,20 +7191,6 @@ "node": ">= 6" } }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", @@ -7935,16 +7425,6 @@ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve-static": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", @@ -8072,19 +7552,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -8249,22 +7716,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "license": "MIT", @@ -8275,20 +7726,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "2.0.1", "license": "MIT", @@ -8313,20 +7750,6 @@ "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, - "node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "license": "MIT" @@ -8894,13 +8317,6 @@ "node": ">=0.10.0" } }, - "node_modules/workerpool": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", - "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/wrap-ansi": { "version": "7.0.0", "license": "MIT", @@ -8916,25 +8332,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "license": "ISC" @@ -9026,42 +8423,6 @@ "node": ">=12" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yargs/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", diff --git a/package.json b/package.json index d100795f5..326295e53 100644 --- a/package.json +++ b/package.json @@ -62,14 +62,13 @@ "xml2js": "^0.6.2" }, "devDependencies": { + "@cloudron/bail-reporter": "^1.1.0", "@eslint/js": "^10.0.1", "commander": "^14.0.3", "easy-table": "^1.2.0", "eslint": "^10.0.0", "eventsource": "^4.1.0", - "expect.js": "*", "globals": "^17.3.0", - "mocha": "^11.7.5", "nock": "^14.0.11", "ssh2": "^1.17.0" }, diff --git a/run-tests b/run-tests index 9bd58c10a..39e30c836 100755 --- a/run-tests +++ b/run-tests @@ -6,6 +6,12 @@ readonly source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly DATA_DIR="${HOME}/.cloudron_test" readonly DEFAULT_TESTS="./src/test/*-test.js ./src/routes/test/*-test.js" +# fast path: if explicit tests are provided, run them directly and skip setup. +if [[ $# -gt 0 ]]; then + BOX_ENV=test node --test --test-concurrency=1 --test-reporter spec --test-reporter-destination stdout --test-reporter @cloudron/bail-reporter --test-reporter-destination stderr "$@" + exit $? +fi + ! "${source_dir}/src/test/check-install" && exit 1 # cleanup old data dirs some of those docker container data requires sudo to be removed @@ -84,9 +90,6 @@ echo "=> Run database migrations" BOX_ENV=test DATABASE_URL=mysql://root:password@${MYSQL_IP}/box node_modules/.bin/db-migrate up TESTS=${DEFAULT_TESTS} -if [[ $# -gt 0 ]]; then - TESTS="$*" -fi -echo "=> Run tests with mocha" -BOX_ENV=test ./node_modules/.bin/mocha --bail --no-timeouts --exit -R spec ${TESTS} +echo "=> Run tests with node:test" +BOX_ENV=test node --test --test-concurrency=1 --test-reporter spec --test-reporter-destination stdout --test-reporter @cloudron/bail-reporter --test-reporter-destination stderr ${TESTS} diff --git a/src/routes/test/api-test.js b/src/routes/test/api-test.js index eb04c48c2..48ee67a4d 100644 --- a/src/routes/test/api-test.js +++ b/src/routes/test/api-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; import timers from 'timers/promises'; import tokens from '../../tokens.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('API', function () { const { setup, cleanup, serverUrl, owner, user } = common; @@ -25,8 +22,8 @@ describe('API', function () { .send('some invalid non-strict json') .ok(() => true); - expect(response.status).to.equal(400); - expect(response.body.message).to.be('Failed to parse body'); + assert.equal(response.status, 400); + assert.equal(response.body.message, 'Failed to parse body'); }); it('does not crash with invalid string', async function () { @@ -36,7 +33,7 @@ describe('API', function () { .send('some string') .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); }); @@ -46,7 +43,7 @@ describe('API', function () { .auth(owner.username, owner.password) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot get userInfo with invalid token (token length)', async function () { @@ -54,16 +51,16 @@ describe('API', function () { .query({ access_token: 'x' + owner.token }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can get userInfo with token in auth header', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .set('Authorization', 'Bearer ' + owner.token); - expect(response.status).to.equal(200); - expect(response.body.username).to.equal(user.username.toLowerCase()); - expect(response.body.email).to.equal(user.email.toLowerCase()); + assert.equal(response.status, 200); + assert.equal(response.body.username, user.username.toLowerCase()); + assert.equal(response.body.email, user.email.toLowerCase()); }); it('cannot get userInfo with invalid token in auth header', async function () { @@ -71,7 +68,7 @@ describe('API', function () { .set('Authorization', 'Bearer ' + 'x' + owner.token) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot get userInfo with expired token', async function () { @@ -90,14 +87,14 @@ describe('API', function () { const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .set('Authorization', 'Bearer ' + token2.accessToken); - expect(response.status).to.be(200); + assert.equal(response.status, 200); await timers.setTimeout(3000); // wait for token to expire const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .set('Authorization', 'Bearer ' + token2.accessToken) .ok(() => true); - expect(response2.status).to.be(401); + assert.equal(response2.status, 401); }); }); diff --git a/src/routes/test/applinks-test.js b/src/routes/test/applinks-test.js index 8a8a86c59..896a4bccf 100644 --- a/src/routes/test/applinks-test.js +++ b/src/routes/test/applinks-test.js @@ -1,13 +1,10 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import applinks from '../../applinks.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('AppLinks API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -21,8 +18,8 @@ describe('AppLinks API', function () { const response = await superagent.post(`${serverUrl}/api/v1/applinks`) .query({ access_token: owner.token }) .send({ label: 'Berlin', tags: ['city'], upstreamUri: 'https://www.berlin.de', accessRestriction: null }); - expect(response.status).to.equal(201); - expect(response.body.id).to.be.ok(); + assert.equal(response.status, 201); + assert.ok(response.body.id); applinkId = response.body.id; }); @@ -31,57 +28,57 @@ describe('AppLinks API', function () { const response = await superagent.get(`${serverUrl}/api/v1/applinks/random`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot get valid applink', async function () { const response = await superagent.get(`${serverUrl}/api/v1/applinks/${applinkId}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.upstreamUri).to.be('https://www.berlin.de'); + assert.equal(response.status, 200); + assert.equal(response.body.upstreamUri, 'https://www.berlin.de'); }); it('can get get icon', async function () { const response = await superagent.get(`${serverUrl}/api/v1/applinks/${applinkId}/icon`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.headers['content-type']).to.be('application/octet-stream'); + assert.equal(response.status, 200); + assert.equal(response.headers['content-type'], 'application/octet-stream'); }); it('can update applink tags', async function () { const response = await superagent.post(`${serverUrl}/api/v1/applinks/${applinkId}`) .query({ access_token: owner.token }) .send({ tags: ['city', 'germany'] }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await applinks.get(applinkId); - expect(result.tags).to.eql(['city', 'germany']); + assert.deepEqual(result.tags, ['city', 'germany']); }); it('can list applinks', async function () { const response = await superagent.get(`${serverUrl}/api/v1/applinks`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.applinks.length).to.equal(1); - expect(response.body.applinks[0].upstreamUri).to.be('https://www.berlin.de'); + assert.equal(response.status, 200); + assert.equal(response.body.applinks.length, 1); + assert.equal(response.body.applinks[0].upstreamUri, 'https://www.berlin.de'); }); it('cannot del random applink', async function () { const response = await superagent.del(`${serverUrl}/api/v1/applinks/random`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can del applink', async function () { const response = await superagent.del(`${serverUrl}/api/v1/applinks/${applinkId}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const result = await applinks.get(applinkId); - expect(result).to.be(null); + assert.equal(result, null); }); }); diff --git a/src/routes/test/apppasswords-test.js b/src/routes/test/apppasswords-test.js index 3241defff..54271bf3b 100644 --- a/src/routes/test/apppasswords-test.js +++ b/src/routes/test/apppasswords-test.js @@ -1,13 +1,10 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('App Passwords', function () { const { setup, cleanup, serverUrl, user } = common; @@ -22,7 +19,7 @@ describe('App Passwords', function () { .send({ name: 'my-device', identifier: 'someapp' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot add app password without name', async function () { @@ -31,7 +28,7 @@ describe('App Passwords', function () { .send({ identifier: 'someapp', expiresAt: null }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot add app password without expiresAt', async function () { @@ -40,7 +37,7 @@ describe('App Passwords', function () { .send({ name: 'my-device', identifier: 'someapp' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot add app password with invalid expiresAt type', async function () { @@ -49,7 +46,7 @@ describe('App Passwords', function () { .send({ name: 'my-device', identifier: 'someapp', expiresAt: 12345 }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot add app password with invalid expiresAt date', async function () { @@ -58,7 +55,7 @@ describe('App Passwords', function () { .send({ name: 'my-device', identifier: 'someapp', expiresAt: 'not-a-date' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); let pwd; @@ -67,8 +64,8 @@ describe('App Passwords', function () { .query({ access_token: user.token }) .send({ name: 'my-device', identifier: 'someapp', expiresAt: null }); - expect(response.status).to.equal(201); - expect(response.body.password).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.password, 'string'); pwd = response.body; }); @@ -77,43 +74,43 @@ describe('App Passwords', function () { .query({ access_token: user.token }) .send({ name: 'expiring-device', identifier: 'someapp', expiresAt: new Date(Date.now() + 86400000).toISOString() }); - expect(response.status).to.equal(201); - expect(response.body.password).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.password, 'string'); }); it('can get app passwords', async function () { const response = await superagent.get(`${serverUrl}/api/v1/app_passwords`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.appPasswords).to.be.an(Array); - expect(response.body.appPasswords.length).to.be(2); - expect(response.body.appPasswords[0].name).to.be('expiring-device'); - expect(response.body.appPasswords[0].expiresAt).to.be.a('string'); - expect(response.body.appPasswords[1].name).to.be('my-device'); - expect(response.body.appPasswords[1].identifier).to.be('someapp'); - expect(response.body.appPasswords[1].expiresAt).to.be(null); - expect(response.body.appPasswords[1].hashedPassword).to.be(undefined); - expect(response.body.appPasswords[1].password).to.be(undefined); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.appPasswords)); + assert.equal(response.body.appPasswords.length, 2); + assert.equal(response.body.appPasswords[0].name, 'expiring-device'); + assert.equal(typeof response.body.appPasswords[0].expiresAt, 'string'); + assert.equal(response.body.appPasswords[1].name, 'my-device'); + assert.equal(response.body.appPasswords[1].identifier, 'someapp'); + assert.equal(response.body.appPasswords[1].expiresAt, null); + assert.equal(response.body.appPasswords[1].hashedPassword, undefined); + assert.equal(response.body.appPasswords[1].password, undefined); }); it('can get app password', async function () { const response = await superagent.get(`${serverUrl}/api/v1/app_passwords/${pwd.id}`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.name).to.be('my-device'); - expect(response.body.identifier).to.be('someapp'); - expect(response.body.expiresAt).to.be(null); - expect(response.body.hashedPassword).to.be(undefined); - expect(response.body.password).to.be(undefined); + assert.equal(response.status, 200); + assert.equal(response.body.name, 'my-device'); + assert.equal(response.body.identifier, 'someapp'); + assert.equal(response.body.expiresAt, null); + assert.equal(response.body.hashedPassword, undefined); + assert.equal(response.body.password, undefined); }); it('can del app password', async function () { const response = await superagent.del(`${serverUrl}/api/v1/app_passwords/${pwd.id}`) .query({ access_token: user.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); }); diff --git a/src/routes/test/appstore-test.js b/src/routes/test/appstore-test.js index deebfb28e..ea07852a4 100644 --- a/src/routes/test/appstore-test.js +++ b/src/routes/test/appstore-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import appstore from '../../appstore.js'; import common from './common.js'; import constants from '../../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ const { setup, cleanup, serverUrl, owner, appstoreToken } = common; @@ -21,7 +18,7 @@ describe('Appstore Apps API', function () { const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.be(424); + assert.equal(response.status, 424); }); it('cannot get app with bad token', async function () { @@ -33,8 +30,8 @@ describe('Appstore Apps API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.be(402); - expect(scope1.isDone()).to.be.ok(); + assert.equal(response.status, 402); + assert.ok(scope1.isDone()); }); it('can list apps', async function () { @@ -45,8 +42,8 @@ describe('Appstore Apps API', function () { const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(scope1.isDone()).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(scope1.isDone()); }); it('can get app', async function () { @@ -57,8 +54,8 @@ describe('Appstore Apps API', function () { const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps/org.wordpress.cloudronapp`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(scope1.isDone()).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(scope1.isDone()); }); it('can get app version', async function () { @@ -69,7 +66,7 @@ describe('Appstore Apps API', function () { const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps/org.wordpress.cloudronapp/versions/3.4.2`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(scope1.isDone()).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(scope1.isDone()); }); }); diff --git a/src/routes/test/archives-test.js b/src/routes/test/archives-test.js index d8dd4a893..cbbb6b47c 100644 --- a/src/routes/test/archives-test.js +++ b/src/routes/test/archives-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import archives from '../../archives.js'; import backups from '../../backups.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Archives API', function () { const { setup, cleanup, serverUrl, owner, auditSource, getDefaultBackupSite } = common; @@ -42,43 +39,43 @@ describe('Archives API', function () { it('list succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/archives`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.archives.length).to.be(1); - expect(response.body.archives[0].id).to.be(archiveId); - expect(response.body.archives[0].appConfig).to.eql(appBackup.appConfig); - expect(response.body.archives[0].manifest).to.eql(appBackup.manifest); + assert.equal(response.status, 200); + assert.equal(response.body.archives.length, 1); + assert.equal(response.body.archives[0].id, archiveId); + assert.deepEqual(response.body.archives[0].appConfig, appBackup.appConfig); + assert.deepEqual(response.body.archives[0].manifest, appBackup.manifest); }); it('get valid archive', async function () { const response = await superagent.get(`${serverUrl}/api/v1/archives/${archiveId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.appConfig).to.eql(appBackup.appConfig); - expect(response.body.manifest).to.eql(appBackup.manifest); + assert.equal(response.status, 200); + assert.deepEqual(response.body.appConfig, appBackup.appConfig); + assert.deepEqual(response.body.manifest, appBackup.manifest); }); it('cannot get invalid archive', async function () { const response = await superagent.get(`${serverUrl}/api/v1/archives/random`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot del invalid archive', async function () { const response = await superagent.del(`${serverUrl}/api/v1/archives/random`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('del valid archive', async function () { const response = await superagent.del(`${serverUrl}/api/v1/archives/${archiveId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/archives`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.archives.length).to.be(0); + assert.equal(response2.status, 200); + assert.equal(response2.body.archives.length, 0); }); }); diff --git a/src/routes/test/backups-test.js b/src/routes/test/backups-test.js index 84fe57b54..9312f2ad1 100644 --- a/src/routes/test/backups-test.js +++ b/src/routes/test/backups-test.js @@ -1,7 +1,7 @@ -/* global it, describe, before, after */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; import timers from 'timers/promises'; @@ -18,16 +18,16 @@ describe('Backups API', function () { const site = await getDefaultBackupSite(); const response = await superagent.post(`${serverUrl}/api/v1/backup_sites/${site.id}/create_backup`) .query({ access_token: admin.token }); - expect(response.status).to.equal(202); - expect(response.body.taskId).to.be.a('string'); + assert.equal(response.status, 202); + assert.equal(typeof response.body.taskId, 'string'); await waitForTask(response.body.taskId); }); it('can list', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backups`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.backups.length).to.be(1); + assert.equal(response.status, 200); + assert.equal(response.body.backups.length, 1); someBackup = response.body.backups[0]; }); @@ -35,24 +35,24 @@ describe('Backups API', function () { const site = await getDefaultBackupSite(); const response = await superagent.get(`${serverUrl}/api/v1/backup_sites/${site.id}/backups`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.backups.length).to.be(1); // only box backups are listed + assert.equal(response.status, 200); + assert.equal(response.body.backups.length, 1); // only box backups are listed }); it('cannot get random id', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backups/bad_id`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can get valid id', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backups/${someBackup.id}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.preserveSecs).to.be(0); - expect(response.body.label).to.be(''); + assert.equal(response.status, 200); + assert.equal(response.body.preserveSecs, 0); + assert.equal(response.body.label, ''); }); it('cannot update invalid preserve secs', async function () { @@ -60,14 +60,14 @@ describe('Backups API', function () { .query({ access_token: owner.token }) .send({ preserveSecs: 'not-a-number', label: 'some string' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can update', async function () { const response = await superagent.post(`${serverUrl}/api/v1/backups/${someBackup.id}`) .query({ access_token: owner.token }) .send({ preserveSecs: 30, label: 'NewOrleans' }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); describe('integrity', function () { @@ -75,9 +75,9 @@ describe('Backups API', function () { const response = await superagent.post(`${serverUrl}/api/v1/backups/${someBackup.id}/start_integrity_check`) .query({ access_token: admin.token }) .send({}); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); const taskId = response.body.taskId; - expect(taskId).to.be.a('string'); + assert.equal(typeof taskId, 'string'); }); it('wait for check', async function () { @@ -85,24 +85,24 @@ describe('Backups API', function () { for (let i = 0; i < 10; i++) { response = await superagent.get(`${serverUrl}/api/v1/backups/${someBackup.id}`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); if (!response.body.integrityCheckTask?.active) break; await timers.setTimeout(3000); } - expect(response.body.integrityCheckTask).to.be(null); + assert.equal(response.body.integrityCheckTask, null); }); it('has integrity fields', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backups/${someBackup.id}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.lastIntegrityCheckTime).to.be.a('string'); - expect(response.body.integrityCheckStatus).to.equal('passed'); - expect(response.body.integrityCheckResult.messages).to.eql([]); - expect(response.body.integrityCheckResult.stats).to.be.an('object'); - expect(response.body.integrityCheckTask).to.be(null); + assert.equal(response.status, 200); + assert.equal(typeof response.body.lastIntegrityCheckTime, 'string'); + assert.equal(response.body.integrityCheckStatus, 'passed'); + assert.deepEqual(response.body.integrityCheckResult.messages, []); + assert.equal(typeof response.body.integrityCheckResult.stats, 'object'); + assert.equal(response.body.integrityCheckTask, null); }); }); }); diff --git a/src/routes/test/backupsites-test.js b/src/routes/test/backupsites-test.js index 22cc448ca..696b0ad3b 100644 --- a/src/routes/test/backupsites-test.js +++ b/src/routes/test/backupsites-test.js @@ -1,8 +1,8 @@ -/* global it, describe, before, after */ +import { describe, it, before, after } from 'node:test'; import backupSites from '../../backupsites.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; describe('Backups API', function () { @@ -40,7 +40,7 @@ describe('Backups API', function () { .send(newSite) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('succeeds as owner', async function () { @@ -49,7 +49,7 @@ describe('Backups API', function () { .send(newSite) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); newSite.id = response.body.id; }); @@ -61,7 +61,7 @@ describe('Backups API', function () { .send(tmp) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); encryptedSite.id = response.body.id; }); }); @@ -70,14 +70,14 @@ describe('Backups API', function () { it('succeeds as admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backup_sites`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.backupSites.length).to.be(3); + assert.equal(response.status, 200); + assert.equal(response.body.backupSites.length, 3); const tmp = response.body.backupSites.find(t => t.id === newSite.id); - expect(tmp.provider).to.be(newSite.provider); - expect(tmp.config).to.be.ok(); - expect(tmp.format).to.be(newSite.format); - expect(tmp.name).to.be(newSite.name); - expect(tmp.enableForUpdates).to.be(true); + assert.equal(tmp.provider, newSite.provider); + assert.ok(tmp.config); + assert.equal(tmp.format, newSite.format); + assert.equal(tmp.name, newSite.name); + assert.equal(tmp.enableForUpdates, true); }); }); @@ -85,25 +85,25 @@ describe('Backups API', function () { it('succeeds as admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backup_sites/${newSite.id}`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.provider).to.be(newSite.provider); - expect(response.body.config).to.be.ok(); - expect(response.body.format).to.be(newSite.format); - expect(response.body.name).to.be(newSite.name); - expect(response.body.enableForUpdates).to.be(true); + assert.equal(response.status, 200); + assert.equal(response.body.provider, newSite.provider); + assert.ok(response.body.config); + assert.equal(response.body.format, newSite.format); + assert.equal(response.body.name, newSite.name); + assert.equal(response.body.enableForUpdates, true); }); it('succeeds as admin (encrypted)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backup_sites/${encryptedSite.id}`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.provider).to.be(encryptedSite.provider); - expect(response.body.config).to.be.ok(); - expect(response.body.format).to.be(encryptedSite.format); - expect(response.body.name).to.be(encryptedSite.name); - expect(response.body.enableForUpdates).to.be(false); - expect(response.body.encrypted).to.be(true); - expect(response.body.encryptedFilenames).to.be(true); + assert.equal(response.status, 200); + assert.equal(response.body.provider, encryptedSite.provider); + assert.ok(response.body.config); + assert.equal(response.body.format, encryptedSite.format); + assert.equal(response.body.name, encryptedSite.name); + assert.equal(response.body.enableForUpdates, false); + assert.equal(response.body.encrypted, true); + assert.equal(response.body.encryptedFilenames, true); }); }); @@ -114,7 +114,7 @@ describe('Backups API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set invalid schedule', async function () { @@ -123,7 +123,7 @@ describe('Backups API', function () { .send({ schedule: 'whatever' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set "never" schedule', async function () { @@ -132,10 +132,10 @@ describe('Backups API', function () { .send({ schedule: 'never' }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.schedule).to.be('never'); + assert.equal(result.schedule, 'never'); }); it('can set valid schedule', async function () { @@ -144,9 +144,9 @@ describe('Backups API', function () { .send({ schedule: '00 00 3 * * *' }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.schedule).to.be('00 00 3 * * *'); + assert.equal(result.schedule, '00 00 3 * * *'); }); }); @@ -157,7 +157,7 @@ describe('Backups API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set invalid retention', async function () { @@ -166,7 +166,7 @@ describe('Backups API', function () { .send({ retention: 'whatever' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set backup_policy with retention with invalid keepWithinSecs', async function () { @@ -175,7 +175,7 @@ describe('Backups API', function () { .send({ retention: { keepWithinSecs: 'not a number' } }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set valid retention', async function () { @@ -184,9 +184,9 @@ describe('Backups API', function () { .send({ retention: { keepWithinSecs: 2 * 24 * 60 * 60 } }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.retention).to.eql({ keepWithinSecs: 2 * 24 * 60 * 60 }); + assert.deepEqual(result.retention, { keepWithinSecs: 2 * 24 * 60 * 60 }); }); }); @@ -197,7 +197,7 @@ describe('Backups API', function () { .send({ limits: 2 }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set valid limits', async function () { @@ -206,9 +206,9 @@ describe('Backups API', function () { .send({ limits: { syncConcurrency: 34 } }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.limits).to.eql({ syncConcurrency: 34 }); + assert.deepEqual(result.limits, { syncConcurrency: 34 }); }); }); @@ -219,7 +219,7 @@ describe('Backups API', function () { .send({ contents: 'garbage' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set invalid include', async function () { @@ -228,7 +228,7 @@ describe('Backups API', function () { .send({ contents: { include: 'something' } }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set include', async function () { @@ -237,9 +237,9 @@ describe('Backups API', function () { .send({ contents: { include: [ 'something' ]} }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.contents).to.eql({ include: [ 'something' ]}); + assert.deepEqual(result.contents, { include: [ 'something' ]}); }); it('can set exclude', async function () { @@ -248,9 +248,9 @@ describe('Backups API', function () { .send({ contents: { exclude: [ 'something' ]} }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.contents).to.eql({ exclude: [ 'something' ] }); + assert.deepEqual(result.contents, { exclude: [ 'something' ] }); }); it('can set null', async function () { @@ -259,9 +259,9 @@ describe('Backups API', function () { .send({ contents: null }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.contents).to.eql(null); + assert.deepEqual(result.contents, null); }); }); @@ -272,7 +272,7 @@ describe('Backups API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can set enable_for_updates', async function () { @@ -283,12 +283,12 @@ describe('Backups API', function () { .send({ enable: false }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.enableForUpdates).to.be(false); + assert.equal(result.enableForUpdates, false); const result2 = await backupSites.get(oldDefault.id); - expect(result2.enableForUpdates).to.be(true); + assert.equal(result2.enableForUpdates, true); }); }); @@ -298,7 +298,7 @@ describe('Backups API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can delete', async function () { @@ -306,7 +306,7 @@ describe('Backups API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); @@ -321,7 +321,7 @@ describe('Backups API', function () { .send({ config: 32 }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set valid config', async function () { @@ -330,9 +330,9 @@ describe('Backups API', function () { .send({ config: someConfig }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const result = await backupSites.get(newSite.id); - expect(result.config.backupDir).to.be(someConfig.backupDir); + assert.equal(result.config.backupDir, someConfig.backupDir); }); }); @@ -340,16 +340,16 @@ describe('Backups API', function () { it('mount status', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backup_sites/${newSite.id}/status`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.state).to.be('active'); - expect(response.body.message).to.contain('Backups are stored'); + assert.equal(response.status, 200); + assert.equal(response.body.state, 'active'); + assert.ok(response.body.message.includes('Backups are stored')); }); it('remount', async function () { const response = await superagent.post(`${serverUrl}/api/v1/backup_sites/${newSite.id}/remount`) .query({ access_token: owner.token }) .send({}); - expect(response.status).to.equal(202); + assert.equal(response.status, 202); }); }); @@ -357,8 +357,8 @@ describe('Backups API', function () { it('succeeds', async function () { const response = await superagent.post(`${serverUrl}/api/v1/backup_sites/${newSite.id}/create_backup`) .query({ access_token: admin.token }); - expect(response.status).to.equal(202); - expect(response.body.taskId).to.be.a('string'); + assert.equal(response.status, 202); + assert.equal(typeof response.body.taskId, 'string'); await waitForTask(response.body.taskId); }); }); @@ -367,8 +367,8 @@ describe('Backups API', function () { it('succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/backup_sites/${newSite.id}/backups`) .query({ access_token: admin.token }); - expect(response.status).to.equal(200); - expect(response.body.backups).to.be.an(Array); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.backups)); }); }); }); diff --git a/src/routes/test/branding-test.js b/src/routes/test/branding-test.js index 895b60e92..65db3c5c7 100644 --- a/src/routes/test/branding-test.js +++ b/src/routes/test/branding-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import constants from '../../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import paths from '../../paths.js'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Branding API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -24,8 +21,8 @@ describe('Branding API', function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_name`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.name).to.be('Cloudron'); + assert.equal(response.status, 200); + assert.equal(response.body.name, 'Cloudron'); }); it('cannot set without name', async function () { @@ -33,7 +30,7 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set empty name', async function () { @@ -42,7 +39,7 @@ describe('Branding API', function () { .send({ name: '' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -50,15 +47,15 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .send({ name }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_name`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.name).to.eql(name); + assert.equal(response.status, 200); + assert.deepEqual(response.body.name, name); }); }); @@ -67,8 +64,8 @@ describe('Branding API', function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_avatar`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body).to.be.a(Buffer); + assert.equal(response.status, 200); + assert.ok((response.body) instanceof (Buffer)); }); it('cannot set without data', async function () { @@ -76,7 +73,7 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -84,15 +81,15 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .attach('avatar', paths.CLOUDRON_DEFAULT_AVATAR_FILE); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_avatar`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.toString()).to.eql(fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE, 'utf-8')); + assert.equal(response.status, 200); + assert.deepEqual(response.body.toString(), fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE, 'utf-8')); }); }); @@ -102,7 +99,7 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot set without data', async function () { @@ -110,7 +107,7 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -118,28 +115,28 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .attach('background', paths.CLOUDRON_DEFAULT_AVATAR_FILE); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_background`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.toString()).to.eql(fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE, 'utf-8')); + assert.equal(response.status, 200); + assert.deepEqual(response.body.toString(), fs.readFileSync(paths.CLOUDRON_DEFAULT_AVATAR_FILE, 'utf-8')); }); it('unset succeeds', async function () { const response = await superagent.del(`${serverUrl}/api/v1/branding/cloudron_background`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const response2 = await superagent.get(`${serverUrl}/api/v1/branding/cloudron_background`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(404); + assert.equal(response2.status, 404); }); }); @@ -149,8 +146,8 @@ describe('Branding API', function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/footer`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.footer).to.eql(constants.FOOTER); + assert.equal(response.status, 200); + assert.deepEqual(response.body.footer, constants.FOOTER); }); it('cannot set without data', async function () { @@ -158,7 +155,7 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -166,15 +163,15 @@ describe('Branding API', function () { .query({ access_token: owner.token }) .send({ footer: 'BigFoot Inc' }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/branding/footer`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.footer).to.eql('BigFoot Inc'); + assert.equal(response.status, 200); + assert.deepEqual(response.body.footer, 'BigFoot Inc'); }); }); }); diff --git a/src/routes/test/cloudron-test.js b/src/routes/test/cloudron-test.js index 9a729f4da..f5ee5af0c 100644 --- a/src/routes/test/cloudron-test.js +++ b/src/routes/test/cloudron-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import constants from '../../constants.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; import url from 'node:url'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Cloudron', function () { const { setup, cleanup, serverUrl, owner, user, dashboardFqdn } = common; @@ -21,31 +18,31 @@ describe('Cloudron', function () { const response = await superagent.get(`${serverUrl}/api/v1/dashboard/config`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can get config (admin)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/dashboard/config`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.apiServerOrigin).to.eql('http://localhost:6060'); - expect(response.body.webServerOrigin).to.eql('https://cloudron.io'); - expect(response.body.adminFqdn).to.eql(dashboardFqdn); - expect(response.body.version).to.eql(constants.VERSION); - expect(response.body.cloudronName).to.be.a('string'); + assert.equal(response.status, 200); + assert.deepEqual(response.body.apiServerOrigin, 'http://localhost:6060'); + assert.deepEqual(response.body.webServerOrigin, 'https://cloudron.io'); + assert.deepEqual(response.body.adminFqdn, dashboardFqdn); + assert.deepEqual(response.body.version, constants.VERSION); + assert.equal(typeof response.body.cloudronName, 'string'); }); it('can get config (non-admin)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/dashboard/config`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.apiServerOrigin).to.eql('http://localhost:6060'); - expect(response.body.webServerOrigin).to.eql('https://cloudron.io'); - expect(response.body.adminFqdn).to.eql(dashboardFqdn); - expect(response.body.version).to.eql(constants.VERSION); - expect(response.body.cloudronName).to.be.a('string'); + assert.equal(response.status, 200); + assert.deepEqual(response.body.apiServerOrigin, 'http://localhost:6060'); + assert.deepEqual(response.body.webServerOrigin, 'https://cloudron.io'); + assert.deepEqual(response.body.adminFqdn, dashboardFqdn); + assert.deepEqual(response.body.version, constants.VERSION); + assert.equal(typeof response.body.cloudronName, 'string'); }); }); @@ -59,13 +56,13 @@ describe('Cloudron', function () { const response = await superagent.post(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }) .send({ email }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); const userId = response.body.id; const response2 = await superagent.get(`${serverUrl}/api/v1/users/${userId}/invite_link`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(200); + assert.equal(response2.status, 200); const response3 = await superagent.post(`${serverUrl}/api/v1/auth/setup_account`) .send({ @@ -73,20 +70,20 @@ describe('Cloudron', function () { password, username, displayName }) .ok(() => true); - expect(response3.status).to.equal(201); - expect(response3.body.accessToken).to.be.a('string'); + assert.equal(response3.status, 201); + assert.equal(typeof response3.body.accessToken, 'string'); const response4 = await superagent.get(`${serverUrl}/api/v1/users/${userId}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response4.status).to.equal(200); - expect(response4.body.username).to.equal(username); - expect(response4.body.displayName).to.equal(displayName); + assert.equal(response4.status, 200); + assert.equal(response4.body.username, username); + assert.equal(response4.body.displayName, displayName); const response5 = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username, password }); - expect(response5.status).to.equal(200); + assert.equal(response5.status, 200); }); it('user can overwrite display name (username and email preset)', async function () { @@ -98,13 +95,13 @@ describe('Cloudron', function () { const response = await superagent.post(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }) .send({ email, username: 'presetup2', displayName: 'pre setup' }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); const userId = response.body.id; const response2 = await superagent.get(`${serverUrl}/api/v1/users/${userId}/invite_link`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(200); + assert.equal(response2.status, 200); const response3 = await superagent.post(`${serverUrl}/api/v1/auth/setup_account`) .send({ @@ -114,7 +111,7 @@ describe('Cloudron', function () { displayName }) .ok(() => true); - expect(response3.status).to.equal(409); + assert.equal(response3.status, 409); const response4 = await superagent.post(`${serverUrl}/api/v1/auth/setup_account`) .send({ @@ -123,20 +120,20 @@ describe('Cloudron', function () { displayName }) .ok(() => true); - expect(response4.status).to.equal(201); - expect(response4.body.accessToken).to.be.a('string'); + assert.equal(response4.status, 201); + assert.equal(typeof response4.body.accessToken, 'string'); const response5 = await superagent.get(`${serverUrl}/api/v1/users/${userId}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response5.status).to.equal(200); - expect(response5.body.username).to.equal(username); - expect(response5.body.displayName).to.equal(displayName); + assert.equal(response5.status, 200); + assert.equal(response5.body.username, username); + assert.equal(response5.body.displayName, displayName); const response6 = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username, password }); - expect(response6.status).to.equal(200); + assert.equal(response6.status, 200); }); it('cannot set username and display name when profiles are locked', async function () { @@ -147,18 +144,18 @@ describe('Cloudron', function () { const response0 = await superagent.post(`${serverUrl}/api/v1/user_directory/profile_config`) .query({ access_token: owner.token }) .send({ lockUserProfiles: true, mandatory2FA: false }); - expect(response0.status).to.equal(200); + assert.equal(response0.status, 200); const response = await superagent.post(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }) .send({ email, username: 'presetup3', displayName: 'pre setup3' }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); const userId = response.body.id; const response2 = await superagent.get(`${serverUrl}/api/v1/users/${userId}/invite_link`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(200); + assert.equal(response2.status, 200); let response3 = await superagent.post(`${serverUrl}/api/v1/auth/setup_account`) .send({ @@ -167,7 +164,7 @@ describe('Cloudron', function () { username, // cannot set username when profile is locked }) .ok(() => true); - expect(response3.status).to.equal(409); + assert.equal(response3.status, 409); response3 = await superagent.post(`${serverUrl}/api/v1/auth/setup_account`) .send({ @@ -175,19 +172,19 @@ describe('Cloudron', function () { password, }) .ok(() => true); - expect(response3.status).to.equal(201); + assert.equal(response3.status, 201); const response4 = await superagent.get(`${serverUrl}/api/v1/users/${userId}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response4.status).to.equal(200); - expect(response4.body.username).to.equal('presetup3'); // what the admin provided - expect(response4.body.displayName).to.equal('pre setup3'); // what the admin provided + assert.equal(response4.status, 200); + assert.equal(response4.body.username, 'presetup3'); // what the admin provided + assert.equal(response4.body.displayName, 'pre setup3'); // what the admin provided const response5 = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: 'presetup3', password }); - expect(response5.status).to.equal(200); + assert.equal(response5.status, 200); }); }); @@ -195,7 +192,7 @@ describe('Cloudron', function () { it('cannot login without body', async function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot login without username', async function () { @@ -203,7 +200,7 @@ describe('Cloudron', function () { .send({ password: owner.password }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot login without password', async function () { @@ -211,7 +208,7 @@ describe('Cloudron', function () { .send({ username: owner.username }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot login with empty username', async function () { @@ -219,7 +216,7 @@ describe('Cloudron', function () { .send({ username: '', password: owner.password }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot login with empty password', async function () { @@ -227,7 +224,7 @@ describe('Cloudron', function () { .send({ username: owner.username, password: '' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot login with unknown username', async function () { @@ -235,7 +232,7 @@ describe('Cloudron', function () { .send({ username: 'somethingrandom', password: owner.password }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot login with unknown email', async function () { @@ -243,7 +240,7 @@ describe('Cloudron', function () { .send({ username: 'randomgemail', password: owner.password }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot login with wrong password', async function () { @@ -251,43 +248,43 @@ describe('Cloudron', function () { .send({ username: owner.username, password: owner.password.toUpperCase() }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can login with username', async function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: owner.username, password: owner.password }); - expect(response.status).to.equal(200); - expect(new Date(response.body.expires).toString()).to.not.be('Invalid Date'); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.notEqual(new Date(response.body.expires).toString(), 'Invalid Date'); + assert.equal(typeof response.body.accessToken, 'string'); }); it('can login with uppercase username', async function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: owner.username.toUpperCase(), password: owner.password }); - expect(response.status).to.equal(200); - expect(new Date(response.body.expires).toString()).to.not.be('Invalid Date'); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.notEqual(new Date(response.body.expires).toString(), 'Invalid Date'); + assert.equal(typeof response.body.accessToken, 'string'); }); it('can login with email', async function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: owner.email, password: owner.password }); - expect(response.status).to.equal(200); - expect(new Date(response.body.expires).toString()).to.not.be('Invalid Date'); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.notEqual(new Date(response.body.expires).toString(), 'Invalid Date'); + assert.equal(typeof response.body.accessToken, 'string'); }); it('can login with uppercase email', async function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: owner.email.toUpperCase(), password: owner.password }); - expect(response.status).to.equal(200); - expect(new Date(response.body.expires).toString()).to.not.be('Invalid Date'); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.notEqual(new Date(response.body.expires).toString(), 'Invalid Date'); + assert.equal(typeof response.body.accessToken, 'string'); }); }); @@ -295,9 +292,9 @@ describe('Cloudron', function () { it('succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/cloudron/languages`); - expect(response.status).to.equal(200); - expect(response.body.languages).to.be.an('array'); - expect(response.body.languages.indexOf('en')).to.not.equal(-1); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.languages)); + assert.notEqual(response.body.languages.indexOf('en'), -1); }); }); }); diff --git a/src/routes/test/common.js b/src/routes/test/common.js index 11e7aeec8..d6ab3e6e4 100644 --- a/src/routes/test/common.js +++ b/src/routes/test/common.js @@ -4,7 +4,7 @@ import backupSites from '../../backupsites.js'; import debugModule from 'debug'; import constants from '../../constants.js'; import database from '../../database.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import mailer from '../../mailer.js'; import nock from 'nock'; import oidcClients from '../../oidcclients.js'; @@ -115,7 +115,7 @@ async function setup() { // setup let response = await superagent.post(`${serverUrl}/api/v1/provision/setup`) .send({ domainConfig: { provider: 'noop', domain: dashboardDomain, config: {}, tlsConfig: { provider: 'fallback' } } }); - expect(response.status).to.eql(200); + assert.deepEqual(response.status, 200); await timers.setTimeout(2000); @@ -132,19 +132,19 @@ async function setup() { .query({ setupToken: 'somesetuptoken' }) .send({ username: owner.username, password: owner.password, email: owner.email }) .ok(() => true); - expect(response.status).to.eql(201); + assert.deepEqual(response.status, 201); owner.token = response.body.token; owner.id = response.body.userId; - expect(scope1.isDone()).to.be.ok(); + assert.ok(scope1.isDone()); scope1.persist(false); - expect(scope2.isDone()).to.be.ok(); + assert.ok(scope2.isDone()); scope2.persist(false); // create an admin response = await superagent.post(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }) .send({ username: admin.username, email: admin.email, password: admin.password, role: 'admin' }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); admin.id = response.body.id; // HACK to get a token for second user (passwords are generated and the user should have gotten a password setup link...) const token1 = await tokens.add({ identifier: admin.id, clientId: oidcClients.ID_WEBADMIN, expires: Date.now() + (60 * 60 * 1000), name: 'fromtest', allowedIpRanges: '' }); @@ -154,7 +154,7 @@ async function setup() { response = await superagent.post(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }) .send({ username: user.username, email: user.email, password: user.password }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); user.id = response.body.id; // HACK to get a token for second user (passwords are generated and the user should have gotten a password setup link...) const token2 = await tokens.add({ identifier: user.id, clientId: oidcClients.ID_WEBADMIN, expires: Date.now() + (60 * 60 * 1000), name: 'fromtest', allowedIpRanges: '' }); @@ -182,7 +182,7 @@ function clearMailQueue() { async function checkMails(number) { await timers.setTimeout(1000); - expect(mailer._mailQueue.length).to.equal(number); + assert.equal(mailer._mailQueue.length, number); clearMailQueue(); } @@ -191,7 +191,7 @@ async function waitForTask(taskId) { for (let i = 0; i < 30; i++) { const result = await tasks.get(taskId); - expect(result).to.not.be(null); + assert.notEqual(result, null); if (!result.active) { if (result.success) return result; throw new Error(`Task ${taskId} failed: ${result.error.message} - ${result.error.stack}`); diff --git a/src/routes/test/directoryserver-test.js b/src/routes/test/directoryserver-test.js index 2c1a7710f..a4c842889 100644 --- a/src/routes/test/directoryserver-test.js +++ b/src/routes/test/directoryserver-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Directory Server API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -26,8 +23,8 @@ describe('Directory Server API', function () { const response = await superagent.get(`${serverUrl}/api/v1/directory_server/config`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body).to.eql(defaultConfig); + assert.equal(response.status, 200); + assert.deepEqual(response.body, defaultConfig); }); it('cannot set directory_server config without enabled boolean', async function () { @@ -39,7 +36,7 @@ describe('Directory Server API', function () { .send(tmp) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set directory_server config without secret', async function () { @@ -52,7 +49,7 @@ describe('Directory Server API', function () { .send(tmp) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot enable directory_server config with empty secret', async function () { @@ -64,7 +61,7 @@ describe('Directory Server API', function () { .send(tmp) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot enable directory_server config with empty allowlist', async function () { @@ -77,7 +74,7 @@ describe('Directory Server API', function () { .send(tmp) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can enable directory_server config', async function () { @@ -90,7 +87,7 @@ describe('Directory Server API', function () { .query({ access_token: owner.token }) .send(tmp); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('can get directory_server config', async function () { @@ -100,8 +97,8 @@ describe('Directory Server API', function () { const response = await superagent.get(`${serverUrl}/api/v1/directory_server/config`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body).to.eql({ enabled: true, secret: 'ldapsecret', allowlist: '1.2.3.4' }); + assert.equal(response.status, 200); + assert.deepEqual(response.body, { enabled: true, secret: 'ldapsecret', allowlist: '1.2.3.4' }); }); // keep this last. this ensures directory server is stopped and the tests can exit @@ -114,7 +111,7 @@ describe('Directory Server API', function () { .query({ access_token: owner.token }) .send(tmp); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); }); }); diff --git a/src/routes/test/dockerregistries-test.js b/src/routes/test/dockerregistries-test.js index e14e1374e..aab1b581b 100644 --- a/src/routes/test/dockerregistries-test.js +++ b/src/routes/test/dockerregistries-test.js @@ -1,13 +1,10 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Docker Registries', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -21,7 +18,7 @@ describe('Docker Registries', function () { .send({ provider: 'devops', serverAddress: 'registry.devops' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot add registry without provider', async function () { @@ -30,7 +27,7 @@ describe('Docker Registries', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); let id; @@ -39,8 +36,8 @@ describe('Docker Registries', function () { .query({ access_token: owner.token }) .send({ provider: 'devops', serverAddress: 'registry.devops', password: 'hushhush' }); - expect(response.status).to.equal(201); - expect(response.body.id).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.id, 'string'); id = response.body.id; }); @@ -48,12 +45,12 @@ describe('Docker Registries', function () { const response = await superagent.get(`${serverUrl}/api/v1/docker/registries`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.registries).to.be.an(Array); - expect(response.body.registries.length).to.be(1); - expect(response.body.registries[0].provider).to.be('devops'); - expect(response.body.registries[0].serverAddress).to.be('registry.devops'); - expect(response.body.registries[0].password).to.be(undefined); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.registries)); + assert.equal(response.body.registries.length, 1); + assert.equal(response.body.registries[0].provider, 'devops'); + assert.equal(response.body.registries[0].serverAddress, 'registry.devops'); + assert.equal(response.body.registries[0].password, undefined); }); it('can update registry', async function () { @@ -61,23 +58,23 @@ describe('Docker Registries', function () { .query({ access_token: owner.token }) .send({ provider: 'devops2', serverAddress: 'registry.devops2', password: 'hushhush2' }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('can get registry', async function () { const response = await superagent.get(`${serverUrl}/api/v1/docker/registries/${id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.provider).to.be('devops2'); - expect(response.body.serverAddress).to.be('registry.devops2'); - expect(response.body.password).to.be(undefined); + assert.equal(response.status, 200); + assert.equal(response.body.provider, 'devops2'); + assert.equal(response.body.serverAddress, 'registry.devops2'); + assert.equal(response.body.password, undefined); }); it('can del registry', async function () { const response = await superagent.del(`${serverUrl}/api/v1/docker/registries/${id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); diff --git a/src/routes/test/domains-test.js b/src/routes/test/domains-test.js index 7c0bd2a5b..b99d8a254 100644 --- a/src/routes/test/domains-test.js +++ b/src/routes/test/domains-test.js @@ -1,16 +1,13 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import child_process from 'node:child_process'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import paths from '../../paths.js'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ const DOMAIN_0 = { domain: 'domain0.com', @@ -44,7 +41,7 @@ describe('Domains API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails with invalid domain', async function () { @@ -53,7 +50,7 @@ describe('Domains API', function () { .send({ domain: 'abc' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails with unknown provider', async function () { @@ -62,7 +59,7 @@ describe('Domains API', function () { .send({ domain: 'cloudron.com', provider: 'doesnotexist', config: { }}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails with invalid tlsConfig', async function () { @@ -71,7 +68,7 @@ describe('Domains API', function () { .send({ domain: 'cloudron.com', provider: 'noop', config: { }, tlsConfig: 'foobar' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails with unknown tls provider', async function () { @@ -80,7 +77,7 @@ describe('Domains API', function () { .send({ domain: 'cloudron.com', provider: 'noop', config: { }, tlsConfig: { provider: 'hello' }}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails without token', async function () { @@ -89,7 +86,7 @@ describe('Domains API', function () { .send(DOMAIN_0) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails for normal user', async function () { @@ -98,7 +95,7 @@ describe('Domains API', function () { .send(DOMAIN_0) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('succeeds', async function () { @@ -106,7 +103,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send(DOMAIN_0); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('succeeds for second domain without zoneName', async function () { @@ -114,7 +111,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send(DOMAIN_1); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('fails for already added domain', async function () { @@ -123,7 +120,7 @@ describe('Domains API', function () { .send(DOMAIN_0) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); }); @@ -132,20 +129,20 @@ describe('Domains API', function () { const response = await superagent.get(`${serverUrl}/api/v1/domains`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.domains).to.be.an(Array); - expect(response.body.domains.length).to.equal(3); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.domains)); + assert.equal(response.body.domains.length, 3); - expect(response.body.domains[0].domain).to.equal(DOMAIN_0.domain); - expect(response.body.domains[1].domain).to.equal(DOMAIN_1.domain); - expect(response.body.domains[2].domain).to.equal(dashboardDomain); + assert.equal(response.body.domains[0].domain, DOMAIN_0.domain); + assert.equal(response.body.domains[1].domain, DOMAIN_1.domain); + assert.equal(response.body.domains[2].domain, dashboardDomain); for (const d of response.body.domains) { - expect(d.tlsConfig).to.be.an('object'); - expect(d.config).to.be.an('object'); - expect(d.fallbackCertificate).to.be.an('object'); - expect(d.fallbackCertificate.cert).to.be.a('string'); - expect(d.fallbackCertificate.key).to.be(undefined); + assert.equal(typeof d.tlsConfig, 'object'); + assert.equal(typeof d.config, 'object'); + assert.equal(typeof d.fallbackCertificate, 'object'); + assert.equal(typeof d.fallbackCertificate.cert, 'string'); + assert.equal(d.fallbackCertificate.key, undefined); } }); @@ -153,20 +150,20 @@ describe('Domains API', function () { const response = await superagent.get(`${serverUrl}/api/v1/domains`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.domains).to.be.an(Array); - expect(response.body.domains.length).to.equal(3); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.domains)); + assert.equal(response.body.domains.length, 3); - expect(response.body.domains[0].domain).to.equal(DOMAIN_0.domain); - expect(response.body.domains[1].domain).to.equal(DOMAIN_1.domain); - expect(response.body.domains[2].domain).to.equal(dashboardDomain); + assert.equal(response.body.domains[0].domain, DOMAIN_0.domain); + assert.equal(response.body.domains[1].domain, DOMAIN_1.domain); + assert.equal(response.body.domains[2].domain, dashboardDomain); for (const d of response.body.domains) { - expect(d.tlsConfig).to.be.an('object'); - expect(d.config).to.be.an('object'); - expect(d.fallbackCertificate).to.be.an('object'); - expect(d.fallbackCertificate.cert).to.be.a('string'); - expect(d.fallbackCertificate.key).to.be(undefined); + assert.equal(typeof d.tlsConfig, 'object'); + assert.equal(typeof d.config, 'object'); + assert.equal(typeof d.fallbackCertificate, 'object'); + assert.equal(typeof d.fallbackCertificate.cert, 'string'); + assert.equal(d.fallbackCertificate.key, undefined); } }); @@ -178,21 +175,21 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/domains/${DOMAIN_0.domain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const d = response.body; - expect(d.domain).to.equal(DOMAIN_0.domain); - expect(d.tlsConfig).to.be.an('object'); - expect(d.config).to.be.an('object'); - expect(d.fallbackCertificate).to.be.an('object'); - expect(d.fallbackCertificate.cert).to.be.a('string'); - expect(d.fallbackCertificate.key).to.be(undefined); + assert.equal(d.domain, DOMAIN_0.domain); + assert.equal(typeof d.tlsConfig, 'object'); + assert.equal(typeof d.config, 'object'); + assert.equal(typeof d.fallbackCertificate, 'object'); + assert.equal(typeof d.fallbackCertificate.cert, 'string'); + assert.equal(d.fallbackCertificate.key, undefined); }); it('fails for normal user', async function () { @@ -200,7 +197,7 @@ describe('Domains API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); }); @@ -210,7 +207,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('config fails as normal user', async function () { @@ -219,7 +216,7 @@ describe('Domains API', function () { .send(DOMAIN_0) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('config succeeds as admin', async function () { @@ -227,7 +224,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send(DOMAIN_0); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('wellknown succeeds', async function () { @@ -235,7 +232,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send({ wellKnown: null }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('wellknown succeeds', async function () { @@ -243,7 +240,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send({ wellKnown: { service: 'some.service' } }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); @@ -270,7 +267,7 @@ describe('Domains API', function () { .send(d) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set certificate without key', async function () { @@ -282,7 +279,7 @@ describe('Domains API', function () { .send(d) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set certificate with cert not being a string', async function () { @@ -294,7 +291,7 @@ describe('Domains API', function () { .send(d) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set certificate with key not being a string', async function () { @@ -306,7 +303,7 @@ describe('Domains API', function () { .send(d) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set non-fallback certificate', async function () { @@ -318,7 +315,7 @@ describe('Domains API', function () { .send(d) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set fallback certificate', async function () { @@ -329,15 +326,15 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .send(d); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('did set the certificate', async function () { const cert = fs.readFileSync(path.join(paths.NGINX_CERT_DIR, `${DOMAIN_0.domain}.host.cert`), 'utf-8'); - expect(cert).to.eql(validCert1); + assert.deepEqual(cert, validCert1); const key = fs.readFileSync(path.join(paths.NGINX_CERT_DIR, `${DOMAIN_0.domain}.host.key`), 'utf-8'); - expect(key).to.eql(validKey1); + assert.deepEqual(key, validKey1); }); }); @@ -347,7 +344,7 @@ describe('Domains API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('fails for normal user', async function () { @@ -355,20 +352,20 @@ describe('Domains API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('succeeds as admin', async function () { const response = await superagent.del(`${serverUrl}/api/v1/domains/${DOMAIN_0.domain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/domains/${DOMAIN_0.domain}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(404); + assert.equal(response2.status, 404); }); }); }); diff --git a/src/routes/test/eventlog-test.js b/src/routes/test/eventlog-test.js index 7ac954063..50fef05a3 100644 --- a/src/routes/test/eventlog-test.js +++ b/src/routes/test/eventlog-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import async from 'async'; import common from './common.js'; import eventlog from '../../eventlog.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Eventlog API', function () { const { setup, cleanup, serverUrl, owner, user } = common; @@ -21,11 +18,11 @@ describe('Eventlog API', function () { data: { something: 'is there' } }; - before(function (done) { - async.series([ + before(async function () { + await async.series([ setup, async () => { EVENT_0.id = await eventlog.add(EVENT_0.action, EVENT_0.source, EVENT_0.data); }, - ], done); + ]); }); after(cleanup); @@ -34,14 +31,14 @@ describe('Eventlog API', function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog/someid`) .query({ access_token: 'badtoken' }) .ok(() => true); - expect(response.status).to.be(401); + assert.equal(response.status, 401); }); it('fails for non-admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog/someid`) .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('fails if not exists', async function () { @@ -49,7 +46,7 @@ describe('Eventlog API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('succeeds for admin', async function () { @@ -57,9 +54,9 @@ describe('Eventlog API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); delete response.body.event.creationTime; - expect(response.body.event).to.eql(EVENT_0); + assert.deepEqual(response.body.event, EVENT_0); }); }); @@ -68,7 +65,7 @@ describe('Eventlog API', function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: 'badtoken' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails for non-admin', async function () { @@ -76,47 +73,47 @@ describe('Eventlog API', function () { .query({ access_token: user.token, page: 1, per_page: 10 }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('succeeds for admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10 }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs.length >= 2).to.be.ok(); // activate, user.add + assert.equal(response.status, 200); + assert.ok(response.body.eventlogs.length >= 2); // activate, user.add }); it('succeeds with action', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10, action: 'cloudron.activate' }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs.length).to.equal(1); + assert.equal(response.status, 200); + assert.equal(response.body.eventlogs.length, 1); }); it('succeeds with actions', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10, actions: 'cloudron.activate, user.add' }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs.length).to.equal(4); + assert.equal(response.status, 200); + assert.equal(response.body.eventlogs.length, 4); }); it('succeeds with search', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10, search: owner.email }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs.length).to.equal(1); + assert.equal(response.status, 200); + assert.equal(response.body.eventlogs.length, 1); }); it('succeeds with search and actions', async function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10, search: owner.email, actions: 'cloudron.activate' }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs.length).to.equal(0); + assert.equal(response.status, 200); + assert.equal(response.body.eventlogs.length, 0); }); it('succeeds with from and to', async function () { @@ -125,8 +122,8 @@ describe('Eventlog API', function () { const response = await superagent.get(`${serverUrl}/api/v1/eventlog`) .query({ access_token: owner.token, page: 1, per_page: 10, from, to }); - expect(response.status).to.equal(200); - expect(response.body.eventlogs).to.be.an('array'); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.eventlogs)); }); it('fails with invalid from', async function () { @@ -134,7 +131,7 @@ describe('Eventlog API', function () { .query({ access_token: owner.token, page: 1, per_page: 10, from: 'not-a-date' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails with invalid to', async function () { @@ -142,7 +139,7 @@ describe('Eventlog API', function () { .query({ access_token: owner.token, page: 1, per_page: 10, to: 'invalid' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); }); }); diff --git a/src/routes/test/externalldap-test.js b/src/routes/test/externalldap-test.js index b472aef37..d25abe9ef 100644 --- a/src/routes/test/externalldap-test.js +++ b/src/routes/test/externalldap-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('External LDAP API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -22,8 +19,8 @@ describe('External LDAP API', function () { const response = await superagent.get(`${serverUrl}/api/v1/external_ldap/config`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body).to.eql(defaultConfig); + assert.equal(response.status, 200); + assert.deepEqual(response.body, defaultConfig); }); it('can set external_ldap to noop', async function () { @@ -34,7 +31,7 @@ describe('External LDAP API', function () { .query({ access_token: owner.token }) .send(config); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); }); }); diff --git a/src/routes/test/groups-test.js b/src/routes/test/groups-test.js index cc9e7f16b..4663dbc03 100644 --- a/src/routes/test/groups-test.js +++ b/src/routes/test/groups-test.js @@ -1,13 +1,10 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ const GROUP_NAME = 'externals'; let group0Object, group1Object; @@ -23,7 +20,7 @@ describe('Groups API', function () { .send({ name: GROUP_NAME }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('create succeeds', async function () { @@ -31,7 +28,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ name: GROUP_NAME }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); group0Object = response.body; }); @@ -41,7 +38,7 @@ describe('Groups API', function () { .send({ name: GROUP_NAME}) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('can create another group', async function () { @@ -49,7 +46,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ name: 'group1'}); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); group1Object = response.body; }); @@ -59,7 +56,7 @@ describe('Groups API', function () { .send({ groupIds: [ group0Object.id, 'something' ]}) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can set groups of a user', async function () { @@ -67,7 +64,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ groupIds: [ group0Object.id, group1Object.id ]}); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('cannot set duplicate groups for a user', async function () { @@ -76,7 +73,7 @@ describe('Groups API', function () { .send({ groupIds: [ group0Object.id, group1Object.id, group0Object.id ]}) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('can set users of a group', async function () { @@ -84,7 +81,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ userIds: [ owner.id, user.id ]}); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('cannot set duplicate users of a group', async function () { @@ -93,7 +90,7 @@ describe('Groups API', function () { .send({ userIds: [ owner.id, user.id, owner.id ]}) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('cannot get non-existing group', async function () { @@ -101,7 +98,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot get existing group with normal user', async function () { @@ -109,25 +106,25 @@ describe('Groups API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can get existing group', async function () { const response = await superagent.get(`${serverUrl}/api/v1/groups/${group0Object.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.name).to.be(group0Object.name); - expect(response.body.userIds.length).to.be(2); - expect(response.body.userIds).to.contain(owner.id); - expect(response.body.userIds).to.contain(user.id); + assert.equal(response.status, 200); + assert.equal(response.body.name, group0Object.name); + assert.equal(response.body.userIds.length, 2); + assert.ok(response.body.userIds.includes(owner.id)); + assert.ok(response.body.userIds.includes(user.id)); }); it('cannot list groups without token', async function () { const response = await superagent.get(`${serverUrl}/api/v1/groups`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot list groups as normal user', async function () { @@ -135,18 +132,18 @@ describe('Groups API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can list groups', async function () { const response = await superagent.get(`${serverUrl}/api/v1/groups`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.groups).to.be.an(Array); - expect(response.body.groups.length).to.be(2); - expect(response.body.groups[0].name).to.eql(group0Object.name); - expect(response.body.groups[1].name).to.eql(group1Object.name); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.groups)); + assert.equal(response.body.groups.length, 2); + assert.deepEqual(response.body.groups[0].name, group0Object.name); + assert.deepEqual(response.body.groups[1].name, group1Object.name); }); it('cannot set missing group name', async function () { @@ -155,7 +152,7 @@ describe('Groups API', function () { .send({ }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set invalid group name', async function () { @@ -164,7 +161,7 @@ describe('Groups API', function () { .send({ name: '!group1-newname'}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set group name', async function () { @@ -172,7 +169,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ name: 'group1-newname'}); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('cannot set unknown app access', async function () { @@ -181,7 +178,7 @@ describe('Groups API', function () { .send({ appIds: ['app-id' ] }) .ok(() => true); - expect(response.status).to.equal(200); // bad appId is just ignored + assert.equal(response.status, 200); // bad appId is just ignored }); it('can set app access', async function () { @@ -189,7 +186,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ appIds: [app.id] }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('did set app access', async function () { @@ -197,7 +194,7 @@ describe('Groups API', function () { .query({ access_token: owner.token }); const group1 = response.body.groups.filter(g => g.id === group1Object.id)[0]; - expect(group1.appIds).to.eql([app.id]); + assert.deepEqual(group1.appIds, [app.id]); }); it('remove user from group', async function () { @@ -205,14 +202,14 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ groupIds: [ group0Object.id ]}); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('cannot remove without token', async function () { const response = await superagent.del(`${serverUrl}/api/v1/groups/externals`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can clear users of a group', async function () { @@ -220,20 +217,20 @@ describe('Groups API', function () { .query({ access_token: owner.token }) .send({ userIds: [ ]}); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('can remove empty group', async function () { const response = await superagent.del(`${serverUrl}/api/v1/groups/${group1Object.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('can remove non-empty group', async function () { const response = await superagent.del(`${serverUrl}/api/v1/groups/${group0Object.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); diff --git a/src/routes/test/mail-test.js b/src/routes/test/mail-test.js index bb42be8e0..fcee3c12d 100644 --- a/src/routes/test/mail-test.js +++ b/src/routes/test/mail-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import mail from '../../mail.js'; import superagent from '@cloudron/superagent'; import _ from '../../underscore.js'; import dig from '../../dig.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Mail API', function () { const { setup, cleanup, serverUrl, owner, dashboardDomain, dashboardFqdn, mailFqdn } = common; @@ -29,21 +26,21 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can get domain', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.domain).to.equal(dashboardDomain); - expect(response.body.enabled).to.equal(false); - expect(response.body.mailFromValidation).to.equal(true); - expect(response.body.catchAll).to.be.an(Array); - expect(response.body.catchAll.length).to.equal(0); - expect(response.body.relay).to.be.an('object'); - expect(response.body.relay.provider).to.equal('cloudron-smtp'); + assert.equal(response.status, 200); + assert.equal(response.body.domain, dashboardDomain); + assert.equal(response.body.enabled, false); + assert.equal(response.body.mailFromValidation, true); + assert.ok(Array.isArray(response.body.catchAll)); + assert.equal(response.body.catchAll.length, 0); + assert.equal(typeof response.body.relay, 'object'); + assert.equal(response.body.relay.provider, 'cloudron-smtp'); }); }); @@ -55,7 +52,7 @@ describe('Mail API', function () { // replace dns resolveTxt() dig._setMockResolve(async function (hostname, type/*, options*/) { - expect(hostname).to.be.a('string'); + assert.equal(typeof hostname, 'string'); if (!dnsAnswerQueue[hostname] || !(type in dnsAnswerQueue[hostname])) throw new Error('no mock answer'); @@ -73,21 +70,18 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .send({ enabled: true }); - expect(response.status).to.be(202); + assert.equal(response.status, 202); }); - after(function (done) { - + after(function () { dig._setMockResolve(null); - - done(); }); it('does not fail when dns errors', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/status`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); function clearDnsAnswerQueue() { @@ -103,39 +97,39 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/status') .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.dkim).to.be.an('object'); - expect(response.body.dkim.domain).to.eql(dkimDomain); - expect(response.body.dkim.type).to.eql('TXT'); - expect(response.body.dkim.value).to.eql(null); - expect(response.body.dkim.expected).to.eql(`v=DKIM1; t=s; p=${publicKey}`); - expect(response.body.dkim.status).to.eql('failed'); + assert.equal(typeof response.body.dkim, 'object'); + assert.deepEqual(response.body.dkim.domain, dkimDomain); + assert.deepEqual(response.body.dkim.type, 'TXT'); + assert.deepEqual(response.body.dkim.value, null); + assert.deepEqual(response.body.dkim.expected, `v=DKIM1; t=s; p=${publicKey}`); + assert.deepEqual(response.body.dkim.status, 'failed'); - expect(response.body.spf).to.be.an('object'); - expect(response.body.spf.domain).to.eql(spfDomain); - expect(response.body.spf.type).to.eql('TXT'); - expect(response.body.spf.value).to.eql(null); - expect(response.body.spf.expected).to.eql(`v=spf1 a:${dashboardFqdn} ~all`); - expect(response.body.spf.status).to.eql('failed'); + assert.equal(typeof response.body.spf, 'object'); + assert.deepEqual(response.body.spf.domain, spfDomain); + assert.deepEqual(response.body.spf.type, 'TXT'); + assert.deepEqual(response.body.spf.value, null); + assert.deepEqual(response.body.spf.expected, `v=spf1 a:${dashboardFqdn} ~all`); + assert.deepEqual(response.body.spf.status, 'failed'); - expect(response.body.dmarc).to.be.an('object'); - expect(response.body.dmarc.type).to.eql('TXT'); - expect(response.body.dmarc.value).to.eql(null); - expect(response.body.dmarc.expected).to.eql('v=DMARC1; p=reject; pct=100'); - expect(response.body.dmarc.status).to.eql('failed'); + assert.equal(typeof response.body.dmarc, 'object'); + assert.deepEqual(response.body.dmarc.type, 'TXT'); + assert.deepEqual(response.body.dmarc.value, null); + assert.deepEqual(response.body.dmarc.expected, 'v=DMARC1; p=reject; pct=100'); + assert.deepEqual(response.body.dmarc.status, 'failed'); - expect(response.body.mx).to.be.an('object'); - expect(response.body.mx.type).to.eql('MX'); - expect(response.body.mx.value).to.eql(null); - expect(response.body.mx.expected).to.eql(`10 ${mailFqdn}.`); - expect(response.body.mx.status).to.eql('failed'); + assert.equal(typeof response.body.mx, 'object'); + assert.deepEqual(response.body.mx.type, 'MX'); + assert.deepEqual(response.body.mx.value, null); + assert.deepEqual(response.body.mx.expected, `10 ${mailFqdn}.`); + assert.deepEqual(response.body.mx.status, 'failed'); - expect(response.body.ptr4).to.be.an('object'); - expect(response.body.ptr4.type).to.eql('PTR'); - // expect(response.body.ptr.value).to.eql(null); this will be anything random - expect(response.body.ptr4.expected).to.eql(mailFqdn); - expect(response.body.ptr4.status).to.eql('failed'); + assert.equal(typeof response.body.ptr4, 'object'); + assert.deepEqual(response.body.ptr4.type, 'PTR'); + // assert.deepEqual(response.body.ptr.value, null); this will be anything random + assert.deepEqual(response.body.ptr4.expected, mailFqdn); + assert.deepEqual(response.body.ptr4.status, 'failed'); }); it('succeeds with "undefined" spf, dkim, dmarc, mx, ptr records', async function () { @@ -149,32 +143,32 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/status') .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.spf).to.be.an('object'); - expect(response.body.spf.expected).to.eql(`v=spf1 a:${dashboardFqdn} ~all`); - expect(response.body.spf.status).to.eql('failed'); - expect(response.body.spf.value).to.eql(null); + assert.equal(typeof response.body.spf, 'object'); + assert.deepEqual(response.body.spf.expected, `v=spf1 a:${dashboardFqdn} ~all`); + assert.deepEqual(response.body.spf.status, 'failed'); + assert.deepEqual(response.body.spf.value, null); - expect(response.body.dkim).to.be.an('object'); - expect(response.body.dkim.expected).to.eql(`v=DKIM1; t=s; p=${publicKey}`); - expect(response.body.dkim.status).to.eql('failed'); - expect(response.body.dkim.value).to.eql(null); + assert.equal(typeof response.body.dkim, 'object'); + assert.deepEqual(response.body.dkim.expected, `v=DKIM1; t=s; p=${publicKey}`); + assert.deepEqual(response.body.dkim.status, 'failed'); + assert.deepEqual(response.body.dkim.value, null); - expect(response.body.dmarc).to.be.an('object'); - expect(response.body.dmarc.expected).to.eql('v=DMARC1; p=reject; pct=100'); - expect(response.body.dmarc.status).to.eql('failed'); - expect(response.body.dmarc.value).to.eql(null); + assert.equal(typeof response.body.dmarc, 'object'); + assert.deepEqual(response.body.dmarc.expected, 'v=DMARC1; p=reject; pct=100'); + assert.deepEqual(response.body.dmarc.status, 'failed'); + assert.deepEqual(response.body.dmarc.value, null); - expect(response.body.mx).to.be.an('object'); - expect(response.body.mx.status).to.eql('failed'); - expect(response.body.mx.expected).to.eql(`10 ${mailFqdn}.`); - expect(response.body.mx.value).to.eql(null); + assert.equal(typeof response.body.mx, 'object'); + assert.deepEqual(response.body.mx.status, 'failed'); + assert.deepEqual(response.body.mx.expected, `10 ${mailFqdn}.`); + assert.deepEqual(response.body.mx.value, null); - expect(response.body.ptr4).to.be.an('object'); - expect(response.body.ptr4.expected).to.eql(mailFqdn); - expect(response.body.ptr4.status).to.eql('failed'); - // expect(response.body.ptr.value).to.eql(null); this will be anything random + assert.equal(typeof response.body.ptr4, 'object'); + assert.deepEqual(response.body.ptr4.expected, mailFqdn); + assert.deepEqual(response.body.ptr4.status, 'failed'); + // assert.deepEqual(response.body.ptr.value, null); this will be anything random }); it('succeeds with all different spf, dkim, dmarc, mx, ptr records', async function () { @@ -188,34 +182,34 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/status') .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.spf).to.be.an('object'); - expect(response.body.spf.expected).to.eql(`v=spf1 a:${dashboardFqdn} a:random.com ~all`); - expect(response.body.spf.status).to.eql('failed'); - expect(response.body.spf.value).to.eql('v=spf1 a:random.com ~all'); + assert.equal(typeof response.body.spf, 'object'); + assert.deepEqual(response.body.spf.expected, `v=spf1 a:${dashboardFqdn} a:random.com ~all`); + assert.deepEqual(response.body.spf.status, 'failed'); + assert.deepEqual(response.body.spf.value, 'v=spf1 a:random.com ~all'); - expect(response.body.dkim).to.be.an('object'); - expect(response.body.dkim.expected).to.eql('v=DKIM1; t=s; p=' + publicKey); - expect(response.body.dkim.status).to.eql('passed'); // as long as p= matches we are good - expect(response.body.dkim.value).to.eql('v=DKIM2; t=s; p=' + publicKey); + assert.equal(typeof response.body.dkim, 'object'); + assert.deepEqual(response.body.dkim.expected, 'v=DKIM1; t=s; p=' + publicKey); + assert.deepEqual(response.body.dkim.status, 'passed'); // as long as p= matches we are good + assert.deepEqual(response.body.dkim.value, 'v=DKIM2; t=s; p=' + publicKey); - expect(response.body.dmarc).to.be.an('object'); - expect(response.body.dmarc.expected).to.eql('v=DMARC1; p=reject; pct=100'); - expect(response.body.dmarc.status).to.eql('failed'); - expect(response.body.dmarc.value).to.eql('v=DMARC2; p=reject; pct=100'); + assert.equal(typeof response.body.dmarc, 'object'); + assert.deepEqual(response.body.dmarc.expected, 'v=DMARC1; p=reject; pct=100'); + assert.deepEqual(response.body.dmarc.status, 'failed'); + assert.deepEqual(response.body.dmarc.value, 'v=DMARC2; p=reject; pct=100'); - expect(response.body.mx).to.be.an('object'); - expect(response.body.mx.status).to.eql('passed'); - expect(response.body.mx.expected).to.eql(`10 ${mailFqdn}.`); - expect(response.body.mx.value).to.eql(`20 ${mailFqdn}. 10 some.other.server.`); + assert.equal(typeof response.body.mx, 'object'); + assert.deepEqual(response.body.mx.status, 'passed'); + assert.deepEqual(response.body.mx.expected, `10 ${mailFqdn}.`); + assert.deepEqual(response.body.mx.value, `20 ${mailFqdn}. 10 some.other.server.`); - expect(response.body.ptr4).to.be.an('object'); - expect(response.body.ptr4.expected).to.eql(mailFqdn); - expect(response.body.ptr4.status).to.eql('failed'); - // expect(response.body.ptr.value).to.eql(null); this will be anything random + assert.equal(typeof response.body.ptr4, 'object'); + assert.deepEqual(response.body.ptr4.expected, mailFqdn); + assert.deepEqual(response.body.ptr4.status, 'failed'); + // assert.deepEqual(response.body.ptr.value, null); this will be anything random - expect(response.body.relay).to.be.an('object'); + assert.equal(typeof response.body.relay, 'object'); }); it('succeeds with existing embedded spf', async function () { @@ -226,14 +220,14 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/status`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.spf).to.be.an('object'); - expect(response.body.spf.domain).to.eql(spfDomain); - expect(response.body.spf.type).to.eql('TXT'); - expect(response.body.spf.value).to.eql(`v=spf1 a:example.com a:${mailFqdn} ~all`); - expect(response.body.spf.expected).to.eql(`v=spf1 a:example.com a:${mailFqdn} ~all`); - expect(response.body.spf.status).to.eql('passed'); + assert.equal(typeof response.body.spf, 'object'); + assert.deepEqual(response.body.spf.domain, spfDomain); + assert.deepEqual(response.body.spf.type, 'TXT'); + assert.deepEqual(response.body.spf.value, `v=spf1 a:example.com a:${mailFqdn} ~all`); + assert.deepEqual(response.body.spf.expected, `v=spf1 a:example.com a:${mailFqdn} ~all`); + assert.deepEqual(response.body.spf.status, 'passed'); }); it('succeeds with modified DMARC1 values', async function () { @@ -244,12 +238,12 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/status`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.dmarc).to.be.an('object'); - expect(response.body.dmarc.expected).to.eql('v=DMARC1; p=reject; pct=100'); - expect(response.body.dmarc.status).to.eql('passed'); - expect(response.body.dmarc.value).to.eql('v=DMARC1; p=reject; rua=mailto:rua@example.com; pct=100'); + assert.equal(typeof response.body.dmarc, 'object'); + assert.deepEqual(response.body.dmarc.expected, 'v=DMARC1; p=reject; pct=100'); + assert.deepEqual(response.body.dmarc.status, 'passed'); + assert.deepEqual(response.body.dmarc.value, 'v=DMARC1; p=reject; rua=mailto:rua@example.com; pct=100'); }); it('succeeds with all correct records', async function () { @@ -263,31 +257,31 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/status') .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); - expect(response.body.dkim).to.be.an('object'); - expect(response.body.dkim.domain).to.eql(dkimDomain); - expect(response.body.dkim.type).to.eql('TXT'); - expect(response.body.dkim.value).to.eql(`v=DKIM1; t=s; p=${publicKey}`); - expect(response.body.dkim.expected).to.eql(`v=DKIM1; t=s; p=${publicKey}`); - expect(response.body.dkim.status).to.eql('passed'); + assert.equal(typeof response.body.dkim, 'object'); + assert.deepEqual(response.body.dkim.domain, dkimDomain); + assert.deepEqual(response.body.dkim.type, 'TXT'); + assert.deepEqual(response.body.dkim.value, `v=DKIM1; t=s; p=${publicKey}`); + assert.deepEqual(response.body.dkim.expected, `v=DKIM1; t=s; p=${publicKey}`); + assert.deepEqual(response.body.dkim.status, 'passed'); - expect(response.body.spf).to.be.an('object'); - expect(response.body.spf.domain).to.eql(spfDomain); - expect(response.body.spf.type).to.eql('TXT'); - expect(response.body.spf.value).to.eql(`v=spf1 a:${dashboardFqdn} ~all`); - expect(response.body.spf.expected).to.eql(`v=spf1 a:${dashboardFqdn} ~all`); - expect(response.body.spf.status).to.eql('passed'); + assert.equal(typeof response.body.spf, 'object'); + assert.deepEqual(response.body.spf.domain, spfDomain); + assert.deepEqual(response.body.spf.type, 'TXT'); + assert.deepEqual(response.body.spf.value, `v=spf1 a:${dashboardFqdn} ~all`); + assert.deepEqual(response.body.spf.expected, `v=spf1 a:${dashboardFqdn} ~all`); + assert.deepEqual(response.body.spf.status, 'passed'); - expect(response.body.dmarc).to.be.an('object'); - expect(response.body.dmarc.expected).to.eql('v=DMARC1; p=reject; pct=100'); - expect(response.body.dmarc.status).to.eql('passed'); - expect(response.body.dmarc.value).to.eql('v=DMARC1; p=reject; pct=100'); + assert.equal(typeof response.body.dmarc, 'object'); + assert.deepEqual(response.body.dmarc.expected, 'v=DMARC1; p=reject; pct=100'); + assert.deepEqual(response.body.dmarc.status, 'passed'); + assert.deepEqual(response.body.dmarc.value, 'v=DMARC1; p=reject; pct=100'); - expect(response.body.mx).to.be.an('object'); - expect(response.body.mx.status).to.eql('passed'); - expect(response.body.mx.expected).to.eql(`10 ${mailFqdn}.`); - expect(response.body.mx.value).to.eql(`10 ${mailFqdn}.`); + assert.equal(typeof response.body.mx, 'object'); + assert.deepEqual(response.body.mx.status, 'passed'); + assert.deepEqual(response.body.mx.expected, `10 ${mailFqdn}.`); + assert.deepEqual(response.body.mx.value, `10 ${mailFqdn}.`); }); }); @@ -296,8 +290,8 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.mailFromValidation).to.eql(true); + assert.equal(response.status, 200); + assert.deepEqual(response.body.mailFromValidation, true); }); it('cannot set without enabled field', async function () { @@ -306,7 +300,7 @@ describe('Mail API', function () { .send({ }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set with enabled field', async function () { @@ -314,7 +308,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .send({ enabled: false }); - expect(response.status).to.equal(202); + assert.equal(response.status, 202); }); }); @@ -322,8 +316,8 @@ describe('Mail API', function () { it('get catch_all succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.catchAll).to.eql([]); + assert.equal(response.status, 200); + assert.deepEqual(response.body.catchAll, []); }); it('cannot set without addresses field', async function () { @@ -332,7 +326,7 @@ describe('Mail API', function () { .send({ }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set with bad addresses field', async function () { @@ -341,7 +335,7 @@ describe('Mail API', function () { .send({ addresses: [ 'user1', 123 ] }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set with bad addresses field', async function () { @@ -350,7 +344,7 @@ describe('Mail API', function () { .send({ addresses: [ 'user1' ] }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -358,15 +352,15 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .send({ addresses: [ `user1@${dashboardDomain}` ] }); - expect(response.status).to.equal(202); + assert.equal(response.status, 202); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.catchAll).to.eql([ `user1@${dashboardDomain}` ]); + assert.equal(response.status, 200); + assert.deepEqual(response.body.catchAll, [ `user1@${dashboardDomain}` ]); }); }); @@ -374,8 +368,8 @@ describe('Mail API', function () { it('get mail relay succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.relay).to.eql({ provider: 'cloudron-smtp' }); + assert.equal(response.status, 200); + assert.deepEqual(response.body.relay, { provider: 'cloudron-smtp' }); }); it('cannot set without provider field', async function () { @@ -384,7 +378,7 @@ describe('Mail API', function () { .send({ }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set with bad host', async function () { @@ -393,7 +387,7 @@ describe('Mail API', function () { .send({ provider: 'external-smtp', host: true }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set fails because mail server is unreachable', async function () { @@ -402,7 +396,7 @@ describe('Mail API', function () { .send({ provider: 'external-smtp', host: 'host', port: 25, username: 'u', password: 'p', tls: true }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('get succeeds', async function () { @@ -413,8 +407,8 @@ describe('Mail API', function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(_.omit(response.body.relay, ['password'])).to.eql(_.omit(relay, ['password'])); + assert.equal(response.status, 200); + assert.deepEqual(_.omit(response.body.relay, ['password']), _.omit(relay, ['password'])); }); }); @@ -426,7 +420,7 @@ describe('Mail API', function () { .send({ name: MAILBOX_NAME, ownerId: owner.id, ownerType: 'user', active: true, enablePop3: false, storageQuota: 10, messagesQuota: 20 }) .query({ access_token: owner.token }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('cannot add again', async function () { @@ -435,7 +429,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('get fails if not exist', async function () { @@ -443,41 +437,41 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes/${MAILBOX_NAME}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.mailbox).to.be.an('object'); - expect(response.body.mailbox.name).to.equal(MAILBOX_NAME); - expect(response.body.mailbox.active).to.equal(true); - expect(response.body.mailbox.enablePop3).to.equal(false); - expect(response.body.mailbox.ownerId).to.equal(owner.id); - expect(response.body.mailbox.ownerType).to.equal('user'); - expect(response.body.mailbox.aliasName).to.equal(null); - expect(response.body.mailbox.aliasDomain).to.equal(null); - expect(response.body.mailbox.domain).to.equal(dashboardDomain); - expect(response.body.mailbox.storageQuota).to.equal(10); - expect(response.body.mailbox.messagesQuota).to.equal(20); + assert.equal(response.status, 200); + assert.equal(typeof response.body.mailbox, 'object'); + assert.equal(response.body.mailbox.name, MAILBOX_NAME); + assert.equal(response.body.mailbox.active, true); + assert.equal(response.body.mailbox.enablePop3, false); + assert.equal(response.body.mailbox.ownerId, owner.id); + assert.equal(response.body.mailbox.ownerType, 'user'); + assert.equal(response.body.mailbox.aliasName, null); + assert.equal(response.body.mailbox.aliasDomain, null); + assert.equal(response.body.mailbox.domain, dashboardDomain); + assert.equal(response.body.mailbox.storageQuota, 10); + assert.equal(response.body.mailbox.messagesQuota, 20); }); it('listing succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.mailboxes.length).to.eql(1); - expect(response.body.mailboxes[0]).to.be.an('object'); - expect(response.body.mailboxes[0].name).to.equal(MAILBOX_NAME); - expect(response.body.mailboxes[0].ownerId).to.equal(owner.id); - expect(response.body.mailboxes[0].ownerType).to.equal('user'); - expect(response.body.mailboxes[0].aliases).to.eql([]); - expect(response.body.mailboxes[0].domain).to.equal(dashboardDomain); - expect(response.body.mailboxes[0].storageQuota).to.equal(10); - expect(response.body.mailboxes[0].messagesQuota).to.equal(20); + assert.equal(response.status, 200); + assert.deepEqual(response.body.mailboxes.length, 1); + assert.equal(typeof response.body.mailboxes[0], 'object'); + assert.equal(response.body.mailboxes[0].name, MAILBOX_NAME); + assert.equal(response.body.mailboxes[0].ownerId, owner.id); + assert.equal(response.body.mailboxes[0].ownerType, 'user'); + assert.deepEqual(response.body.mailboxes[0].aliases, []); + assert.equal(response.body.mailboxes[0].domain, dashboardDomain); + assert.equal(response.body.mailboxes[0].storageQuota, 10); + assert.equal(response.body.mailboxes[0].messagesQuota, 20); }); it('disable fails even if not exist', async function () { @@ -486,7 +480,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('disable succeeds', async function () { @@ -494,12 +488,12 @@ describe('Mail API', function () { .send({ deleteMails: false }) .query({ access_token: owner.token }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); const response2 = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/mailboxes/' + MAILBOX_NAME) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(404); + assert.equal(response2.status, 404); }); }); @@ -515,7 +509,7 @@ describe('Mail API', function () { .send({ name: MAILBOX_NAME, ownerId: owner.id, ownerType: 'user', active: true, enablePop3: false, storageQuota: 10, messagesQuota: 20 }) .query({ access_token: owner.token }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('set fails if aliases is missing', async function () { @@ -523,7 +517,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set fails if user does not exist', async function () { @@ -532,7 +526,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('set fails if aliases is the wrong type', async function () { @@ -541,7 +535,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('set succeeds', async function () { @@ -549,15 +543,15 @@ describe('Mail API', function () { .send({ aliases: [{ name: 'hello*', domain: dashboardDomain}, {name: 'there', domain: dashboardDomain}] }) .query({ access_token: owner.token }); - expect(response.status).to.equal(202); + assert.equal(response.status, 202); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}` + '/mailboxes/' + MAILBOX_NAME + '/aliases') .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.aliases).to.eql([{ name: 'hello*', domain: dashboardDomain}, {name: 'there', domain: dashboardDomain}]); + assert.equal(response.status, 200); + assert.deepEqual(response.body.aliases, [{ name: 'hello*', domain: dashboardDomain}, {name: 'there', domain: dashboardDomain}]); }); it('get fails if mailbox does not exist', async function () { @@ -565,7 +559,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); }); @@ -581,7 +575,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('add fails with invalid groupId', async function () { @@ -590,7 +584,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('add fails without members array', async function () { @@ -599,7 +593,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('add succeeds', async function () { @@ -607,7 +601,7 @@ describe('Mail API', function () { .send({ name: LIST_NAME, members: [ `admin2@${dashboardDomain}`, `${owner.username}@${dashboardDomain}`], membersOnly: false, active: true }) .query({ access_token: owner.token }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('add twice fails', async function () { @@ -616,7 +610,7 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('get fails if not exist', async function (){ @@ -624,36 +618,36 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/lists/${LIST_NAME}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.list).to.be.an('object'); - expect(response.body.list.name).to.equal(LIST_NAME); - expect(response.body.list.ownerId).to.equal('admin'); - expect(response.body.list.aliasName).to.equal(null); - expect(response.body.list.domain).to.equal(dashboardDomain); - expect(response.body.list.members).to.eql([ `admin2@${dashboardDomain}`, `superadmin@${dashboardDomain}` ]); - expect(response.body.list.membersOnly).to.be(false); + assert.equal(response.status, 200); + assert.equal(typeof response.body.list, 'object'); + assert.equal(response.body.list.name, LIST_NAME); + assert.equal(response.body.list.ownerId, 'admin'); + assert.equal(response.body.list.aliasName, null); + assert.equal(response.body.list.domain, dashboardDomain); + assert.deepEqual(response.body.list.members, [ `admin2@${dashboardDomain}`, `superadmin@${dashboardDomain}` ]); + assert.equal(response.body.list.membersOnly, false); }); it('get all succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/lists`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.lists).to.be.an(Array); - expect(response.body.lists.length).to.equal(1); - expect(response.body.lists[0].name).to.equal(LIST_NAME); - expect(response.body.lists[0].ownerId).to.equal('admin'); - expect(response.body.lists[0].aliasName).to.equal(null); - expect(response.body.lists[0].domain).to.equal(dashboardDomain); - expect(response.body.lists[0].members).to.eql([ `admin2@${dashboardDomain}`, `superadmin@${dashboardDomain}` ]); - expect(response.body.lists[0].membersOnly).to.be(false); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.lists)); + assert.equal(response.body.lists.length, 1); + assert.equal(response.body.lists[0].name, LIST_NAME); + assert.equal(response.body.lists[0].ownerId, 'admin'); + assert.equal(response.body.lists[0].aliasName, null); + assert.equal(response.body.lists[0].domain, dashboardDomain); + assert.deepEqual(response.body.lists[0].members, [ `admin2@${dashboardDomain}`, `superadmin@${dashboardDomain}` ]); + assert.equal(response.body.lists[0].membersOnly, false); }); it('del fails if list does not exist', async function () { @@ -661,20 +655,20 @@ describe('Mail API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('del succeeds', async function () { const response = await superagent.del(`${serverUrl}/api/v1/mail/${dashboardDomain}/lists/${LIST_NAME}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/lists/${LIST_NAME}`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(404); + assert.equal(response2.status, 404); }); }); }); diff --git a/src/routes/test/network-test.js b/src/routes/test/network-test.js index b2fb074b0..398b93d74 100644 --- a/src/routes/test/network-test.js +++ b/src/routes/test/network-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Network API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -19,8 +16,8 @@ describe('Network API', function () { const response = await superagent.get(`${serverUrl}/api/v1/network/dynamic_dns`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.enabled).to.be(false); + assert.equal(response.status, 200); + assert.equal(response.body.enabled, false); }); it('cannot set without enabled', async function () { @@ -28,7 +25,7 @@ describe('Network API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set', async function () { @@ -37,15 +34,15 @@ describe('Network API', function () { .send({ enabled: true }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('get succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/network/dynamic_dns`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.enabled).to.be(true); + assert.equal(response.status, 200); + assert.equal(response.body.enabled, true); }); }); }); diff --git a/src/routes/test/notifications-test.js b/src/routes/test/notifications-test.js index 92d63b42d..bde03a52d 100644 --- a/src/routes/test/notifications-test.js +++ b/src/routes/test/notifications-test.js @@ -1,13 +1,10 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import notifications from '../../notifications.js'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Notifications API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -27,17 +24,17 @@ describe('Notifications API', function () { const response = await superagent.get(`${serverUrl}/api/v1/notifications/random`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can get notification by id', async function () { const response = await superagent.get(`${serverUrl}/api/v1/notifications/${notificationIds[0]}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.id).to.be(notificationIds[0]); - expect(response.body.title).to.be('title 0'); - expect(response.body.message).to.be('message 0'); - expect(response.body.acknowledged).to.be(false); + assert.equal(response.status, 200); + assert.equal(response.body.id, notificationIds[0]); + assert.equal(response.body.title, 'title 0'); + assert.equal(response.body.message, 'message 0'); + assert.equal(response.body.acknowledged, false); }); it('can ack notification', async function () { @@ -45,10 +42,10 @@ describe('Notifications API', function () { .query({ access_token: owner.token }) .send({ acknowledged: true }) .ok(() => true); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const result = await notifications.get(notificationIds[0]); - expect(result.acknowledged).to.be(true); + assert.equal(result.acknowledged, true); }); it('can ack non-existent notification', async function () { @@ -56,22 +53,22 @@ describe('Notifications API', function () { .query({ access_token: owner.token }) .send({ acknowledged: true }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can list unread notifications', async function () { const response = await superagent.get(`${serverUrl}/api/v1/notifications`) // ?acknowledged=false is default .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.notifications.length).to.be.greaterThan(2); + assert.equal(response.status, 200); + assert.ok((response.body.notifications.length) > (2)); }); it('can list read notifications', async function () { const response = await superagent.get(`${serverUrl}/api/v1/notifications?acknowledged=true`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.notifications.length).to.be(1); - expect(response.body.notifications[0].id).to.be(notificationIds[0]); - expect(response.body.notifications[0].title).to.be('title 0'); + assert.equal(response.status, 200); + assert.equal(response.body.notifications.length, 1); + assert.equal(response.body.notifications[0].id, notificationIds[0]); + assert.equal(response.body.notifications[0].title, 'title 0'); }); }); diff --git a/src/routes/test/oidcclients-test.js b/src/routes/test/oidcclients-test.js index efc987724..468581664 100644 --- a/src/routes/test/oidcclients-test.js +++ b/src/routes/test/oidcclients-test.js @@ -1,13 +1,10 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ const CLIENT_0 = { id: 'client0', @@ -36,7 +33,7 @@ describe('OpenID connect clients API', function () { .send(CLIENT_0) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('create succeeds', async function () { @@ -44,7 +41,7 @@ describe('OpenID connect clients API', function () { .query({ access_token: owner.token }) .send(CLIENT_0); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); CLIENT_0.id = response.body.id; CLIENT_0.secret = response.body.secret; }); @@ -54,7 +51,7 @@ describe('OpenID connect clients API', function () { .query({ access_token: owner.token }) .send(CLIENT_1); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); CLIENT_1.id = response.body.id; CLIENT_1.secret = response.body.secret; }); @@ -64,7 +61,7 @@ describe('OpenID connect clients API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot get existing client with normal user', async function () { @@ -72,18 +69,18 @@ describe('OpenID connect clients API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can get existing client', async function () { const response = await superagent.get(`${serverUrl}/api/v1/oidc/clients/${CLIENT_1.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.id).to.equal(CLIENT_1.id); - expect(response.body.secret).to.equal(CLIENT_1.secret); - expect(response.body.loginRedirectUri).to.equal(CLIENT_1.loginRedirectUri); - expect(response.body.tokenSignatureAlgorithm).to.equal(CLIENT_1.tokenSignatureAlgorithm); + assert.equal(response.status, 200); + assert.equal(response.body.id, CLIENT_1.id); + assert.equal(response.body.secret, CLIENT_1.secret); + assert.equal(response.body.loginRedirectUri, CLIENT_1.loginRedirectUri); + assert.equal(response.body.tokenSignatureAlgorithm, CLIENT_1.tokenSignatureAlgorithm); }); it('cannot update non-existent client', async function () { @@ -92,14 +89,14 @@ describe('OpenID connect clients API', function () { .send(CLIENT_0) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('cannot list clients without token', async function () { const response = await superagent.get(`${serverUrl}/api/v1/oidc/clients`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('cannot list clients as normal user', async function () { @@ -107,18 +104,18 @@ describe('OpenID connect clients API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can list clients', async function () { const response = await superagent.get(`${serverUrl}/api/v1/oidc/clients`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.clients).to.be.an(Array); - expect(response.body.clients.length).to.be(2); - expect(response.body.clients[0].id).to.eql(CLIENT_0.id); - expect(response.body.clients[1].id).to.eql(CLIENT_1.id); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.clients)); + assert.equal(response.body.clients.length, 2); + assert.deepEqual(response.body.clients[0].id, CLIENT_0.id); + assert.deepEqual(response.body.clients[1].id, CLIENT_1.id); }); it('cann update client', async function () { @@ -127,7 +124,7 @@ describe('OpenID connect clients API', function () { .send({ loginRedirectUri: CLIENT_0.loginRedirectUri }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot update client without loginRedirectUri', async function () { @@ -136,20 +133,20 @@ describe('OpenID connect clients API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot remove without token', async function () { const response = await superagent.del(`${serverUrl}/api/v1/oidc/clients/${CLIENT_0.id}`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can remove empty group', async function () { const response = await superagent.del(`${serverUrl}/api/v1/oidc/clients/${CLIENT_0.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); diff --git a/src/routes/test/profile-test.js b/src/routes/test/profile-test.js index 65d8aa3e7..cd6c79959 100644 --- a/src/routes/test/profile-test.js +++ b/src/routes/test/profile-test.js @@ -1,7 +1,8 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import passkeys from '../../passkeys.js'; import speakeasy from 'speakeasy'; @@ -11,10 +12,6 @@ import webauthnHelper from '../../test/webauthn-helper.js'; const customAvatarSize = fs.readFileSync('./logo.png').length; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Profile API', function () { const { setup, cleanup, serverUrl, owner, user } = common; @@ -27,7 +24,7 @@ describe('Profile API', function () { const response = await superagent.get(`${serverUrl}/api/v1/profile`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails with empty token', async function () { @@ -35,7 +32,7 @@ describe('Profile API', function () { .query({ access_token: '' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails with invalid token', async function () { @@ -43,32 +40,32 @@ describe('Profile API', function () { .query({ access_token: 'some token' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('succeeds', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.username).to.equal(owner.username.toLowerCase()); - expect(response.body.email).to.equal(owner.email.toLowerCase()); - expect(response.body.fallbackEmail).to.equal(''); - expect(response.body.displayName).to.be.a('string'); - expect(response.body.password).to.not.be.ok(); - expect(response.body.salt).to.not.be.ok(); - expect(response.body.language).to.be(null); + assert.equal(response.status, 200); + assert.equal(response.body.username, owner.username.toLowerCase()); + assert.equal(response.body.email, owner.email.toLowerCase()); + assert.equal(response.body.fallbackEmail, ''); + assert.equal(typeof response.body.displayName, 'string'); + assert.ok(!(response.body.password)); + assert.ok(!(response.body.salt)); + assert.equal(response.body.language, null); }); it('fails with expired token', async function () { const token = await tokens.add({ identifier: '0', clientId: 'clientid-0', expires: Date.now() - 2000, allowedIpRanges: '' }); - expect(token.accessToken).to.be.a('string'); + assert.equal(typeof token.accessToken, 'string'); const response = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: token.accessToken }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails with invalid token in auth header', async function () { @@ -76,18 +73,18 @@ describe('Profile API', function () { .set('Authorization', 'Bearer ' + 'x' + owner.token) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('succeeds with token in auth header', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile`).set('Authorization', 'Bearer ' + owner.token); - expect(response.status).to.equal(200); - expect(response.body.username).to.equal(owner.username.toLowerCase()); - expect(response.body.email).to.equal(owner.email.toLowerCase()); - expect(response.body.displayName).to.be.a('string'); - expect(response.body.password).to.not.be.ok(); - expect(response.body.salt).to.not.be.ok(); + assert.equal(response.status, 200); + assert.equal(response.body.username, owner.username.toLowerCase()); + assert.equal(response.body.email, owner.email.toLowerCase()); + assert.equal(typeof response.body.displayName, 'string'); + assert.ok(!(response.body.password)); + assert.ok(!(response.body.salt)); }); }); @@ -97,7 +94,7 @@ describe('Profile API', function () { .send({ email: 'newemail@example.com' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('change email fails due to missing password', async function () { @@ -106,7 +103,7 @@ describe('Profile API', function () { .send({ email: 'newemail@example.com' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change email fails due to invalid password', async function () { @@ -115,7 +112,7 @@ describe('Profile API', function () { .send({ email: 'foo@bar.com', password: 'this is wrong' }) .ok(() => true); - expect(response.status).to.equal(412); + assert.equal(response.status, 412); }); it('change email fails due to invalid email', async function () { @@ -124,7 +121,7 @@ describe('Profile API', function () { .send({ email: 'foo@bar' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change email succeeds', async function () { @@ -132,15 +129,15 @@ describe('Profile API', function () { .query({ access_token: owner.token }) .send({ email: 'newemail@example.Com', password: owner.password }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.username).to.equal(owner.username); - expect(response2.body.email).to.equal('newemail@example.com'); // lower cased - expect(response2.body.displayName).to.equal(''); + assert.equal(response2.status, 200); + assert.equal(response2.body.username, owner.username); + assert.equal(response2.body.email, 'newemail@example.com'); // lower cased + assert.equal(response2.body.displayName, ''); }); }); @@ -151,7 +148,7 @@ describe('Profile API', function () { .send({ fallbackEmail: 'newemail@example.com' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change fallback email fails due to invalid password', async function () { @@ -160,7 +157,7 @@ describe('Profile API', function () { .send({ fallbackEmail: 'foo@bar.com', password: 'this is wrong' }) .ok(() => true); - expect(response.status).to.equal(412); + assert.equal(response.status, 412); }); it('change fallback email succeeds', async function () { @@ -168,14 +165,14 @@ describe('Profile API', function () { .query({ access_token: owner.token }) .send({ fallbackEmail: 'NewFallbackemail@example.com', password: owner.password }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.username).to.equal(owner.username); - expect(response2.body.fallbackEmail).to.equal('newfallbackemail@example.com'); // lowercase + assert.equal(response2.status, 200); + assert.equal(response2.body.username, owner.username); + assert.equal(response2.body.fallbackEmail, 'newfallbackemail@example.com'); // lowercase }); }); @@ -185,14 +182,14 @@ describe('Profile API', function () { .query({ access_token: owner.token }) .send({ displayName: 'Agent Smith' }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.username).to.equal(owner.username); - expect(response2.body.email).to.equal('newemail@example.com'); // lower cased - expect(response2.body.displayName).to.equal('Agent Smith'); + assert.equal(response2.status, 200); + assert.equal(response2.body.username, owner.username); + assert.equal(response2.body.email, 'newemail@example.com'); // lower cased + assert.equal(response2.body.displayName, 'Agent Smith'); }); }); @@ -203,7 +200,7 @@ describe('Profile API', function () { .send({ newPassword: 'some wrong password' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails due to missing new password', async function () { @@ -212,7 +209,7 @@ describe('Profile API', function () { .send({ password: owner.password }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('fails due to wrong password', async function () { @@ -221,7 +218,7 @@ describe('Profile API', function () { .send({ password: 'some wrong password', newPassword: 'MOre#$%34' }) .ok(() => true); - expect(response.status).to.equal(412); + assert.equal(response.status, 412); }); it('fails due to invalid password', async function () { @@ -230,7 +227,7 @@ describe('Profile API', function () { .send({ password: owner.password, newPassword: 'five' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('succeeds', async function () { @@ -238,7 +235,7 @@ describe('Profile API', function () { .query({ access_token: owner.token }) .send({ password: owner.password, newPassword: 'MOre#$%34' }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); @@ -266,7 +263,7 @@ describe('Profile API', function () { .send({ username: user.username, password: user.password }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('fails due to wrong token', async function () { @@ -274,7 +271,7 @@ describe('Profile API', function () { .send({ username: user.username, password: user.password, totpToken: '12345' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('succeeds', async function () { @@ -286,9 +283,9 @@ describe('Profile API', function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: user.username, password: user.password, totpToken: totpToken }); - expect(response.status).to.equal(200); - expect(response.body).to.be.an(Object); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.ok((response.body) && typeof (response.body) === 'object' && !Array.isArray(response.body)); + assert.equal(typeof response.body.accessToken, 'string'); }); it('can disable 2fa', async function () { @@ -301,9 +298,9 @@ describe('Profile API', function () { const response = await superagent.post(`${serverUrl}/api/v1/auth/login`) .send({ username: user.username, password: user.password }); - expect(response.status).to.equal(200); - expect(response.body).to.be.an(Object); - expect(response.body.accessToken).to.be.a('string'); + assert.equal(response.status, 200); + assert.ok((response.body) && typeof (response.body) === 'object' && !Array.isArray(response.body)); + assert.equal(typeof response.body.accessToken, 'string'); }); }); @@ -320,8 +317,8 @@ describe('Profile API', function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.passkey).to.be(null); + assert.equal(response.status, 200); + assert.equal(response.body.passkey, null); }); it('fails to get registration options without token', async function () { @@ -329,7 +326,7 @@ describe('Profile API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('can get registration options', async function () { @@ -337,9 +334,9 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({}); - expect(response.status).to.equal(200); - expect(response.body.challenge).to.be.a('string'); - expect(response.body.rp).to.be.an(Object); + assert.equal(response.status, 200); + assert.equal(typeof response.body.challenge, 'string'); + assert.ok((response.body.rp) && typeof (response.body.rp) === 'object' && !Array.isArray(response.body.rp)); }); it('can register passkey', async function () { @@ -355,18 +352,18 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({ credential, name: 'Test Passkey' }); - expect(response.status).to.equal(201); - expect(response.body.id).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.id, 'string'); }); it('passkey is visible', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.passkey).to.be.an(Object); - expect(response.body.passkey.name).to.be('Test Passkey'); - expect(response.body.passkey.credentialId).to.be(undefined); // private field stripped + assert.equal(response.status, 200); + assert.ok((response.body.passkey) && typeof (response.body.passkey) === 'object' && !Array.isArray(response.body.passkey)); + assert.equal(response.body.passkey.name, 'Test Passkey'); + assert.equal(response.body.passkey.credentialId, undefined); // private field stripped }); it('rejects duplicate registration', async function () { @@ -375,7 +372,7 @@ describe('Profile API', function () { .send({}) .ok(() => true); - expect(optionsResponse.status).to.equal(409); + assert.equal(optionsResponse.status, 409); }); it('fails to register without credential', async function () { @@ -383,14 +380,14 @@ describe('Profile API', function () { const optionsResponse = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register/options`) .query({ access_token: owner.token }) .send({}); - expect(optionsResponse.status).to.equal(200); + assert.equal(optionsResponse.status, 200); const response = await superagent.post(`${serverUrl}/api/v1/profile/passkey/register`) .query({ access_token: owner.token }) .send({}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can disable passkey', async function () { @@ -398,15 +395,15 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({ password: user.password }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('passkey is gone after disable', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/passkey`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.passkey).to.be(null); + assert.equal(response.status, 200); + assert.equal(response.body.passkey, null); }); it('disable fails when no passkey registered', async function () { @@ -415,7 +412,7 @@ describe('Profile API', function () { .send({ password: user.password }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); }); @@ -424,7 +421,7 @@ describe('Profile API', function () { it('empty by default', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`).ok(() => true); - expect(response.status).to.be(404); + assert.equal(response.status, 404); }); it('can set custom avatar', async function () { @@ -434,27 +431,27 @@ describe('Profile API', function () { avatarSize = fs.readFileSync('./logo.png').length; - expect(response.status).to.be(204); + assert.equal(response.status, 204); }); it('did set custom avatar', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`) .ok(() => true); - expect(parseInt(response.headers['content-length'])).to.equal(avatarSize); - expect(response.status).to.equal(200); + assert.equal(parseInt(response.headers['content-length']), avatarSize); + assert.equal(response.status, 200); }); it('can unset custom avatar', async function () { const response = await superagent.del(`${serverUrl}/api/v1/profile/avatar`) .query({ access_token: user.token }); - expect(response.status).to.be(204); + assert.equal(response.status, 204); }); it('did unset custom avatar', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`).ok(() => true); - expect(response.status).to.be(404); + assert.equal(response.status, 404); }); }); @@ -463,7 +460,7 @@ describe('Profile API', function () { const response = await superagent.get(`${serverUrl}/api/v1/profile/background_image`) .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.be(404); + assert.equal(response.status, 404); }); it('can set custom background', async function () { @@ -471,7 +468,7 @@ describe('Profile API', function () { .query({ access_token: user.token }) .attach('backgroundImage', './logo.png'); - expect(response.status).to.be(200); + assert.equal(response.status, 200); }); it('did set custom background', async function () { @@ -479,20 +476,20 @@ describe('Profile API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(parseInt(response2.headers['content-length'])).to.equal(customAvatarSize); - expect(response2.status).to.equal(200); + assert.equal(parseInt(response2.headers['content-length']), customAvatarSize); + assert.equal(response2.status, 200); }); it('can unset background', async function () { const response = await superagent.del(`${serverUrl}/api/v1/profile/background_image`) .query({ access_token: user.token }); - expect(response.status).to.be(200); + assert.equal(response.status, 200); const response2 = await superagent.get(`${serverUrl}/api/v1/profile/background_image`) .query({ access_token: user.token }) .ok(() => true); - expect(response2.status).to.be(404); + assert.equal(response2.status, 404); }); }); @@ -502,7 +499,7 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({ language: 'ta' }) .ok(() => true); - expect(response.status).to.be(400); + assert.equal(response.status, 400); }); it('fails to set bad language', async function () { @@ -510,7 +507,7 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({ language: 123 }) .ok(() => true); - expect(response.status).to.be(400); + assert.equal(response.status, 400); }); it('fails to set unknown language', async function () { @@ -518,31 +515,31 @@ describe('Profile API', function () { .query({ access_token: user.token }) .send({ language: 'ta' }) .ok(() => true); - expect(response.status).to.be(400); + assert.equal(response.status, 400); }); it('set valid language', async function () { const response = await superagent.post(`${serverUrl}/api/v1/profile/language`) .query({ access_token: user.token }) .send({ language: 'en' }); - expect(response.status).to.be(204); + assert.equal(response.status, 204); }); it('did set language', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile`).query({ access_token: user.token }); - expect(response.body.language).to.contain('en'); + assert.ok(response.body.language.includes('en')); }); it('reset valid language', async function () { const response = await superagent.post(`${serverUrl}/api/v1/profile/language`) .query({ access_token: user.token }) .send({ language: '' }); - expect(response.status).to.be(204); + assert.equal(response.status, 204); }); it('did reset language', async function () { const response = await superagent.get(`${serverUrl}/api/v1/profile`).query({ access_token: user.token }); - expect(response.body.language).to.be(null); + assert.equal(response.body.language, null); }); }); }); diff --git a/src/routes/test/provision-test.js b/src/routes/test/provision-test.js index fdb101359..905754ff7 100644 --- a/src/routes/test/provision-test.js +++ b/src/routes/test/provision-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import appstore from '../../appstore.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import superagent from '@cloudron/superagent'; import timers from 'timers/promises'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ const DOMAIN = 'example-server-test.com'; @@ -39,7 +36,7 @@ describe('Provision', function () { .send({ domainConfig: { domain: DOMAIN, config: {} } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid provider', async function () { @@ -47,7 +44,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'foobar', domain: DOMAIN, config: {} } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with missing domain', async function () { @@ -55,7 +52,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', config: {} } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid domain', async function () { @@ -63,7 +60,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: '.foo', config: {} } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid config', async function () { @@ -71,7 +68,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, config: 'not an object' } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid zoneName', async function () { @@ -79,7 +76,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, config: {}, zoneName: 1337 } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid tlsConfig', async function () { @@ -87,7 +84,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, config: {}, tlsConfig: 'foobar' } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid tlsConfig provider', async function () { @@ -95,7 +92,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, config: {}, tlsConfig: { provider: 1337 } } }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('succeeds', async function () { @@ -103,7 +100,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, adminFqdn: 'my.' + DOMAIN, config: {}, tlsConfig: { provider: 'fallback' } } }) .ok(() => true); - expect(response.status).to.eql(200); + assert.deepEqual(response.status, 200); await waitForSetup(); }); @@ -113,7 +110,7 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, adminFqdn: 'my.' + DOMAIN, config: {}, tlsConfig: { provider: 'fallback' } } }) .ok(() => true); - expect(response.status).to.eql(200); + assert.deepEqual(response.status, 200); await waitForSetup(); }); @@ -150,10 +147,10 @@ describe('Provision', function () { it('device is in first time mode', async function () { const response = await superagent.get(`${serverUrl}/api/v1/provision/status`); - expect(response.status).to.equal(200); - expect(response.body.activated).to.not.be.ok(); - expect(response.body.version).to.be.ok(); - expect(response.body.adminFqdn).to.be.ok(); // dashboard is setup at this point + assert.equal(response.status, 200); + assert.ok(!(response.body.activated)); + assert.ok(response.body.version); + assert.ok(response.body.adminFqdn); // dashboard is setup at this point }); it('fails without username', async function () { @@ -161,7 +158,7 @@ describe('Provision', function () { .send({ password: owner.password, email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid username', async function () { @@ -169,7 +166,7 @@ describe('Provision', function () { .send({ username: '?this.is-not!valid', password: owner.password, email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails due to empty username', async function () { @@ -177,7 +174,7 @@ describe('Provision', function () { .send({ username: '', password: owner.password, email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails without email', async function () { @@ -185,7 +182,7 @@ describe('Provision', function () { .send({ username: owner.username, password: owner.password }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails due to empty email', async function () { @@ -193,7 +190,7 @@ describe('Provision', function () { .send({ username: owner.username, password: owner.password, email: '' }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails due to invalid email', async function () { @@ -201,7 +198,7 @@ describe('Provision', function () { .send({ username: owner.username, password: owner.password, email: 'invalidemail' }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails without password', async function () { @@ -209,7 +206,7 @@ describe('Provision', function () { .send({ username: owner.password.username, email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails due to empty password', async function () { @@ -217,7 +214,7 @@ describe('Provision', function () { .send({ username: owner.username, password: '', email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails with invalid password', async function () { @@ -225,7 +222,7 @@ describe('Provision', function () { .send({ username: owner.username, password: 'short', email: owner.email }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('fails due to wrong displayName type', async function () { @@ -233,15 +230,15 @@ describe('Provision', function () { .send({ username: owner.username, password: owner.password, email: owner.email, displayName: 1234 }) .ok(() => true); - expect(response.status).to.eql(400); + assert.deepEqual(response.status, 400); }); it('succeeds', async function () { const response = await superagent.post(`${serverUrl}/api/v1/provision/activate`) .send({ username: owner.username, password: owner.password, email: owner.email, displayName: owner.displayName }); - expect(response.status).to.equal(201); - expect(response.body.token).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.token, 'string'); }); it('activate fails the second time', async function () { @@ -249,7 +246,7 @@ describe('Provision', function () { .send({ username: owner.username, password: owner.password, email: owner.email, displayName: owner.displayName }) .ok(() => true); - expect(response.status).to.eql(405); // route unavailable post activation + assert.deepEqual(response.status, 405); // route unavailable post activation }); it('setup fails after activation', async function () { @@ -257,13 +254,13 @@ describe('Provision', function () { .send({ domainConfig: { provider: 'noop', domain: DOMAIN, adminFqdn: 'my.' + DOMAIN, config: {}, tlsConfig: { provider: 'fallback' } } }) .ok(() => true); - expect(response.status).to.eql(405); + assert.deepEqual(response.status, 405); }); it('device left first time mode', async function () { const response = await superagent.get(`${serverUrl}/api/v1/provision/status`); - expect(response.status).to.equal(200); - expect(response.body.activated).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(response.body.activated); }); }); }); diff --git a/src/routes/test/system-test.js b/src/routes/test/system-test.js index c5f007660..fa1b6ca4f 100644 --- a/src/routes/test/system-test.js +++ b/src/routes/test/system-test.js @@ -1,9 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import constants from '../../constants.js'; import common from './common.js'; import { EventSource } from 'eventsource'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import http from 'node:http'; import nock from 'nock'; @@ -12,9 +12,6 @@ import paths from '../../paths.js'; import safe from 'safetydance'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('System', function () { const { setup, cleanup, serverUrl, owner, user, waitForAsyncTask } = common; @@ -32,10 +29,10 @@ describe('System', function () { const response = await superagent.get(`${serverUrl}/api/v1/system/cpus`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.cpus).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(response.body.cpus); - expect(response.body.cpus.every(c => typeof c.model === 'string')).to.be(true); + assert.equal(response.body.cpus.every(c => typeof c.model === 'string'), true); }); }); @@ -44,14 +41,14 @@ describe('System', function () { const response = await superagent.get(`${serverUrl}/api/v1/system/info`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.info).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(response.body.info); - expect(response.body.info.sysVendor).to.be.a('string'); - expect(response.body.info.productName).to.be.a('string'); - expect(response.body.info.uptimeSecs).to.be.a('number'); - expect(response.body.info.rebootRequired).to.be.a('boolean'); - expect(response.body.info.activationTime).to.be.a('string'); + assert.equal(typeof response.body.info.sysVendor, 'string'); + assert.equal(typeof response.body.info.productName, 'string'); + assert.equal(typeof response.body.info.uptimeSecs, 'number'); + assert.equal(typeof response.body.info.rebootRequired, 'boolean'); + assert.equal(typeof response.body.info.activationTime, 'string'); }); }); @@ -66,10 +63,10 @@ describe('System', function () { .query({ access_token: owner.token, fromLine: 0 }) .ok(() => true); - expect(response.status).to.be(400); + assert.equal(response.status, 400); }); - it('logStream - stream logs', function (done) { + it('logStream - stream logs', async function () { const options = { host: 'localhost', port: constants.PORT, @@ -78,32 +75,33 @@ describe('System', function () { }; // superagent doesn't work. maybe https://github.com/visionmedia/superagent/issues/420 - const req = http.get(options, function (res) { - let data = ''; - res.on('data', function (d) { data += d.toString('utf8'); }); - setTimeout(function checkData() { - let dataMessageFound = false; + const data = await new Promise((resolve, reject) => { + const req = http.get(options, function (res) { + let collected = ''; + res.on('data', function (d) { collected += d.toString('utf8'); }); + res.on('error', reject); + setTimeout(function checkData() { + res.destroy(); + req.destroy(); + resolve(collected); + }, 1000); + }); - expect(data.length).to.not.be(0); - data.split('\n').forEach(function (line) { - if (line.indexOf('id: ') === 0) { - expect(parseInt(line.substr('id: '.length), 10)).to.be.a('number'); - } else if (line.indexOf('data: ') === 0) { - const message = JSON.parse(line.slice('data: '.length)).message; - if (Array.isArray(message) || typeof message === 'string') dataMessageFound = true; - } - }); - - expect(dataMessageFound).to.be.ok(); - - res.destroy(); - req.destroy(); - done(); - }, 1000); - res.on('error', done); + req.on('error', reject); }); - req.on('error', done); + let dataMessageFound = false; + assert.notEqual(data.length, 0); + data.split('\n').forEach(function (line) { + if (line.indexOf('id: ') === 0) { + assert.equal(typeof parseInt(line.substr('id: '.length), 10), 'number'); + } else if (line.indexOf('data: ') === 0) { + const message = JSON.parse(line.slice('data: '.length)).message; + if (Array.isArray(message) || typeof message === 'string') dataMessageFound = true; + } + }); + + assert.ok(dataMessageFound); }); }); @@ -112,25 +110,25 @@ describe('System', function () { const response = await superagent.get(`${serverUrl}/api/v1/system/memory`) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('succeeds (admin)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/system/memory`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.memory).to.eql(os.totalmem()); - expect(response.body.swap).to.be.a('number'); + assert.equal(response.status, 200); + assert.deepEqual(response.body.memory, os.totalmem()); + assert.equal(typeof response.body.swap, 'number'); }); it('succeeds (admin)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/system/memory`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.memory).to.eql(os.totalmem()); - expect(response.body.swap).to.be.a('number'); + assert.equal(response.status, 200); + assert.deepEqual(response.body.memory, os.totalmem()); + assert.equal(typeof response.body.swap, 'number'); }); }); @@ -141,24 +139,24 @@ describe('System', function () { const response = await superagent.get(`${serverUrl}/api/v1/system/filesystems`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); rootFs = Object.values(response.body.filesystems).find(v => v.mountpoint === '/'); - expect(rootFs.filesystem).to.be.ok(); + assert.ok(rootFs.filesystem); }); it('fails without query param', async function () { const es = new EventSource(`${serverUrl}/api/v1/system/filesystem_usage?access_token=${owner.token}`); const [error] = await safe(waitForAsyncTask(es)); - expect(error.code).to.be(400); + assert.equal(error.code, 400); }); it('succceeds with query param', async function () { const es = new EventSource(`${serverUrl}/api/v1/system/filesystem_usage?access_token=${owner.token}&filesystem=${rootFs.filesystem}`); const messages = await waitForAsyncTask(es); - expect(messages.find(m => m.type === 'progress')).to.be.ok(); - expect(messages.find(m => m.type === 'data')).to.be.ok(); - expect(messages.find(m => m.type === 'done')).to.be.ok(); + assert.ok(messages.find(m => m.type === 'progress')); + assert.ok(messages.find(m => m.type === 'data')); + assert.ok(messages.find(m => m.type === 'done')); }); }); @@ -167,10 +165,10 @@ describe('System', function () { const response = await superagent.get(`${serverUrl}/api/v1/system/block_devices`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.devices).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(response.body.devices); - expect(response.body.devices.some(d => d.mountpoints.includes('/'))).to.be(true); + assert.equal(response.body.devices.some(d => d.mountpoints.includes('/')), true); }); }); }); diff --git a/src/routes/test/tasks-test.js b/src/routes/test/tasks-test.js index 784be485f..93d37bbf0 100644 --- a/src/routes/test/tasks-test.js +++ b/src/routes/test/tasks-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import superagent from '@cloudron/superagent'; import tasks from '../../tasks.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Tasks API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -24,13 +21,13 @@ describe('Tasks API', function () { const response = await superagent.get(`${serverUrl}/api/v1/tasks/${taskId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.percent).to.be(100); - expect(response.body.args).to.be(undefined); - expect(response.body.active).to.be(false); // finished - expect(response.body.success).to.be(true); - expect(response.body.result).to.be('ping'); - expect(response.body.error).to.be(null); + assert.equal(response.status, 200); + assert.equal(response.body.percent, 100); + assert.equal(response.body.args, undefined); + assert.equal(response.body.active, false); // finished + assert.equal(response.body.success, true); + assert.equal(response.body.result, 'ping'); + assert.equal(response.body.error, null); }); it('can get logs', async function () { @@ -64,19 +61,19 @@ describe('Tasks API', function () { .send({}) .ok(() => true); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }, 100); await safe(tasks.startTask(taskId, {})); const response = await superagent.get(`${serverUrl}/api/v1/tasks/${taskId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.percent).to.not.be(100); - expect(response.body.active).to.be(false); // finished - expect(response.body.success).to.be(false); - expect(response.body.result).to.be(null); - expect(response.body.error.message).to.contain('stopped'); + assert.equal(response.status, 200); + assert.notEqual(response.body.percent, 100); + assert.equal(response.body.active, false); // finished + assert.equal(response.body.success, false); + assert.equal(response.body.result, null); + assert.ok(response.body.error.message.includes('stopped')); }); it('can list tasks', async function () { @@ -86,14 +83,14 @@ describe('Tasks API', function () { const response = await superagent.get(`${serverUrl}/api/v1/tasks?type=${tasks._TASK_IDENTITY}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.tasks.length >= 1).to.be(true); - expect(response.body.tasks[0].id).to.be(taskId); - expect(response.body.tasks[0].percent).to.be(100); - expect(response.body.tasks[0].args).to.be(undefined); - expect(response.body.tasks[0].active).to.be(false); // finished - expect(response.body.tasks[0].success).to.be(true); // finished - expect(response.body.tasks[0].result).to.be('ping'); - expect(response.body.tasks[0].error).to.be(null); + assert.equal(response.status, 200); + assert.equal(response.body.tasks.length >= 1, true); + assert.equal(response.body.tasks[0].id, taskId); + assert.equal(response.body.tasks[0].percent, 100); + assert.equal(response.body.tasks[0].args, undefined); + assert.equal(response.body.tasks[0].active, false); // finished + assert.equal(response.body.tasks[0].success, true); // finished + assert.equal(response.body.tasks[0].result, 'ping'); + assert.equal(response.body.tasks[0].error, null); }); }); diff --git a/src/routes/test/tokens-test.js b/src/routes/test/tokens-test.js index 5ea5c6967..01732d12a 100644 --- a/src/routes/test/tokens-test.js +++ b/src/routes/test/tokens-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Tokens API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -22,7 +19,7 @@ describe('Tokens API', function () { .query({ access_token: owner.token }) .send({ name: new Array(128).fill('s').join('') }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can create token', async function () { @@ -30,8 +27,8 @@ describe('Tokens API', function () { .query({ access_token: owner.token }) .send({ name: 'mytoken1' }); - expect(response.status).to.equal(201); - expect(response.body).to.be.a('object'); + assert.equal(response.status, 201); + assert.equal(typeof response.body, 'object'); token = response.body; }); @@ -40,8 +37,8 @@ describe('Tokens API', function () { .query({ access_token: owner.token }) .send({ name: 'mytoken1', scope: { '*': 'r' }}); - expect(response.status).to.equal(201); - expect(response.body).to.be.a('object'); + assert.equal(response.status, 201); + assert.equal(typeof response.body, 'object'); readOnlyToken = response.body; }); @@ -51,30 +48,30 @@ describe('Tokens API', function () { .send({ name: 'mytoken1', scope: { 'foobar': 'rw' }}) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can list tokens', async function () { const response = await superagent.get(`${serverUrl}/api/v1/tokens`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.tokens.length).to.be(3); // one is owner token on activation + assert.equal(response.status, 200); + assert.equal(response.body.tokens.length, 3); // one is owner token on activation const tokenIds = response.body.tokens.map(t => t.id); - expect(tokenIds).to.contain(token.id); - expect(tokenIds).to.contain(readOnlyToken.id); + assert.ok(tokenIds.includes(token.id)); + assert.ok(tokenIds.includes(readOnlyToken.id)); }); it('can get token', async function () { const response = await superagent.get(`${serverUrl}/api/v1/tokens/${token.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.id).to.be(token.id); + assert.equal(response.status, 200); + assert.equal(response.body.id, token.id); }); it('can delete token', async function () { const response = await superagent.del(`${serverUrl}/api/v1/tokens/${token.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); @@ -87,7 +84,7 @@ describe('Tokens API', function () { .send({ name: 'mytoken1', allowedIpRanges: 'What' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can create token with valid range', async function () { @@ -95,7 +92,7 @@ describe('Tokens API', function () { .query({ access_token: owner.token }) .send({ name: 'mytoken1', allowedIpRanges: '#this is localhost\n10.0.0.0/8' }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); allowedRangeToken = response.body; }); @@ -103,7 +100,7 @@ describe('Tokens API', function () { const response = await superagent.get(`${serverUrl}/api/v1/tokens`) .query({ access_token: allowedRangeToken.accessToken }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); }); @@ -114,7 +111,7 @@ describe('Tokens API', function () { .send({ name: 'somename' }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can use read only token to list domains', async function () { @@ -122,8 +119,8 @@ describe('Tokens API', function () { .query({ access_token: readOnlyToken.accessToken }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.domains.length).to.be(1); + assert.equal(response.status, 200); + assert.equal(response.body.domains.length, 1); }); it('cannot use read only token for creating a domain', async function () { @@ -142,14 +139,14 @@ describe('Tokens API', function () { .send(DOMAIN_0) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('cannot get non-existent token', async function () { const response = await superagent.get(`${serverUrl}/api/v1/tokens/foobar`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); }); }); diff --git a/src/routes/test/updater-test.js b/src/routes/test/updater-test.js index ebea5e8fc..26a417cf0 100644 --- a/src/routes/test/updater-test.js +++ b/src/routes/test/updater-test.js @@ -1,13 +1,10 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import constants from '../../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Updater API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -19,43 +16,43 @@ describe('Updater API', function () { it('can get app auto update pattern (default)', async function () { const response = await superagent.get(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.pattern).to.be.ok(); + assert.equal(response.status, 200); + assert.ok(response.body.pattern); }); it('cannot set autoupdate_pattern without pattern', async function () { const response = await superagent.post(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can set autoupdate_pattern', async function () { const response = await superagent.post(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }) .send({ pattern: '00 30 11 * * 1-5' }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('can get auto update pattern', async function () { const response = await superagent.get(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.pattern).to.be('00 30 11 * * 1-5'); + assert.equal(response.status, 200); + assert.equal(response.body.pattern, '00 30 11 * * 1-5'); }); it('can set autoupdate_pattern to never', async function () { const response = await superagent.post(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }) .send({ pattern: constants.CRON_PATTERN_NEVER }); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('can get auto update pattern', async function () { const response = await superagent.get(`${serverUrl}/api/v1/updater/autoupdate_pattern`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.pattern).to.be(constants.CRON_PATTERN_NEVER); + assert.equal(response.status, 200); + assert.equal(response.body.pattern, constants.CRON_PATTERN_NEVER); }); it('cannot set invalid autoupdate_pattern', async function () { @@ -63,7 +60,7 @@ describe('Updater API', function () { .query({ access_token: owner.token }) .send({ pattern: '1 3 x 5 6' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); }); }); diff --git a/src/routes/test/user-directory-test.js b/src/routes/test/user-directory-test.js index a52a31e1f..101ed086d 100644 --- a/src/routes/test/user-directory-test.js +++ b/src/routes/test/user-directory-test.js @@ -1,13 +1,10 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('User Directory API', function () { const { setup, cleanup, serverUrl, owner, user } = common; @@ -21,9 +18,9 @@ describe('User Directory API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.lockUserProfiles).to.be(false); - expect(response.body.mandatory2FA).to.be(false); + assert.equal(response.status, 200); + assert.equal(response.body.lockUserProfiles, false); + assert.equal(response.body.mandatory2FA, false); }); it('cannot set profile config without mandatory2FA', async function() { @@ -32,7 +29,7 @@ describe('User Directory API', function () { .send({ lockUserProfiles: true }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot set as normal user', async function() { @@ -41,7 +38,7 @@ describe('User Directory API', function () { .send({ lockUserProfiles: true, mandatory2FA: true }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can lock user profile', async function() { @@ -50,35 +47,35 @@ describe('User Directory API', function () { .send({ lockUserProfiles: true, mandatory2FA: false }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); const response2 = await superagent.post(`${serverUrl}/api/v1/profile/email`) .query({ access_token: owner.token }) .send({ email: 'newemail@example.Com', password: owner.password }) .ok(() => true); - expect(response2.status).to.equal(403); // profile is locked + assert.equal(response2.status, 403); // profile is locked const response3 = await superagent.post(`${serverUrl}/api/v1/profile/avatar`) .query({ access_token: owner.token }) .attach('avatar', './logo.png') .ok(() => true); - expect(response3.status).to.equal(403); // profile is locked + assert.equal(response3.status, 403); // profile is locked const response4 = await superagent.post(`${serverUrl}/api/v1/profile/fallback_email`) .query({ access_token: owner.token }) .send({ email: 'newemail@example.Com', password: owner.password }) .ok(() => true); - expect(response4.status).to.equal(403); // profile is locked + assert.equal(response4.status, 403); // profile is locked const response5 = await superagent.post(`${serverUrl}/api/v1/profile/display_name`) .query({ access_token: owner.token }) .send({ displayName: 'some new name' }) .ok(() => true); - expect(response5.status).to.equal(403); // profile is locked + assert.equal(response5.status, 403); // profile is locked }); it('can set mandatory 2fa', async function() { @@ -87,20 +84,20 @@ describe('User Directory API', function () { .send({ lockUserProfiles: true, mandatory2FA: true }) .ok(() => true); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); // token gets revoked! const response2 = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(200); // token is not gone, since it is persisted + assert.equal(response2.status, 200); // token is not gone, since it is persisted const response3 = await superagent.get(`${serverUrl}/api/v1/profile`) .query({ access_token: user.token }) .ok(() => true); - expect(response3.status).to.equal(401); // token is gone + assert.equal(response3.status, 401); // token is gone }); }); }); diff --git a/src/routes/test/users-test.js b/src/routes/test/users-test.js index db8d5fdf2..df40a06e3 100644 --- a/src/routes/test/users-test.js +++ b/src/routes/test/users-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import superagent from '@cloudron/superagent'; import users from '../../users.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Users API', function () { const { setup, cleanup, serverUrl, owner, user, dashboardDomain } = common; @@ -50,18 +47,18 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can get userInfo with token', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.username).to.equal(user.username.toLowerCase()); - expect(response.body.email).to.equal(user.email.toLowerCase()); - expect(response.body.groupIds).to.eql([]); - expect(response.body.role).to.be(users.ROLE_USER); + assert.equal(response.status, 200); + assert.equal(response.body.username, user.username.toLowerCase()); + assert.equal(response.body.email, user.email.toLowerCase()); + assert.deepEqual(response.body.groupIds, []); + assert.equal(response.body.role, users.ROLE_USER); }); it('cannot get userInfo with normal user token', async function () { @@ -69,7 +66,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(reponse.status).to.equal(403); + assert.equal(reponse.status, 403); }); }); @@ -80,7 +77,7 @@ describe('Users API', function () { .send({ username: user2.username }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot create user with non email fallbackEmail', async function () { @@ -89,7 +86,7 @@ describe('Users API', function () { .send({ username: user2.username, email: user2.email, fallbackEmail: 'notanemail' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('create second user succeeds', async function () { @@ -97,7 +94,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ username: user2.username, email: user2.email }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); user2.id = response.body.id; }); @@ -106,10 +103,10 @@ describe('Users API', function () { const response = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.username).to.equal(user2.username.toLowerCase()); - expect(response.body.email).to.equal(user2.email.toLowerCase()); - expect(response.body.groupIds).to.eql([]); + assert.equal(response.status, 200); + assert.equal(response.body.username, user2.username.toLowerCase()); + assert.equal(response.body.email, user2.email.toLowerCase()); + assert.deepEqual(response.body.groupIds, []); }); it('create user missing username succeeds', async function () { @@ -117,7 +114,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ email: unnamedUser.email }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); unnamedUser.id = response.body.id; }); @@ -127,7 +124,7 @@ describe('Users API', function () { .send({ username: 'someusername' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('create user reserved name fails', async function () { @@ -136,7 +133,7 @@ describe('Users API', function () { .send({ username: 'no-reply', email: 'reserved@cloudron.local' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('create user with short name succeeds', async function () { @@ -144,7 +141,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ username: 'n', email: 'singleletter@cloudron.local' }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('create user with same username should fail', async function () { @@ -153,7 +150,7 @@ describe('Users API', function () { .send({ username: user2.username, email: user2.email }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('cannot create user with bad password', async function () { @@ -162,7 +159,7 @@ describe('Users API', function () { .send({ username: 'badpassworduser', email: 'badpass@cloudron.local', password:'tooweak' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can create user with a password', async function () { @@ -170,7 +167,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ username: userWithPassword.username, email: userWithPassword.email, password: userWithPassword.password }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); userWithPassword.id = response.body.id; }); @@ -185,7 +182,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('creation succeeds', async function () { @@ -193,8 +190,8 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(200); - expect(response.body.inviteLink).to.be.a('string'); + assert.equal(response.status, 200); + assert.equal(typeof response.body.inviteLink, 'string'); }); it('sending succeeds', async function () { @@ -204,7 +201,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ email: user.email }); - expect(response.status).to.equal(202); + assert.equal(response.status, 202); await common.checkMails(1); }); }); @@ -215,15 +212,15 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ role: users.ROLE_ADMIN }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('did set second user as admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.role).to.be(users.ROLE_ADMIN); + assert.equal(response.status, 200); + assert.equal(response.body.role, users.ROLE_ADMIN); }); it('make self as admin fails', async function () { @@ -232,7 +229,7 @@ describe('Users API', function () { .send({ role: users.ROLE_ADMIN }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('make self as normal user fails', async function () { @@ -241,7 +238,7 @@ describe('Users API', function () { .send({ role: users.ROLE_USER }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('remove second user as admin succeeds', async function () { @@ -249,7 +246,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ role: users.ROLE_USER }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('normal user cannot change role of admin', async function () { @@ -258,7 +255,7 @@ describe('Users API', function () { .send({ role: users.ROLE_USER }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); }); @@ -267,11 +264,11 @@ describe('Users API', function () { const response = await superagent.get(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.users).to.be.an('array'); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.users)); response.body.users.forEach(function (u) { - expect('groupIds' in u).to.be(true); + assert.equal('groupIds' in u, true); }); }); }); @@ -282,25 +279,25 @@ describe('Users API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('list users succeeds for admin', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.users).to.be.an('array'); - expect(response.body.users.length).to.be.greaterThan(3); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.users)); + assert.ok((response.body.users.length) > (3)); response.body.users.forEach(function (u) { - expect(u).to.be.an('object'); - expect(u.id).to.be.ok(); - expect(u.email).to.be.ok(); - expect(u.role).to.be.ok(); - if (!u.email.startsWith('unnamed')) expect(u.username).to.be.ok(); - expect(u.password).to.not.be.ok(); - expect(u.salt).to.not.be.ok(); + assert.equal(typeof u, 'object'); + assert.ok(u.id); + assert.ok(u.email); + assert.ok(u.role); + if (!u.email.startsWith('unnamed')) assert.ok(u.username); + assert.ok(!(u.password)); + assert.ok(!(u.salt)); }); }); }); @@ -311,7 +308,7 @@ describe('Users API', function () { .send({ email: 'newemail@cloudron.local' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('change email fails due to invalid email', async function () { @@ -320,7 +317,7 @@ describe('Users API', function () { .send({ email: 'newemail@cloudron' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change fallbackEmail fails due to invalid email', async function () { @@ -329,7 +326,7 @@ describe('Users API', function () { .send({ fallbackEmail: 'newemail@cloudron' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change user succeeds without email nor displayName', async function () { @@ -337,7 +334,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({}); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('change email succeeds', async function () { @@ -346,15 +343,15 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ email: user2.email }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.username).to.equal(user2.username.toLowerCase()); - expect(response2.body.email).to.equal(user2.email.toLowerCase()); - expect(response2.body.displayName).to.equal(''); + assert.equal(response2.status, 200); + assert.equal(response2.body.username, user2.username.toLowerCase()); + assert.equal(response2.body.email, user2.email.toLowerCase()); + assert.equal(response2.body.displayName, ''); }); it('cannot change email to existing one', async function () { @@ -363,7 +360,7 @@ describe('Users API', function () { .send({ email: owner.email }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('can change display name', async function () { @@ -373,13 +370,13 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ displayName: displayName }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.displayName).to.equal(displayName); + assert.equal(response2.status, 200); + assert.equal(response2.body.displayName, displayName); }); it('can change avatar', async function () { @@ -389,26 +386,26 @@ describe('Users API', function () { const customAvatarSize = fs.readFileSync('./logo.png').length; - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}/avatar`) .query({ access_token: owner.token }); - expect(parseInt(response2.headers['content-length'])).to.equal(customAvatarSize); - expect(response2.status).to.equal(200); + assert.equal(parseInt(response2.headers['content-length']), customAvatarSize); + assert.equal(response2.status, 200); }); it('can unset avatar', async function () { const response = await superagent.del(`${serverUrl}/api/v1/users/${user2.id}/avatar`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}/avatar`) .query({ access_token: owner.token }) .ok(() => true); - expect(response2.status).to.equal(404); + assert.equal(response2.status, 404); }); }); @@ -419,7 +416,7 @@ describe('Users API', function () { .send({ password: 'youdontsay' }) .ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('change password fails due to small password', async function () { @@ -428,7 +425,7 @@ describe('Users API', function () { .send({ password: 'small' }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('change password succeeds', async function () { @@ -436,7 +433,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ password: 'bigenough' }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('did change the user password', async function () { @@ -450,13 +447,13 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ active: false }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.active).to.equal(false); + assert.equal(response2.status, 200); + assert.equal(response2.body.active, false); }); it('can make user active', async function () { @@ -464,13 +461,13 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ active: true }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`) .query({ access_token: owner.token }); - expect(response2.status).to.equal(200); - expect(response2.body.active).to.equal(true); + assert.equal(response2.status, 200); + assert.equal(response2.body.active, true); }); }); @@ -480,16 +477,16 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ role: users.ROLE_USER_MANAGER }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('can list users as usermanager', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.users).to.be.an(Array); - expect(response.body.users.length).to.be.greaterThan(3); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.users)); + assert.ok((response.body.users.length) > (3)); }); it('cannot set password of admin', async function () { @@ -498,7 +495,7 @@ describe('Users API', function () { .send({ password: 'bigenough' }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can set password of another', async function () { @@ -506,7 +503,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .send({ password: 'bigenough' }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('cannot change admin bit of another', async function () { @@ -515,7 +512,7 @@ describe('Users API', function () { .send({ role: users.ROLE_ADMIN }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('cannot change admin bit of self', async function () { @@ -524,7 +521,7 @@ describe('Users API', function () { .send({ role: users.ROLE_ADMIN }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('cannot remove admin', async function () { @@ -532,7 +529,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can create user as user manager', async function () { @@ -540,7 +537,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .send({ username: user3.username, email: user3.email }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); user3.id = response.body.id; }); @@ -549,7 +546,7 @@ describe('Users API', function () { const response = await superagent.del(`${serverUrl}/api/v1/users/${user3.id}`) .query({ access_token: user.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('add mailbox fails', async function () { @@ -558,7 +555,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); }); @@ -568,16 +565,16 @@ describe('Users API', function () { .query({ access_token: owner.token }) .send({ role: users.ROLE_MAIL_MANAGER }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('can list users as mail manager', async function () { const response = await superagent.get(`${serverUrl}/api/v1/users`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.users).to.be.an(Array); - expect(response.body.users.length).to.be.greaterThan(3); + assert.equal(response.status, 200); + assert.ok(Array.isArray(response.body.users)); + assert.ok((response.body.users.length) > (3)); }); it('cannot change admin bit of self', async function () { @@ -586,7 +583,7 @@ describe('Users API', function () { .send({ role: users.ROLE_ADMIN }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('cannot remove admin', async function () { @@ -594,7 +591,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .ok(() => true); - expect(response.status).to.equal(403); + assert.equal(response.status, 403); }); it('can create user as mail manager', async function () { @@ -602,7 +599,7 @@ describe('Users API', function () { .query({ access_token: user.token }) .send({ username: user3.username, email: user3.email }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); user3.id = response.body.id; }); @@ -611,7 +608,7 @@ describe('Users API', function () { const response = await superagent.del(`${serverUrl}/api/v1/users/${user3.id}`) .query({ access_token: user.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('add mailbox succeeds as mail manager', async function () { @@ -619,16 +616,16 @@ describe('Users API', function () { .send({ name: 'support', ownerId: owner.id, ownerType: 'user', active: true, storageQuota: 0, messagesQuota: 0, enablePop3: true }) .query({ access_token: user.token }); - expect(response.status).to.equal(201); + assert.equal(response.status, 201); }); it('list mailbox succeeds as mail manager', async function () { const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes`) .query({ access_token: user.token }); - expect(response.status).to.equal(200); - expect(response.body.mailboxes.length).to.be(1); - expect(response.body.mailboxes[0].name).to.be('support'); + assert.equal(response.status, 200); + assert.equal(response.body.mailboxes.length, 1); + assert.equal(response.body.mailboxes[0].name, 'support'); }); }); @@ -638,7 +635,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('user cannot removes himself', async function () { @@ -646,7 +643,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); it('admin removes normal user', async function () { @@ -654,7 +651,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); it('admin removes himself should not be allowed', async function () { @@ -662,7 +659,7 @@ describe('Users API', function () { .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(409); + assert.equal(response.status, 409); }); }); }); diff --git a/src/routes/test/volumes-test.js b/src/routes/test/volumes-test.js index b724d030e..150bd641b 100644 --- a/src/routes/test/volumes-test.js +++ b/src/routes/test/volumes-test.js @@ -1,13 +1,10 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import superagent from '@cloudron/superagent'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Volumes API', function () { const { setup, cleanup, serverUrl, owner } = common; @@ -21,7 +18,7 @@ describe('Volumes API', function () { .query({ access_token: owner.token }) .send({ name: 'music#/ ', mountType: 'filesystem', mountOptions: { hostPath: '/media/cloudron-test-music' } }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('cannot create volume with bad path', async function () { @@ -29,7 +26,7 @@ describe('Volumes API', function () { .query({ access_token: owner.token }) .send({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/tmp/music' } }) .ok(() => true); - expect(response.status).to.equal(400); + assert.equal(response.status, 400); }); it('can create volume', async function () { @@ -38,33 +35,33 @@ describe('Volumes API', function () { .send({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/media/cloudron-test-music' } }) .ok(() => true); - expect(response.status).to.equal(201); - expect(response.body.id).to.be.a('string'); + assert.equal(response.status, 201); + assert.equal(typeof response.body.id, 'string'); volumeId = response.body.id; }); it('can list volumes', async function () { const response = await superagent.get(`${serverUrl}/api/v1/volumes`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.volumes.length).to.be(1); - expect(response.body.volumes[0].id).to.be(volumeId); - expect(response.body.volumes[0].hostPath).to.be('/media/cloudron-test-music'); + assert.equal(response.status, 200); + assert.equal(response.body.volumes.length, 1); + assert.equal(response.body.volumes[0].id, volumeId); + assert.equal(response.body.volumes[0].hostPath, '/media/cloudron-test-music'); }); it('cannot get non-existent volume', async function () { const response = await superagent.get(`${serverUrl}/api/v1/volumes/foobar`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('can get volume', async function () { const response = await superagent.get(`${serverUrl}/api/v1/volumes/${volumeId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.id).to.be(volumeId); - expect(response.body.hostPath).to.be('/media/cloudron-test-music'); + assert.equal(response.status, 200); + assert.equal(response.body.id, volumeId); + assert.equal(response.body.hostPath, '/media/cloudron-test-music'); }); it('cannot update volume', async function () { @@ -73,12 +70,12 @@ describe('Volumes API', function () { .send({ mountOptions: { hostPath: '/media/cloudron-test-music-2' }}) .ok(() => true)); - expect(response.status).to.equal(400); // cannot update filesytem + assert.equal(response.status, 400); // cannot update filesytem }); it('can delete volume', async function () { const response = await superagent.del(`${serverUrl}/api/v1/volumes/${volumeId}`) .query({ access_token: owner.token }); - expect(response.status).to.equal(204); + assert.equal(response.status, 204); }); }); diff --git a/src/test/acme2-test.js b/src/test/acme2-test.js index b37656835..d4139a06b 100644 --- a/src/test/acme2-test.js +++ b/src/test/acme2-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import acme2 from '../acme2.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Acme2', function () { const { setup, cleanup } = common; @@ -16,14 +13,14 @@ describe('Acme2', function () { describe('getChallengeSubdomain', function () { it('non-wildcard', function () { - expect(acme2._getChallengeSubdomain('example.com', 'example.com')).to.be('_acme-challenge'); - expect(acme2._getChallengeSubdomain('git.example.com', 'example.com')).to.be('_acme-challenge.git'); + assert.equal(acme2._getChallengeSubdomain('example.com', 'example.com'), '_acme-challenge'); + assert.equal(acme2._getChallengeSubdomain('git.example.com', 'example.com'), '_acme-challenge.git'); }); it('wildcard', function () { - expect(acme2._getChallengeSubdomain('*.example.com', 'example.com')).to.be('_acme-challenge'); - expect(acme2._getChallengeSubdomain('*.git.example.com', 'example.com')).to.be('_acme-challenge.git'); - expect(acme2._getChallengeSubdomain('*.example.com', 'customer.example.com')).to.be('_acme-challenge'); + assert.equal(acme2._getChallengeSubdomain('*.example.com', 'example.com'), '_acme-challenge'); + assert.equal(acme2._getChallengeSubdomain('*.git.example.com', 'example.com'), '_acme-challenge.git'); + assert.equal(acme2._getChallengeSubdomain('*.example.com', 'customer.example.com'), '_acme-challenge'); }); }); }); diff --git a/src/test/addonconfigs-test.js b/src/test/addonconfigs-test.js index 996d51676..c2451b377 100644 --- a/src/test/addonconfigs-test.js +++ b/src/test/addonconfigs-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import addonConfigs from '../addonconfigs.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Addon config', function () { const { setup, cleanup, app } = common; @@ -16,7 +13,7 @@ describe('Addon config', function () { it('returns empty addon config array for invalid app', async function () { const results = await addonConfigs.getByAppId('randomid'); - expect(results).to.eql([ ]); + assert.deepEqual(results, [ ]); }); it('set succeeds', async function () { @@ -26,37 +23,37 @@ describe('Addon config', function () { it('get succeeds', async function () { const results = await addonConfigs.get(app.id, 'addonid1'); - expect(results).to.eql([ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' } ]); + assert.deepEqual(results, [ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' } ]); }); it('getByAppId succeeds', async function () { const results = await addonConfigs.getByAppId(app.id); - expect(results).to.eql([ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' }, { name: 'ENV3', value: 'env' } ]); + assert.deepEqual(results, [ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' }, { name: 'ENV3', value: 'env' } ]); }); it('getByName succeeds', async function () { const value = await addonConfigs.getByName(app.id, 'addonid1', 'ENV2'); - expect(value).to.be('env2'); + assert.equal(value, 'env2'); }); it('getByName of unknown value succeeds', async function () { const value = await addonConfigs.getByName(app.id, 'addonid1', 'ENVRANDOM'); - expect(value).to.be(null); + assert.equal(value, null); }); it('getAppIdByValue succeeds', async function () { const appId = await addonConfigs.getAppIdByValue('addonid1', 'ENV1', 'env'); - expect(appId).to.be(app.id); + assert.equal(appId, app.id); }); it('getAppIdByValue pattern succeeds', async function () { const appId = await addonConfigs.getAppIdByValue('addonid1', '%ENV1', 'env'); - expect(appId).to.be(app.id); + assert.equal(appId, app.id); }); it('getAppIdByValue pattern of unknown succeeds', async function () { const appId = await addonConfigs.getAppIdByValue('addonid1', '%ENV1', 'envx'); - expect(appId).to.be(null); + assert.equal(appId, null); }); it('unset succeeds', async function () { @@ -65,7 +62,7 @@ describe('Addon config', function () { it('unsetAddonConfig did remove configs', async function () { const results = await addonConfigs.getByAppId(app.id); - expect(results).to.eql([ { name: 'ENV3', value: 'env' }]); + assert.deepEqual(results, [ { name: 'ENV3', value: 'env' }]); }); it('unsetByAppId succeeds', async function () { @@ -74,6 +71,6 @@ describe('Addon config', function () { it('unsetByAppId did remove configs', async function () { const results = await addonConfigs.getByAppId(app.id); - expect(results).to.eql([ ]); + assert.deepEqual(results, [ ]); }); }); diff --git a/src/test/applinks-test.js b/src/test/applinks-test.js index 92ec52b01..84f0f8a82 100644 --- a/src/test/applinks-test.js +++ b/src/test/applinks-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import applinks from '../applinks.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Applinks', function () { const { setup, cleanup } = common; @@ -55,76 +52,76 @@ describe('Applinks', function () { APPLINK_2.id = await applinks.add(deepCopy(APPLINK_2)); const result = await applinks.get(APPLINK_2.id); - expect(result.upstreamUri).to.eql(APPLINK_2.upstreamUri); // should not have changed - expect(result.icon.length).to.not.eql(0); + assert.deepEqual(result.upstreamUri, APPLINK_2.upstreamUri); // should not have changed + assert.notDeepEqual(result.icon.length, 0); }); it('can add fourth applink to test no favicon', async function () { APPLINK_3.id = await applinks.add(deepCopy(APPLINK_3)); const result = await applinks.get(APPLINK_3.id); - expect(result.upstreamUri).to.eql('http://example.com'); - expect(result.icon).to.eql(null); + assert.deepEqual(result.upstreamUri, 'http://example.com'); + assert.deepEqual(result.icon, null); }); it('can list all without accessRestriction', async function () { const result = await applinks.list(); - expect(result.length).to.equal(4); - expect(result[1].id).to.eql(APPLINK_0.id); - expect(result[1].upstreamUri).to.eql(APPLINK_0.upstreamUri); - expect(result[3].id).to.eql(APPLINK_1.id); - expect(result[3].upstreamUri).to.eql(APPLINK_1.upstreamUri); - expect(result[3].label).to.eql(APPLINK_1.label); - expect(result[3].accessRestriction).to.eql(APPLINK_1.accessRestriction); - expect(result[3].tags).to.eql(APPLINK_1.tags); - expect(result[3].icon.toString('base64')).to.eql(APPLINK_1.icon); + assert.equal(result.length, 4); + assert.deepEqual(result[1].id, APPLINK_0.id); + assert.deepEqual(result[1].upstreamUri, APPLINK_0.upstreamUri); + assert.deepEqual(result[3].id, APPLINK_1.id); + assert.deepEqual(result[3].upstreamUri, APPLINK_1.upstreamUri); + assert.deepEqual(result[3].label, APPLINK_1.label); + assert.deepEqual(result[3].accessRestriction, APPLINK_1.accessRestriction); + assert.deepEqual(result[3].tags, APPLINK_1.tags); + assert.deepEqual(result[3].icon.toString('base64'), APPLINK_1.icon); }); it('cannot get applink with wrong id', async function () { const result = await applinks.get('doesnotexist'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can get applink', async function () { const result = await applinks.get(APPLINK_0.id); - expect(result.upstreamUri).to.eql(APPLINK_0.upstreamUri); + assert.deepEqual(result.upstreamUri, APPLINK_0.upstreamUri); }); it('can get second applink', async function () { const result = await applinks.get(APPLINK_1.id); - expect(result.id).to.eql(APPLINK_1.id); - expect(result.upstreamUri).to.eql(APPLINK_1.upstreamUri); - expect(result.label).to.eql(APPLINK_1.label); - expect(result.accessRestriction).to.eql(APPLINK_1.accessRestriction); - expect(result.tags).to.eql(APPLINK_1.tags); - expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon); + assert.deepEqual(result.id, APPLINK_1.id); + assert.deepEqual(result.upstreamUri, APPLINK_1.upstreamUri); + assert.deepEqual(result.label, APPLINK_1.label); + assert.deepEqual(result.accessRestriction, APPLINK_1.accessRestriction); + assert.deepEqual(result.tags, APPLINK_1.tags); + assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon); }); it('can update applink', async function () { await applinks.update(APPLINK_0, { upstreamUri: 'https://duckduckgo.com', icon: APPLINK_1.icon }); const result = await applinks.get(APPLINK_0.id); - expect(result.upstreamUri).to.equal('https://duckduckgo.com'); - expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon); + assert.equal(result.upstreamUri, 'https://duckduckgo.com'); + assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon); }); it('can get applink icon', async function () { const result = await applinks.get(APPLINK_0.id); - expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon); + assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon); }); it('cannot del applink with wrong id', async function () { const [error] = await safe(applinks.del({ id: 'doesnotexist' })); - expect(error).to.be.a(BoxError); - expect(error.reason).to.eql(BoxError.NOT_FOUND); + assert.ok((error) instanceof (BoxError)); + assert.deepEqual(error.reason, BoxError.NOT_FOUND); }); it('can del applink', async function () { await applinks.del(APPLINK_0); const result = await applinks.get(APPLINK_0.id); - expect(result).to.be(null); + assert.equal(result, null); }); }); diff --git a/src/test/apppasswords-test.js b/src/test/apppasswords-test.js index 312aad44c..96eafd33e 100644 --- a/src/test/apppasswords-test.js +++ b/src/test/apppasswords-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import appPasswords from '../apppasswords.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import users from '../users.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('App passwords', function () { const { setup, cleanup, admin } = common; @@ -21,59 +18,59 @@ describe('App passwords', function () { let id, password; it('cannot add bad app password', async function () { const [error] = await safe(appPasswords.add(admin.id, 'appid', 'x'.repeat(201), null)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can add app password', async function () { const result = await appPasswords.add(admin.id, 'appid', 'spark', null); - expect(result.id).to.be.a('string'); - expect(result.password).to.be.a('string'); + assert.equal(typeof result.id, 'string'); + assert.equal(typeof result.password, 'string'); id = result.id; password = result.password; }); it('can get app password', async function () { const result = await appPasswords.get(id); - expect(result.hashedPassword).to.be.a('string'); - expect(result.name).to.be('spark'); - expect(result.identifier).to.be('appid'); + assert.equal(typeof result.hashedPassword, 'string'); + assert.equal(result.name, 'spark'); + assert.equal(result.identifier, 'appid'); }); it('cannot get random app password', async function () { const result = await appPasswords.get('random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can get app passwords', async function () { const results = await appPasswords.list(admin.id); - expect(results.length).to.be(1); - expect(results[0].hashedPassword).to.be.a('string'); - expect(results[0].name).to.be('spark'); - expect(results[0].identifier).to.be('appid'); + assert.equal(results.length, 1); + assert.equal(typeof results[0].hashedPassword, 'string'); + assert.equal(results[0].name, 'spark'); + assert.equal(results[0].identifier, 'appid'); }); it('can verify app password', async function () { const result = await users.verifyWithId(admin.id, password, 'appid', {}); - expect(result).to.be.ok(); - expect(result.appPassword).to.be(true); + assert.ok(result); + assert.equal(result.appPassword, true); }); it('can verify non-app password', async function () { const result = await users.verifyWithId(admin.id, admin.password, 'appid', {}); - expect(result).to.be.ok(); - expect(result.appPassword).to.be(undefined); + assert.ok(result); + assert.equal(result.appPassword, undefined); }); it('cannot verify bad password', async function () { const [error, result] = await safe(users.verifyWithId(admin.id, 'bad', 'appid', {})); - expect(result).to.not.be.ok(); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.ok(!(result)); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('cannot verify password for another app', async function () { const [error, result] = await safe(users.verifyWithId(admin.id, password, 'appid2', {})); - expect(result).to.not.be.ok(); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.ok(!(result)); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('can del app password', async function () { @@ -82,42 +79,42 @@ describe('App passwords', function () { it('cannot verify deleted app password', async function () { const [error] = await safe(users.verifyWithId(admin.id, password, 'appid', {})); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('cannot del random app password', async function () { const [error] = await safe(appPasswords.del('random')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); // expiry tests let expiredPassword; it('can add app password with expiry', async function () { const result = await appPasswords.add(admin.id, 'appid', 'expiring', new Date(Date.now() + 60000).toISOString()); - expect(result.id).to.be.a('string'); - expect(result.password).to.be.a('string'); + assert.equal(typeof result.id, 'string'); + assert.equal(typeof result.password, 'string'); expiredPassword = result.password; }); it('can verify non-expired app password', async function () { const result = await users.verifyWithId(admin.id, expiredPassword, 'appid', {}); - expect(result).to.be.ok(); - expect(result.appPassword).to.be(true); + assert.ok(result); + assert.equal(result.appPassword, true); }); let pastId, pastPassword; it('can add app password with past expiry', async function () { const result = await appPasswords.add(admin.id, 'appid', 'expired', new Date(Date.now() - 60000).toISOString()); - expect(result.id).to.be.a('string'); - expect(result.password).to.be.a('string'); + assert.equal(typeof result.id, 'string'); + assert.equal(typeof result.password, 'string'); pastId = result.id; pastPassword = result.password; }); it('cannot verify expired app password', async function () { const [error, result] = await safe(users.verifyWithId(admin.id, pastPassword, 'appid', {})); - expect(result).to.not.be.ok(); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.ok(!(result)); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('can del expired app password', async function () { diff --git a/src/test/apps-test.js b/src/test/apps-test.js index 367f619f7..5ff17a107 100644 --- a/src/test/apps-test.js +++ b/src/test/apps-test.js @@ -1,19 +1,16 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import apps from '../apps.js'; import AuditSource from '../auditsource.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import Location from '../location.js'; import safe from 'safetydance'; import users from '../users.js'; const { proxyApp } = common; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Apps', function () { const { domainSetup, cleanup, app, admin, user , domain } = common; @@ -32,18 +29,18 @@ describe('Apps', function () { it('throws on exact conflict', async function () { let [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 40000, type: 'tcp', count: 1 }], {})); - expect(error.reason).to.equal(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 50000, type: 'udp', count: 1 }], {})); - expect(error.reason).to.equal(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); }); it('throws on range conflict', async function () { let [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 40080, type: 'tcp', count: 40 }], {})); - expect(error.reason).to.equal(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 49995, type: 'udp', count: 20 }], {})); - expect(error.reason).to.equal(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); }); it('succeeds without conflict', async function () { @@ -57,105 +54,105 @@ describe('Apps', function () { describe('validateLocations', function () { it('does not allow reserved subdomain', async function () { const location = new Location('my', domain.domain, Location.TYPE_ALIAS); - expect(await apps._validateLocations([location])).to.be.an(Error); + assert.ok((await apps._validateLocations([location])) instanceof (Error)); }); it('does not allow unknown domain', async function () { const location = new Location('my2', domain.domain + 'x', Location.TYPE_PRIMARY); - expect(await apps._validateLocations([location])).to.be.an(Error); + assert.ok((await apps._validateLocations([location])) instanceof (Error)); }); it('allows valid locations', async function () { const location = new Location('my2', domain.domain, Location.TYPE_SECONDARY); - expect(await apps._validateLocations([location])).to.be(null); + assert.equal(await apps._validateLocations([location]), null); }); }); describe('validatePortBindings', function () { it('does not allow invalid host port', function () { - expect(apps._validatePorts({ PORT: -1 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 0 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 'text' }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 65536 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 470 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); + assert.ok((apps._validatePorts({ PORT: -1 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 0 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 'text' }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 65536 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 470 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); }); it('does not allow ports not as part of manifest', function () { - expect(apps._validatePorts({ PORT: 1567 }, { tcpPorts: { } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 1567 }, { tcpPorts: { port3: null } })).to.be.an(Error); + assert.ok((apps._validatePorts({ PORT: 1567 }, { tcpPorts: { } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 1567 }, { tcpPorts: { port3: null } })) instanceof (Error)); }); it('does not allow reserved ports', function () { - expect(apps._validatePorts({ PORT: 443 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 50000 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 50100 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); - expect(apps._validatePorts({ PORT: 50050 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error); + assert.ok((apps._validatePorts({ PORT: 443 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 50000 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 50100 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); + assert.ok((apps._validatePorts({ PORT: 50050 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error)); }); it('allows valid bindings', function () { - expect(apps._validatePorts({ PORT: 1024 }, { tcpPorts: { PORT: 5000 } })).to.be(null); + assert.equal(apps._validatePorts({ PORT: 1024 }, { tcpPorts: { PORT: 5000 } }), null); - expect(apps._validatePorts({ + assert.equal(apps._validatePorts({ PORT1: 4033, PORT2: 3242, PORT3: 1234 - }, { tcpPorts: { PORT1: {}, PORT2: {}, PORT3: {} } })).to.be(null); + }, { tcpPorts: { PORT1: {}, PORT2: {}, PORT3: {} } }), null); }); }); describe('validateAccessRestriction', function () { it('allows null input', function () { - expect(apps._validateAccessRestriction(null)).to.eql(null); + assert.deepEqual(apps._validateAccessRestriction(null), null); }); it('does not allow wrong user type', function () { - expect(apps._validateAccessRestriction({ users: {} })).to.be.an(Error); + assert.ok((apps._validateAccessRestriction({ users: {} })) instanceof (Error)); }); it('allows user input', function () { - expect(apps._validateAccessRestriction({ users: [] })).to.eql(null); + assert.deepEqual(apps._validateAccessRestriction({ users: [] }), null); }); it('allows single user input', function () { - expect(apps._validateAccessRestriction({ users: [ 'someuserid' ] })).to.eql(null); + assert.deepEqual(apps._validateAccessRestriction({ users: [ 'someuserid' ] }), null); }); it('allows multi user input', function () { - expect(apps._validateAccessRestriction({ users: [ 'someuserid', 'someuserid1', 'someuserid2', 'someuserid3' ] })).to.eql(null); + assert.deepEqual(apps._validateAccessRestriction({ users: [ 'someuserid', 'someuserid1', 'someuserid2', 'someuserid3' ] }), null); }); }); describe('validateUpstreamUri', function () { it('does not allow empty URI', function () { - expect(apps._validateUpstreamUri('')).to.be.an(Error); + assert.ok((apps._validateUpstreamUri('')) instanceof (Error)); }); it('does not allow invalid URI scheme', function () { - expect(apps._validateUpstreamUri('bla:blub')).to.be.an(Error); + assert.ok((apps._validateUpstreamUri('bla:blub')) instanceof (Error)); }); it('does not allow unsupported scheme', function () { - expect(apps._validateUpstreamUri('ftp://foobar.com')).to.be.an(Error); + assert.ok((apps._validateUpstreamUri('ftp://foobar.com')) instanceof (Error)); }); it('does not allow trailing URI paths ', function () { - expect(apps._validateUpstreamUri('https://foobar.com/extra/path')).to.be.an(Error); + assert.ok((apps._validateUpstreamUri('https://foobar.com/extra/path')) instanceof (Error)); }); it('allows IP', function () { - expect(apps._validateUpstreamUri('http://1.2.3.4')).to.eql(null); + assert.deepEqual(apps._validateUpstreamUri('http://1.2.3.4'), null); }); it('allows IP with port', function () { - expect(apps._validateUpstreamUri('http://1.2.3.4:80')).to.eql(null); + assert.deepEqual(apps._validateUpstreamUri('http://1.2.3.4:80'), null); }); it('allows domain', function () { - expect(apps._validateUpstreamUri('https://www.cloudron.io')).to.eql(null); + assert.deepEqual(apps._validateUpstreamUri('https://www.cloudron.io'), null); }); it('allows domain with port', function () { - expect(apps._validateUpstreamUri('https://www.cloudron.io:443')).to.eql(null); + assert.deepEqual(apps._validateUpstreamUri('https://www.cloudron.io:443'), null); }); }); @@ -164,35 +161,35 @@ describe('Apps', function () { const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN }; it('returns true for unrestricted access', function () { - expect(apps.canAccess({ accessRestriction: null }, someuser)).to.be(true); + assert.equal(apps.canAccess({ accessRestriction: null }, someuser), true); }); it('returns true for allowed user', function () { - expect(apps.canAccess({ accessRestriction: { users: [ 'someuser' ] } }, someuser)).to.be(true); + assert.equal(apps.canAccess({ accessRestriction: { users: [ 'someuser' ] } }, someuser), true); }); it('returns true for allowed user with multiple allowed', function () { - expect(apps.canAccess({ accessRestriction: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser)).to.be(true); + assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser), true); }); it('returns false for not allowed user', function () { - expect(apps.canAccess({ accessRestriction: { users: [ 'foo' ] } }, someuser)).to.be(false); + assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo' ] } }, someuser), false); }); it('returns false for not allowed user with multiple allowed', function () { - expect(apps.canAccess({ accessRestriction: { users: [ 'foo', 'anotheruser' ] } }, someuser)).to.be(false); + assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo', 'anotheruser' ] } }, someuser), false); }); it('returns false for no group or user', function () { - expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ ] } }, someuser)).to.be(false); + assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ ] } }, someuser), false); }); it('returns false for invalid group or user', function () { - expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, someuser)).to.be(false); + assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, someuser), false); }); it('returns true for admin user', function () { - expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, adminuser)).to.be(true); + assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, adminuser), true); }); }); @@ -201,35 +198,35 @@ describe('Apps', function () { const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN }; it('returns false for unrestricted access', function () { - expect(apps.isOperator({ operators: null }, someuser)).to.be(false); + assert.equal(apps.isOperator({ operators: null }, someuser), false); }); it('returns true for allowed user', function () { - expect(apps.isOperator({ operators: { users: [ 'someuser' ] } }, someuser)).to.be(true); + assert.equal(apps.isOperator({ operators: { users: [ 'someuser' ] } }, someuser), true); }); it('returns true for allowed user with multiple allowed', function () { - expect(apps.isOperator({ operators: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser)).to.be(true); + assert.equal(apps.isOperator({ operators: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser), true); }); it('returns false for not allowed user', function () { - expect(apps.isOperator({ operators: { users: [ 'foo' ] } }, someuser)).to.be(false); + assert.equal(apps.isOperator({ operators: { users: [ 'foo' ] } }, someuser), false); }); it('returns false for not allowed user with multiple allowed', function () { - expect(apps.isOperator({ operators: { users: [ 'foo', 'anotheruser' ] } }, someuser)).to.be(false); + assert.equal(apps.isOperator({ operators: { users: [ 'foo', 'anotheruser' ] } }, someuser), false); }); it('returns false for no group or user', function () { - expect(apps.isOperator({ operators: { users: [ ], groups: [ ] } }, someuser)).to.be(false); + assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ ] } }, someuser), false); }); it('returns false for invalid group or user', function () { - expect(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, someuser)).to.be(false); + assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, someuser), false); }); it('returns true for admin user', function () { - expect(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, adminuser)).to.be(true); + assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, adminuser), true); }); }); @@ -238,25 +235,25 @@ describe('Apps', function () { const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN }; it('return user for normal user', function () { - expect(apps.accessLevel({ accessRestriction: null, operators: null }, someuser)).to.be(apps.ACCESS_LEVEL_USER); - expect(apps.accessLevel({ accessRestriction: null, operators: { users: [ ], groups: [ 'groupie' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_USER); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: null }, someuser), apps.ACCESS_LEVEL_USER); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [ ], groups: [ 'groupie' ] } }, someuser), apps.ACCESS_LEVEL_USER); }); it('returns operator for operator user', function () { - expect(apps.accessLevel({ accessRestriction: null, operators: { users: [ 'someuser' ], groups: [ 'groupie' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_OPERATOR); - expect(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [ 'ops' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_OPERATOR); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [ 'someuser' ], groups: [ 'groupie' ] } }, someuser), apps.ACCESS_LEVEL_OPERATOR); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [ 'ops' ] } }, someuser), apps.ACCESS_LEVEL_OPERATOR); }); it('returns admin for admin user', function () { - expect(apps.accessLevel({ accessRestriction: null, operators: null }, adminuser)).to.be(apps.ACCESS_LEVEL_ADMIN); - expect(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [] } }, adminuser)).to.be(apps.ACCESS_LEVEL_ADMIN); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: null }, adminuser), apps.ACCESS_LEVEL_ADMIN); + assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [] } }, adminuser), apps.ACCESS_LEVEL_ADMIN); }); }); describe('crud', function () { it('cannot get invalid app', async function () { const result = await apps.get('nope'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can add app', async function () { @@ -265,35 +262,35 @@ describe('Apps', function () { it('cannot add with same app id', async function () { const [error] = await safe(apps.add(app.id, app.appStoreId, '', app.manifest, app.subdomain, app.domain, app.portBindings, app)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cannot add with same app id', async function () { const [error] = await safe(apps.add(app.id, app.appStoreId, '', app.manifest, app.subdomain, app.domain, app.portBindings, app)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('can get app', async function () { const result = await apps.get(app.id); - expect(result.manifest).to.eql(app.manifest); - expect(result.portBindings).to.eql({}); - expect(result.subdomain).to.eql(app.subdomain); + assert.deepEqual(result.manifest, app.manifest); + assert.deepEqual(result.portBindings, {}); + assert.deepEqual(result.subdomain, app.subdomain); }); it('can list apps', async function () { const result = await apps.list(); - expect(result.length).to.be(1); - expect(result[0].manifest).to.eql(app.manifest); - expect(result[0].portBindings).to.eql({}); - expect(result[0].subdomain).to.eql(app.subdomain); + assert.equal(result.length, 1); + assert.deepEqual(result[0].manifest, app.manifest); + assert.deepEqual(result[0].portBindings, {}); + assert.deepEqual(result[0].subdomain, app.subdomain); }); it('can listByUser', async function () { let result = await apps.listByUser(admin); - expect(result.length).to.be(1); + assert.equal(result.length, 1); result = await apps.listByUser(user); - expect(result.length).to.be(1); + assert.equal(result.length, 1); }); it('update succeeds', async function () { @@ -310,17 +307,17 @@ describe('Apps', function () { await apps.update(app.id, data); const newApp = await apps.get(app.id); - expect(newApp.installationState).to.be('some-other-status'); - expect(newApp.subdomain).to.be('some-other-subdomain'); - expect(newApp.manifest.version).to.be('0.2.0'); - expect(newApp.accessRestriction).to.be(''); - expect(newApp.memoryLimit).to.be(1337); - expect(newApp.cpuQuota).to.be(79); + assert.equal(newApp.installationState, 'some-other-status'); + assert.equal(newApp.subdomain, 'some-other-subdomain'); + assert.equal(newApp.manifest.version, '0.2.0'); + assert.equal(newApp.accessRestriction, ''); + assert.equal(newApp.memoryLimit, 1337); + assert.equal(newApp.cpuQuota, 79); }); it('update of nonexisting app fails', async function () { const [error] = await safe(apps.update('random', { installationState: app.installationState, subdomain: app.subdomain })); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('delete succeeds', async function () { @@ -329,7 +326,7 @@ describe('Apps', function () { it('cannot delete previously delete record', async function () { const [error] = await safe(apps.del(app.id)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); @@ -340,19 +337,19 @@ describe('Apps', function () { it('can set app as healthy', async function () { const result = await apps.get(app.id); - expect(result.health).to.be(null); + assert.equal(result.health, null); await apps.setHealth(app.id, apps.HEALTH_HEALTHY, new Date()); }); it('did set app as healthy', async function () { const result = await apps.get(app.id); - expect(result.health).to.be(apps.HEALTH_HEALTHY); + assert.equal(result.health, apps.HEALTH_HEALTHY); }); it('cannot set health of unknown app', async function () { const [error] = await safe(apps.setHealth('randomId', apps.HEALTH_HEALTHY, new Date())); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); @@ -365,14 +362,14 @@ describe('Apps', function () { it('cannot set invalid upstream uri', async function () { const [error] = await safe(apps.setUpstreamUri(proxyApp, 'foo:bar:80', AuditSource.PLATFORM)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set upstream uri', async function () { await apps.setUpstreamUri(proxyApp, newUpstreamUri, AuditSource.PLATFORM); const result = await apps.get(proxyApp.id); - expect(result.upstreamUri).to.equal(newUpstreamUri); + assert.equal(result.upstreamUri, newUpstreamUri); }); }); @@ -395,9 +392,9 @@ describe('Apps', function () { await apps.configureApps(await apps.list(), { scheduleNow: false }, AuditSource.PLATFORM); const result = await apps.list(); - expect(result[0].installationState).to.be(apps.ISTATE_PENDING_CONFIGURE); - expect(result[1].installationState).to.be(apps.ISTATE_ERROR); - expect(result[2].installationState).to.be(apps.ISTATE_PENDING_CONFIGURE); + assert.equal(result[0].installationState, apps.ISTATE_PENDING_CONFIGURE); + assert.equal(result[1].installationState, apps.ISTATE_ERROR); + assert.equal(result[2].installationState, apps.ISTATE_PENDING_CONFIGURE); }); }); @@ -420,33 +417,33 @@ describe('Apps', function () { await apps.restoreApps(await apps.list(), { scheduleNow: false }, AuditSource.PLATFORM); const result = await apps.list(); - expect(result[0].installationState).to.be(apps.ISTATE_PENDING_INSTALL); - expect(result[1].installationState).to.be(apps.ISTATE_ERROR); - expect(result[2].installationState).to.be(apps.ISTATE_PENDING_INSTALL); + assert.equal(result[0].installationState, apps.ISTATE_PENDING_INSTALL); + assert.equal(result[1].installationState, apps.ISTATE_ERROR); + assert.equal(result[2].installationState, apps.ISTATE_PENDING_INSTALL); }); }); describe('parseCrontab', function () { it('succeeds for null crontob', function () { - expect(apps._parseCrontab(null)).to.eql([]); + assert.deepEqual(apps._parseCrontab(null), []); }); it('succeeds for empty crontob', function () { - expect(apps._parseCrontab('')).to.eql([]); + assert.deepEqual(apps._parseCrontab(''), []); }); it('throws for bad crontab', function () { safe(() => apps._parseCrontab('# some comment\n*/1 * * * ')); // incomplete pattern - expect(safe.error.message).to.be('Invalid cron configuration at line 2'); + assert.equal(safe.error.message, 'Invalid cron configuration at line 2'); safe(() => apps._parseCrontab('* * * * 13 command')); // bad pattern - expect(safe.error.message).to.be('Invalid cron pattern at line 1: Field value (13) is out of range'); + assert.equal(safe.error.message, 'Invalid cron pattern at line 1: Field value (13) is out of range'); safe(() => apps._parseCrontab('*/1 * * *\t* ')); // no command - expect(safe.error.message).to.be('Invalid cron configuration at line 1'); + assert.equal(safe.error.message, 'Invalid cron configuration at line 1'); safe(() => apps._parseCrontab('@whatever /bin/false')); // invalid extension - expect(safe.error.message).to.be('Unknown extension pattern at line 1'); + assert.equal(safe.error.message, 'Unknown extension pattern at line 1'); }); it('succeeds for crontab', function () { @@ -455,24 +452,24 @@ describe('Apps', function () { ' */1 * * *\t* echo "==> This is a custom cron task running every minute"\n\n' + '00 */1 * * * echo "==> This is a custom cron task running every hour" '); // trailing spaces are trimmed - expect(result.length).to.be(2); - expect(result[0].schedule).to.be('*/1 * * * *'); - expect(result[0].command).to.be('echo "==> This is a custom cron task running every minute"'); + assert.equal(result.length, 2); + assert.equal(result[0].schedule, '*/1 * * * *'); + assert.equal(result[0].command, 'echo "==> This is a custom cron task running every minute"'); - expect(result[1].schedule).to.be('00 */1 * * *'); - expect(result[1].command).to.be('echo "==> This is a custom cron task running every hour"'); + assert.equal(result[1].schedule, '00 */1 * * *'); + assert.equal(result[1].command, 'echo "==> This is a custom cron task running every hour"'); }); it('succeeds for crontab (extensions)', function () { const result = apps._parseCrontab('@service /bin/service\n\n@weekly /bin/weekly'); - expect(result.length).to.be(2); + assert.equal(result.length, 2); - expect(result[0].schedule).to.be('@service'); - expect(result[0].command).to.be('/bin/service'); + assert.equal(result[0].schedule, '@service'); + assert.equal(result[0].command, '/bin/service'); - expect(result[1].schedule).to.be('0 0 * * 0'); - expect(result[1].command).to.be('/bin/weekly'); + assert.equal(result[1].schedule, '0 0 * * 0'); + assert.equal(result[1].command, '/bin/weekly'); }); }); }); diff --git a/src/test/apptask-test.js b/src/test/apptask-test.js index 82c91c699..57242dd20 100644 --- a/src/test/apptask-test.js +++ b/src/test/apptask-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import apptask from '../apptask.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import paths from '../paths.js'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('apptask', function () { const { setup, cleanup, app } = common; @@ -19,19 +16,19 @@ describe('apptask', function () { it('create volume', async function () { await apptask._createAppDir(app); - expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true); - expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id + '/data')).to.be(false); + assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true); + assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id + '/data'), false); }); it('delete volume - removeDirectory (false) ', async function () { await apptask._deleteAppDir(app, { removeDirectory: false }); - expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true); - expect(fs.readdirSync(paths.APPS_DATA_DIR + '/' + app.id).length).to.be(0); // empty + assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true); + assert.equal(fs.readdirSync(paths.APPS_DATA_DIR + '/' + app.id).length, 0); // empty }); it('delete volume - removeDirectory (true) ', async function () { await apptask._deleteAppDir(app, { removeDirectory: true }); - expect(!fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true); + assert.equal(!fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true); }); it('barfs on empty manifest', async function () { @@ -39,7 +36,7 @@ describe('apptask', function () { badApp.manifest = { }; const [error] = await safe(apptask._verifyManifest(badApp.manifest)); - expect(error).to.be.ok(); + assert.ok(error); }); it('fails on bad manifest', async function () { @@ -48,7 +45,7 @@ describe('apptask', function () { delete badApp.manifest.httpPort; const [error] = await safe(apptask._verifyManifest(badApp.manifest)); - expect(error).to.be.ok(); + assert.ok(error); }); it('barfs on incompatible manifest', async function () { @@ -57,7 +54,7 @@ describe('apptask', function () { badApp.manifest.maxBoxVersion = '0.0.0'; // max box version is too small const [error] = await safe(apptask._verifyManifest(badApp.manifest)); - expect(error).to.be.ok(); + assert.ok(error); }); it('verifies manifest', async function () { diff --git a/src/test/archives-test.js b/src/test/archives-test.js index 1d1cc9110..d77a0e551 100644 --- a/src/test/archives-test.js +++ b/src/test/archives-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import archives from '../archives.js'; import backups from '../backups.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Archives', function () { const { setup, cleanup, auditSource, getDefaultBackupSite } = common; @@ -41,7 +38,7 @@ describe('Archives', function () { it('cannot add bad backup to archives', async function () { const [error] = await safe(archives.add('badId', {}, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can add good backup to archives', async function () { @@ -50,35 +47,35 @@ describe('Archives', function () { it('cannot get invalid archive', async function () { const result = await archives.get('bad'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can get archive', async function () { const result = await archives.get(archiveId); - expect(result.appConfig).to.eql(appBackup.appConfig); + assert.deepEqual(result.appConfig, appBackup.appConfig); }); it('can list archives', async function () { const result = await archives.list(1, 100); - expect(result.length).to.be(1); - expect(result[0].id).to.be(archiveId); - expect(result[0].appConfig).to.eql(appBackup.appConfig); + assert.equal(result.length, 1); + assert.equal(result[0].id, archiveId); + assert.deepEqual(result[0].appConfig, appBackup.appConfig); }); it('can list backupIds', async function () { const result = await archives.listBackupIds(); - expect(result.length).to.be(1); - expect(result[0]).to.be(appBackup.id); + assert.equal(result.length, 1); + assert.equal(result[0], appBackup.id); }); it('cannot delete bad archive', async function () { const [error] = await safe(archives.del({ id: 'badId' }, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can del valid archive', async function () { await archives.del({ id: archiveId }, auditSource); const result = await archives.list(1, 10); - expect(result.length).to.be(0); + assert.equal(result.length, 0); }); }); diff --git a/src/test/backupcleaner-test.js b/src/test/backupcleaner-test.js index 09fb1c82e..70c377e88 100644 --- a/src/test/backupcleaner-test.js +++ b/src/test/backupcleaner-test.js @@ -1,3 +1,4 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import archives from '../archives.js'; @@ -5,15 +6,11 @@ import backupCleaner from '../backupcleaner.js'; import backups from '../backups.js'; import backupSites from '../backupsites.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import moment from 'moment'; import tasks from '../tasks.js'; import timers from 'timers/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backup cleaner', function () { const { setup, cleanup, app, getDefaultBackupSite, auditSource } = common; @@ -39,25 +36,25 @@ describe('backup cleaner', function () { it('keeps latest', function () { const backup = Object.assign({}, backupTemplate, { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }); backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []); - expect(backup.keepReason).to.be('latest'); + assert.equal(backup.keepReason, 'latest'); }); it('does not keep latest', function () { const backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: false }, []); - expect(backup.keepReason).to.be(undefined); + assert.equal(backup.keepReason, undefined); }); it('always keeps forever policy', function () { const backup = { creationTime: new Date() }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: -1, keepLatest: true }, []); - expect(backup.keepReason).to.be('keepWithinSecs'); + assert.equal(backup.keepReason, 'keepWithinSecs'); }); it('preserveSecs takes precedence', function () { const backup = { creationTime: new Date(), preserveSecs: 3000 }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []); - expect(backup.keepReason).to.be('preserveSecs'); + assert.equal(backup.keepReason, 'preserveSecs'); }); it('1 daily', function () { @@ -69,11 +66,11 @@ describe('backup cleaner', function () { { id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } ]; backupCleaner._applyBackupRetention(b, { keepDaily: 1, keepLatest: true }, []); - expect(b[0].keepReason).to.be('keepDaily'); - expect(b[1].keepReason).to.be(undefined); - expect(b[2].keepReason).to.be(undefined); - expect(b[3].keepReason).to.be(undefined); - expect(b[3].keepReason).to.be(undefined); + assert.equal(b[0].keepReason, 'keepDaily'); + assert.equal(b[1].keepReason, undefined); + assert.equal(b[2].keepReason, undefined); + assert.equal(b[3].keepReason, undefined); + assert.equal(b[3].keepReason, undefined); }); // if you are debugging this test, it's because of some timezone issue with all the hour substraction! @@ -88,13 +85,13 @@ describe('backup cleaner', function () { { id: '6', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } ]; backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepWeekly: 1, keepLatest: false }, []); - expect(b[0].keepReason).to.be('keepDaily'); // today - expect(b[1].keepReason).to.be('keepWeekly'); // today - expect(b[2].keepReason).to.be(undefined); - expect(b[3].keepReason).to.be('keepDaily'); // yesterday - expect(b[4].discardReason).to.be('error'); // errored - expect(b[5].discardReason).to.be('creating-too-long'); // creating for too long - expect(b[6].keepReason).to.be(undefined); // outside retention policy + assert.equal(b[0].keepReason, 'keepDaily'); // today + assert.equal(b[1].keepReason, 'keepWeekly'); // today + assert.equal(b[2].keepReason, undefined); + assert.equal(b[3].keepReason, 'keepDaily'); // yesterday + assert.equal(b[4].discardReason, 'error'); // errored + assert.equal(b[5].discardReason, 'creating-too-long'); // creating for too long + assert.equal(b[6].keepReason, undefined); // outside retention policy }); it('2 daily, 3 monthly, 1 yearly', function () { @@ -111,16 +108,16 @@ describe('backup cleaner', function () { { id: '9', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() }, ]; backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepMonthly: 3, keepYearly: 1, keepLatest: true }, []); - expect(b[0].keepReason).to.be('creating'); - expect(b[1].discardReason).to.be('error'); // errored - expect(b[2].keepReason).to.be('keepDaily'); - expect(b[3].keepReason).to.be('keepMonthly'); - expect(b[4].keepReason).to.be('keepYearly'); - expect(b[5].keepReason).to.be('keepDaily'); // yesterday - expect(b[6].discardReason).to.be('creating-too-long'); // errored - expect(b[7].keepReason).to.be('keepMonthly'); - expect(b[8].keepReason).to.be('keepMonthly'); - expect(b[9].keepReason).to.be(undefined); + assert.equal(b[0].keepReason, 'creating'); + assert.equal(b[1].discardReason, 'error'); // errored + assert.equal(b[2].keepReason, 'keepDaily'); + assert.equal(b[3].keepReason, 'keepMonthly'); + assert.equal(b[4].keepReason, 'keepYearly'); + assert.equal(b[5].keepReason, 'keepDaily'); // yesterday + assert.equal(b[6].discardReason, 'creating-too-long'); // errored + assert.equal(b[7].keepReason, 'keepMonthly'); + assert.equal(b[8].keepReason, 'keepMonthly'); + assert.equal(b[9].keepReason, undefined); }); }); @@ -288,23 +285,23 @@ describe('backup cleaner', function () { await cleanupBackups(site); const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, site.id, 1, 1000); - expect(results.length).to.equal(1); - expect(results[0].id).to.equal(BACKUP_1_BOX.id); + assert.equal(results.length, 1); + assert.equal(results[0].id, BACKUP_1_BOX.id); // check that app backups are gone as well. only backup_1 will remain const result = await backups.get(BACKUP_0_APP_0.id); - expect(result).to.be(null); + assert.equal(result, null); }); it('does not remove expired backups if only one left', async function () { await cleanupBackups(site); const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, site.id, 1, 1000); - expect(results[0].id).to.equal(BACKUP_1_BOX.id); + assert.equal(results[0].id, BACKUP_1_BOX.id); // check that app backups are also still there. backup_1 is still there const result = await backups.get(BACKUP_1_APP_0.id); - expect(result.id).to.equal(BACKUP_1_APP_0.id); + assert.equal(result.id, BACKUP_1_APP_0.id); }); it('succeeds for app backups not referenced by a box backup', async function () { @@ -318,12 +315,12 @@ describe('backup cleaner', function () { await cleanupBackups(site); let result = await backups.listByTypePaged(backups.BACKUP_TYPE_APP, site.id, 1, 1000); - expect(result.length).to.equal(4); + assert.equal(result.length, 4); result = result.sort((r1, r2) => r1.remotePath.localeCompare(r2.remotePath)); - expect(result[0].id).to.be(BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved - expect(result[1].id).to.be(BACKUP_1_APP_0.id); // referenced by box - expect(result[2].id).to.be(BACKUP_1_APP_1.id); // referenced by box - expect(result[3].id).to.be(BACKUP_2_APP_2.id); // referenced by archive + assert.equal(result[0].id, BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved + assert.equal(result[1].id, BACKUP_1_APP_0.id); // referenced by box + assert.equal(result[2].id, BACKUP_1_APP_1.id); // referenced by box + assert.equal(result[3].id, BACKUP_2_APP_2.id); // referenced by archive }); }); }); diff --git a/src/test/backupformat-test.js b/src/test/backupformat-test.js index 747b55843..fa74e7bfa 100644 --- a/src/test/backupformat-test.js +++ b/src/test/backupformat-test.js @@ -1,10 +1,11 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; import DataLayout from '../datalayout.js'; import tgz from '../backupformat/tgz.js'; const EnsureFileSizeStream = tgz._EnsureFileSizeStream; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; @@ -12,10 +13,6 @@ import rsync from '../backupformat/rsync.js'; import safe from 'safetydance'; import stream from 'node:stream/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backuptask', function () { const { setup, cleanup, createTree } = common; @@ -38,9 +35,9 @@ describe('backuptask', function () { const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); - expect(error).to.be(null); + assert.equal(error, null); const out = fs.readFileSync('/tmp/out.txt'); - expect(out).to.eql(data); + assert.deepEqual(out, data); }); it('overflow', async function () { @@ -48,9 +45,9 @@ describe('backuptask', function () { const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); - expect(error).to.be(null); + assert.equal(error, null); const out = fs.readFileSync('/tmp/out.txt'); - expect(out).to.eql(data.subarray(0, 20)); + assert.deepEqual(out, data.subarray(0, 20)); }); it('underflow', async function () { @@ -58,9 +55,9 @@ describe('backuptask', function () { const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); - expect(error).to.be(null); + assert.equal(error, null); const out = fs.readFileSync('/tmp/out.txt'); - expect(out).to.eql(Buffer.concat([data, Buffer.alloc(8)])); + assert.deepEqual(out, Buffer.concat([data, Buffer.alloc(8)])); }); }); @@ -82,24 +79,24 @@ describe('backuptask', function () { await rsync._saveFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`); const emptyDirs = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).emptyDirs; - expect(emptyDirs).to.eql(['./data/subdir/emptydir']); + assert.deepEqual(emptyDirs, ['./data/subdir/emptydir']); const execFiles = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).execFiles; - expect(execFiles).to.eql(['./dir2/file']); + assert.deepEqual(execFiles, ['./dir2/file']); }); it('restores special files', async function () { fs.rmSync(path.join(tmpdir, 'data'), { recursive: true, force: true }); - expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(false); // just make sure rimraf worked + assert.equal(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir')), false); // just make sure rimraf worked const dataLayout = new DataLayout(tmpdir, []); await rsync._restoreFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`); - expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(true); + assert.equal(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir')), true); const mode = fs.statSync(path.join(tmpdir, 'dir2/file')).mode; - expect(mode & ~fs.constants.S_IFREG).to.be(parseInt('0755', 8)); + assert.equal(mode & ~fs.constants.S_IFREG, parseInt('0755', 8)); }); }); }); diff --git a/src/test/backupintegrity-test.js b/src/test/backupintegrity-test.js index 5bc767da5..ef4b79139 100644 --- a/src/test/backupintegrity-test.js +++ b/src/test/backupintegrity-test.js @@ -1,3 +1,4 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import backupIntegrity from '../backupintegrity.js'; @@ -6,17 +7,13 @@ import backupSites from '../backupsites.js'; import BoxError from '../boxerror.js'; import child_process from 'node:child_process'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import tasks from '../tasks.js'; import timers from 'timers/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backupintegrity', function () { const { setup, cleanup, getDefaultBackupSite, auditSource } = common; @@ -64,11 +61,11 @@ describe('backupintegrity', function () { it('throws for missing backup id', async function () { try { await backupIntegrity.check('nonexistent-id', () => {}); - expect().fail('expected BoxError'); + assert.ok().fail('expected BoxError'); } catch (err) { - expect(err).to.be.a(BoxError); - expect(err.reason).to.be(BoxError.BAD_FIELD); - expect(err.message).to.contain('Backup not found'); + assert.ok((err) instanceof (BoxError)); + assert.equal(err.reason, BoxError.BAD_FIELD); + assert.ok(err.message.includes('Backup not found')); } }); @@ -84,9 +81,9 @@ describe('backupintegrity', function () { await backupIntegrity.check(backup.id, (p) => { progressCalls.push(p); }); const updated = await backups.get(backup.id); - expect(updated.integrityCheckStatus).to.be('passed'); - expect(updated.integrityCheckResult.messages).to.eql([]); - expect(updated.integrityCheckResult.stats).to.be.an('object'); + assert.equal(updated.integrityCheckStatus, 'passed'); + assert.deepEqual(updated.integrityCheckResult.messages, []); + assert.equal(typeof updated.integrityCheckResult.stats, 'object'); }); it('cleanup', function () { diff --git a/src/test/backups-test.js b/src/test/backups-test.js index 87da568de..9d0b3d37f 100644 --- a/src/test/backups-test.js +++ b/src/test/backups-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import backups from '../backups.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backups', function () { const { setup, cleanup, getDefaultBackupSite } = common; @@ -77,38 +74,38 @@ describe('backups', function () { it('fails with duplicate path', async function () { const [error] = await safe(backups.add(boxBackup)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('get succeeds', async function () { const result = await backups.get(boxBackup.id); delete result.creationTime; - expect(result).to.eql(boxBackup); + assert.deepEqual(result, boxBackup); }); it('get of unknown id fails', async function () { const result = await backups.get('somerandom'); - expect(result).to.be(null); + assert.equal(result, null); }); it('listByTypePaged succeeds', async function () { const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 5); - expect(results.length).to.be(1); + assert.equal(results.length, 1); delete results[0].creationTime; - expect(results[0]).to.eql(boxBackup); + assert.deepEqual(results[0], boxBackup); }); it('update succeeds', async function () { await backups.update(boxBackup, { label: 'DuMonde', preserveSecs: 30 }); const result = await backups.get(boxBackup.id); - expect(result.label).to.eql('DuMonde'); - expect(result.preserveSecs).to.eql(30); + assert.deepEqual(result.label, 'DuMonde'); + assert.deepEqual(result.preserveSecs, 30); }); it('delete succeeds', async function () { await backups.del(boxBackup.id); const result = await backups.get(boxBackup.id); - expect(result).to.be(null); + assert.equal(result, null); }); it('add app backup succeeds', async function () { @@ -118,20 +115,20 @@ describe('backups', function () { it('get app backup succeeds', async function () { const result = await backups.get(appBackup.id); delete result.creationTime; - expect(result).to.eql(appBackup); + assert.deepEqual(result, appBackup); }); it('listByIdentifierAndStatePaged succeeds', async function () { const results = await backups.listByIdentifierAndStatePaged(appBackup.identifier, backups.BACKUP_STATE_CREATING, 1, 5); - expect(results.length).to.be(1); + assert.equal(results.length, 1); delete results[0].creationTime; - expect(results[0]).to.eql(appBackup); + assert.deepEqual(results[0], appBackup); }); it('delete app backup succeeds', async function () { await backups.del(appBackup.id); const result = await backups.get(appBackup.id); - expect(result).to.be(null); + assert.equal(result, null); }); }); }); diff --git a/src/test/backupsites-test.js b/src/test/backupsites-test.js index de8d1a112..24e788413 100644 --- a/src/test/backupsites-test.js +++ b/src/test/backupsites-test.js @@ -1,3 +1,4 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import archives from '../archives.js'; @@ -6,13 +7,9 @@ import backupSites from '../backupsites.js'; import BoxError from '../boxerror.js'; import common from './common.js'; import constants from '../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backups', function () { const { setup, cleanup, auditSource, getDefaultBackupSite } = common; @@ -60,28 +57,28 @@ describe('backups', function () { it('can add another site', async function () { const id = await backupSites.add(backupSite, auditSource); - expect(id).to.be.ok(); + assert.ok(id); backupSite.id = id; }); it('can list backup sites', async function () { const result = await backupSites.list(); - expect(result.length).to.be(2); + assert.equal(result.length, 2); }); it('can get backup site', async function () { const result = await backupSites.get(defaultBackupSite.id); - expect(result.provider).to.be('filesystem'); - expect(result.config.backupDir).to.be.ok(); // the test sets this to some tmp location - expect(result.format).to.be('tgz'); - expect(result.encryption).to.be(null); - expect(result.contents).to.be(null); - expect(result.enableForUpdates).to.be(true); + assert.equal(result.provider, 'filesystem'); + assert.ok(result.config.backupDir); // the test sets this to some tmp location + assert.equal(result.format, 'tgz'); + assert.equal(result.encryption, null); + assert.equal(result.contents, null); + assert.equal(result.enableForUpdates, true); }); it('cannot get random backup site', async function () { const result = await backupSites.get('random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can set backup config', async function () { @@ -89,39 +86,39 @@ describe('backups', function () { await backupSites.setConfig(defaultBackupSite, newConfig, auditSource); const result = await backupSites.get(defaultBackupSite.id); - expect(result.config.backupDir).to.be('/tmp/backups'); + assert.equal(result.config.backupDir, '/tmp/backups'); }); it('cannot set invalid schedule', async function () { const [error] = await safe(backupSites.setSchedule(defaultBackupSite, '', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set valid schedule', async function () { for (const pattern of [ '00 * * * * *', constants.CRON_PATTERN_NEVER ]) { await backupSites.setSchedule(defaultBackupSite, pattern, auditSource); const result = await backupSites.get(defaultBackupSite.id); - expect(result.schedule).to.be(pattern); + assert.equal(result.schedule, pattern); } }); it('cannot set invalid retention', async function () { const [error] = await safe(backupSites.setRetention(defaultBackupSite, { keepWhenever: 4 }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set valid retention', async function () { for (const retention of [ { keepWithinSecs: 1 }, { keepYearly: 3 }, { keepMonthly: 14 } ]) { await backupSites.setRetention(defaultBackupSite, retention, auditSource); const result = await backupSites.get(defaultBackupSite.id); - expect(result.retention).to.eql(retention); + assert.deepEqual(result.retention, retention); } }); it('cannot disable for update', async function () { await backupSites.setEnabledForUpdates(defaultBackupSite, false, auditSource); const result = await backupSites.get(defaultBackupSite.id); - expect(result.enableForUpdates).to.eql(false); + assert.deepEqual(result.enableForUpdates, false); }); it('can delete all the backup sites', async function () { @@ -129,8 +126,8 @@ describe('backups', function () { backupSite.integrityKeyPair = {}; // keep removePrivateFields happy await backupSites.del(backupSite, auditSource); - expect(await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 10)).to.eql([]); - expect(await archives.list(1, 10)).to.eql([]); - expect(await backupSites.list()).to.eql([]); + assert.deepEqual(await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 10), []); + assert.deepEqual(await archives.list(1, 10), []); + assert.deepEqual(await backupSites.list(), []); }); }); diff --git a/src/test/backuptask-test.js b/src/test/backuptask-test.js index 597d57e57..9bb9104e0 100644 --- a/src/test/backuptask-test.js +++ b/src/test/backuptask-test.js @@ -1,20 +1,17 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import backups from '../backups.js'; import backupSites from '../backupsites.js'; import child_process from 'node:child_process'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import tasks from '../tasks.js'; import timers from 'timers/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('backuptask', function () { const { setup, cleanup, getDefaultBackupSite, auditSource } = common; @@ -69,8 +66,8 @@ describe('backuptask', function () { } const result = await createBackup(defaultBackupSite); - expect(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink).to.be(2); // hard linked to a rotated backup - expect(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink).to.be(2); + assert.equal(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink, 2); // hard linked to a rotated backup + assert.equal(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink, 2); backupInfo1 = result; }); @@ -83,9 +80,9 @@ describe('backuptask', function () { } const result = await createBackup(defaultBackupSite); - expect(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink).to.be(2); // hard linked to a rotated backup - expect(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink).to.be(2); // hard linked to new backup - expect(fs.statSync(path.join(backupConfig.backupDir, backupInfo1.remotePath)).nlink).to.be(1); // not hard linked anymore + assert.equal(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink, 2); // hard linked to a rotated backup + assert.equal(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink, 2); // hard linked to new backup + assert.equal(fs.statSync(path.join(backupConfig.backupDir, backupInfo1.remotePath)).nlink, 1); // not hard linked anymore }); it('cleanup', function () { diff --git a/src/test/blobs-test.js b/src/test/blobs-test.js index a6ffc5e4c..6620dd565 100644 --- a/src/test/blobs-test.js +++ b/src/test/blobs-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import blobs from '../blobs.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('blobs', function () { const { setup, cleanup } = common; @@ -19,17 +16,17 @@ describe('blobs', function () { }); it('can get the set value', async function () { const value = await blobs.get('someid'); - expect(value).to.eql(Buffer.from('somevalue')); + assert.deepEqual(value, Buffer.from('somevalue')); }); it('can update a value', async function () { await blobs.set('someid', Buffer.from('someothervalue')); }); it('can get updated value', async function () { const value = await blobs.get('someid'); - expect(value).to.eql(Buffer.from('someothervalue')); + assert.deepEqual(value, Buffer.from('someothervalue')); }); it('cannot get randome value', async function () { const value = await blobs.get('unknownid'); - expect(value).to.be(null); + assert.equal(value, null); }); }); diff --git a/src/test/branding-test.js b/src/test/branding-test.js index b8b4ab793..f47af0662 100644 --- a/src/test/branding-test.js +++ b/src/test/branding-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import branding from '../branding.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Branding', function () { const { setup, cleanup, auditSource } = common; @@ -18,42 +15,42 @@ describe('Branding', function () { it ('can get default cloudron name', async function () { const name = await branding.getCloudronName(); - expect(name).to.be('Cloudron'); + assert.equal(name, 'Cloudron'); }); it('can set name', async function () { await branding.setCloudronName('Dolomites', auditSource); const name = await branding.getCloudronName(); - expect(name).to.be('Dolomites'); + assert.equal(name, 'Dolomites'); }); it('can set emoji in name', async function () { await branding.setCloudronName('🎊 Cloudron 🎉', auditSource); const name = await branding.getCloudronName(); - expect(name).to.be('🎊 Cloudron 🎉'); + assert.equal(name, '🎊 Cloudron 🎉'); }); it('cannot set large name', async function () { const [error] = await safe(branding.setCloudronName('x'.repeat(65), auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can get default cloudron avatar', async function () { const avatar = await branding.getCloudronAvatar(); - expect(avatar).to.be.a(Buffer); + assert.ok((avatar) instanceof (Buffer)); }); it('can render default footer', async function () { - expect(await branding.renderFooter()).to.contain('(https://cloudron.io)'); + assert.ok((await branding.renderFooter()).includes('(https://cloudron.io)')); }); it('can render footer', async function () { await branding.setFooter('BigFoot Inc', auditSource); - expect(await branding.renderFooter()).to.be('BigFoot Inc'); + assert.equal(await branding.renderFooter(), 'BigFoot Inc'); }); it('can render footer with YEAR', async function () { await branding.setFooter('BigFoot Inc %YEAR%', auditSource); - expect(await branding.renderFooter()).to.be('BigFoot Inc 2026'); + assert.equal(await branding.renderFooter(), 'BigFoot Inc 2026'); }); }); diff --git a/src/test/cloudron-test.js b/src/test/cloudron-test.js index 5325fb093..28beb9034 100644 --- a/src/test/cloudron-test.js +++ b/src/test/cloudron-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; import cloudron from '../cloudron.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Cloudron', function () { const { setup, cleanup } = common; @@ -19,36 +16,36 @@ describe('Cloudron', function () { describe('timezone', function () { it('can get default timezone', async function () { const tz = await cloudron.getTimeZone(); - expect(tz).to.be('UTC'); + assert.equal(tz, 'UTC'); }); it('cannot set invalid timezone', async function () { const [error] = await safe(cloudron.setTimeZone('OMG')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set valid timezone', async function () { await cloudron.setTimeZone('Africa/Johannesburg'); const tz = await cloudron.getTimeZone(); - expect(tz).to.be('Africa/Johannesburg'); + assert.equal(tz, 'Africa/Johannesburg'); }); }); describe('language', function () { it('can get default language', async function () { const lang = await cloudron.getLanguage(); - expect(lang).to.be('en'); + assert.equal(lang, 'en'); }); it('cannot set invalid language', async function () { const [error] = await safe(cloudron.setLanguage('ta')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot set valid language', async function () { await cloudron.setLanguage('de'); const lang = await cloudron.getLanguage(); - expect(lang).to.be('de'); + assert.equal(lang, 'de'); }); }); }); diff --git a/src/test/common.js b/src/test/common.js index b98898194..6c655aed5 100644 --- a/src/test/common.js +++ b/src/test/common.js @@ -6,7 +6,7 @@ import cron from '../cron.js'; import dashboard from '../dashboard.js'; import database from '../database.js'; import domains from '../domains.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import locks from '../locks.js'; import mailer from '../mailer.js'; @@ -238,7 +238,7 @@ function clearMailQueue() { async function checkMails(number) { await timers.setTimeout(1000); - expect(mailer._mailQueue.length).to.equal(number); + assert.equal(mailer._mailQueue.length, number); const emails = [...mailer._mailQueue]; // copy before clearing clearMailQueue(); diff --git a/src/test/database-test.js b/src/test/database-test.js index d7318d63f..e54e15a81 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -1,8 +1,8 @@ -/* global it, describe, before, after */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import database from '../database.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; describe('database', function () { @@ -26,7 +26,7 @@ describe('database', function () { it('basic query', async function () { const result = await database.query('SELECT COUNT(*) as count FROM apps'); - expect(result[0].count).to.be(0); + assert.equal(result[0].count, 0); }); it('bad queries', async function () { @@ -37,8 +37,8 @@ describe('database', function () { for (const query of queries) { const [error] = await safe(database.query(query)); - expect(error.reason).to.be(BoxError.DATABASE_ERROR); - expect(error.sqlMessage).to.be.a('string'); + assert.equal(error.reason, BoxError.DATABASE_ERROR); + assert.equal(typeof error.sqlMessage, 'string'); } }); }); @@ -52,8 +52,8 @@ describe('database', function () { { query: 'SELECT COUNT(*) as count FROM apps', args: [] }, { query: 'SELECT COUNT(*) as count FROM settings', args: [] }, ]); - expect(results[0][0].count).to.be(0); - expect(results[1][0].count).to.be(0); + assert.equal(results[0][0].count, 0); + assert.equal(results[1][0].count, 0); }); it('bad transaction', async function () { @@ -62,8 +62,8 @@ describe('database', function () { { query: 'stuff', args: [] }, ])); - expect(error.reason).to.be(BoxError.DATABASE_ERROR); - expect(error.sqlMessage).to.be.a('string'); + assert.equal(error.reason, BoxError.DATABASE_ERROR); + assert.equal(typeof error.sqlMessage, 'string'); }); }); @@ -75,7 +75,7 @@ describe('database', function () { it('cannot import from non-existent file', async function () { const [error] = await safe(database.importFromFile('/does/not/exist')); - expect(error).to.be.ok(); + assert.ok(error); }); it('can export to file', async function () { diff --git a/src/test/datalayout-test.js b/src/test/datalayout-test.js index 1acf995e6..bc92fd5a3 100644 --- a/src/test/datalayout-test.js +++ b/src/test/datalayout-test.js @@ -1,9 +1,8 @@ -/* global it:false */ +import { describe, it } from 'node:test'; import DataLayout from '../datalayout.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global describe:false */ describe('DataLayout', function () { describe('no dirMap', function () { @@ -11,28 +10,28 @@ describe('DataLayout', function () { const dataLayout = new DataLayout(BOX_DATA_DIR, []); it('localRoot', function () { - expect(dataLayout.localRoot()).to.be(BOX_DATA_DIR); + assert.equal(dataLayout.localRoot(), BOX_DATA_DIR); }); it('getBasename', function () { - expect(dataLayout.getBasename()).to.be('box'); + assert.equal(dataLayout.getBasename(), 'box'); }); it('localPaths', function () { - expect(dataLayout.localPaths()).to.eql([ BOX_DATA_DIR ]); + assert.deepEqual(dataLayout.localPaths(), [ BOX_DATA_DIR ]); }); it('toLocalPath', function () { - expect(dataLayout.toLocalPath('./s1')).to.be(`${BOX_DATA_DIR}/s1`); - expect(dataLayout.toLocalPath('./s1/')).to.be(`${BOX_DATA_DIR}/s1/`); - expect(dataLayout.toLocalPath('./s1/s2')).to.be(`${BOX_DATA_DIR}/s1/s2`); + assert.equal(dataLayout.toLocalPath('./s1'), `${BOX_DATA_DIR}/s1`); + assert.equal(dataLayout.toLocalPath('./s1/'), `${BOX_DATA_DIR}/s1/`); + assert.equal(dataLayout.toLocalPath('./s1/s2'), `${BOX_DATA_DIR}/s1/s2`); }); it('toRemotePath', function () { - expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}`)).to.be('./'); - expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1`)).to.be('./s1'); - expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/`)).to.be('./s1/'); - expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/s2`)).to.be('./s1/s2'); + assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}`), './'); + assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1`), './s1'); + assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/`), './s1/'); + assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/s2`), './s1/s2'); }); }); @@ -42,41 +41,41 @@ describe('DataLayout', function () { const dataLayout = new DataLayout(APP_DATA_DIR, [ { localDir: EXT_DIR, remoteDir: 'data' }]); it('localRoot', function () { - expect(dataLayout.localRoot()).to.be(APP_DATA_DIR); + assert.equal(dataLayout.localRoot(), APP_DATA_DIR); }); it('getBasename', function () { - expect(dataLayout.getBasename()).to.be('appid'); + assert.equal(dataLayout.getBasename(), 'appid'); }); it('localPaths', function () { - expect(dataLayout.localPaths()).to.eql([ APP_DATA_DIR, '/srv/hsb' ]); + assert.deepEqual(dataLayout.localPaths(), [ APP_DATA_DIR, '/srv/hsb' ]); }); it('toLocalPath - root', function () { - expect(dataLayout.toLocalPath('./s1')).to.be(`${APP_DATA_DIR}/s1`); - expect(dataLayout.toLocalPath('./s1/')).to.be(`${APP_DATA_DIR}/s1/`); - expect(dataLayout.toLocalPath('./s1/s2')).to.be(`${APP_DATA_DIR}/s1/s2`); + assert.equal(dataLayout.toLocalPath('./s1'), `${APP_DATA_DIR}/s1`); + assert.equal(dataLayout.toLocalPath('./s1/'), `${APP_DATA_DIR}/s1/`); + assert.equal(dataLayout.toLocalPath('./s1/s2'), `${APP_DATA_DIR}/s1/s2`); }); it('toLocalPath - extdir', function () { - expect(dataLayout.toLocalPath('./data/s1')).to.be(`${EXT_DIR}/s1`); - expect(dataLayout.toLocalPath('./data/s1/')).to.be(`${EXT_DIR}/s1/`); - expect(dataLayout.toLocalPath('./data/s1/s2')).to.be(`${EXT_DIR}/s1/s2`); + assert.equal(dataLayout.toLocalPath('./data/s1'), `${EXT_DIR}/s1`); + assert.equal(dataLayout.toLocalPath('./data/s1/'), `${EXT_DIR}/s1/`); + assert.equal(dataLayout.toLocalPath('./data/s1/s2'), `${EXT_DIR}/s1/s2`); }); it('toRemotePath - root', function () { - expect(dataLayout.toRemotePath(`${APP_DATA_DIR}`)).to.be('./'); - expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1`)).to.be('./s1'); - expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/`)).to.be('./s1/'); - expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/s2`)).to.be('./s1/s2'); + assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}`), './'); + assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1`), './s1'); + assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/`), './s1/'); + assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/s2`), './s1/s2'); }); it('toRemotePath - extdir', function () { - expect(dataLayout.toRemotePath(`${EXT_DIR}`)).to.be('./data/'); - expect(dataLayout.toRemotePath(`${EXT_DIR}/s1`)).to.be('./data/s1'); - expect(dataLayout.toRemotePath(`${EXT_DIR}/s1/`)).to.be('./data/s1/'); - expect(dataLayout.toRemotePath(`${EXT_DIR}/s1/s2`)).to.be('./data/s1/s2'); + assert.equal(dataLayout.toRemotePath(`${EXT_DIR}`), './data/'); + assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1`), './data/s1'); + assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1/`), './data/s1/'); + assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1/s2`), './data/s1/s2'); }); }); diff --git a/src/test/df-test.js b/src/test/df-test.js index d72847d7c..3e96e2143 100644 --- a/src/test/df-test.js +++ b/src/test/df-test.js @@ -1,14 +1,11 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import child_process from 'node:child_process'; import common from './common.js'; import df from '../df.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('df', function () { const { setup, cleanup } = common; @@ -21,8 +18,8 @@ describe('df', function () { if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return; const disks = await df.filesystems(); - expect(disks).to.be.ok(); - expect(disks.some(d => d.mountpoint === '/')).to.be.ok(); + assert.ok(disks); + assert.ok(disks.some(d => d.mountpoint === '/')); }); it('can get file', async function () { @@ -30,7 +27,7 @@ describe('df', function () { if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return; const disks = await df.file(import.meta.dirname); - expect(disks).to.be.ok(); - expect(disks.mountpoint).to.be('/home'); + assert.ok(disks); + assert.equal(disks.mountpoint, '/home'); }); }); diff --git a/src/test/directoryserver-test.js b/src/test/directoryserver-test.js index 5b6ab6107..06afaa4e7 100644 --- a/src/test/directoryserver-test.js +++ b/src/test/directoryserver-test.js @@ -1,20 +1,17 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import async from 'async'; import common from './common.js'; import constants from '../constants.js'; import directoryServer from '../directoryserver.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import groups from '../groups.js'; import ldap from 'ldapjs'; import safe from 'safetydance'; import speakeasy from 'speakeasy'; import users from '../users.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ async function ldapBind(dn, password) { return new Promise((resolve, reject) => { @@ -78,8 +75,8 @@ describe('Directory Server (LDAP)', function () { secret: 'ldapsecret' }; - before(function (done) { - async.series([ + before(async function () { + await async.series([ setup, directoryServer.start.bind(null), directoryServer.setConfig.bind(null, { enabled: true, secret: auth.secret, allowlist: '127.0.0.1' }, auditSource), @@ -91,14 +88,14 @@ describe('Directory Server (LDAP)', function () { group2 = await groups.add({ name: 'ldap-test-2' }, auditSource); await groups.setMembers(group2, [ admin.id ], {}, auditSource); } - ], done); + ]); }); - after(function (done) { - async.series([ + after(async function () { + await async.series([ directoryServer.stop, cleanup - ], done); + ]); }); describe('user bind', function () { @@ -106,12 +103,12 @@ describe('Directory Server (LDAP)', function () { it('cn= fails for nonexisting user', async function () { const [error] = await safe(ldapBind('cn=doesnotexist,ou=users,dc=cloudron', 'password')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('cn= fails with wrong password', async function () { const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, 'wrongpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('cn= succeeds with id', async function () { @@ -128,7 +125,7 @@ describe('Directory Server (LDAP)', function () { it('mail= fails with bad email', async function () { const [error] = await safe(ldapBind('mail=random,ou=users,dc=cloudron', admin.password)); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('mail= succeeds with email', async function () { @@ -147,8 +144,8 @@ describe('Directory Server (LDAP)', function () { it('totp check not requested - fails with bad password', async function () { const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, admin.password + 'random')); - expect(error).to.be.a(ldap.InvalidCredentialsError); - expect(error.lde_message).to.be('Wrong password'); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); + assert.equal(error.lde_message, 'Wrong password'); }); it('totp check not requested - succeeds with good password', async function () { @@ -157,8 +154,8 @@ describe('Directory Server (LDAP)', function () { it('totp check requested - fails with empty 2fa if user has 2fa', async function () { const [error] = await safe(ldapBind(`cn=${admin.id}+totptoken=,ou=users,dc=cloudron`, admin.password)); - expect(error).to.be.a(ldap.InvalidCredentialsError); - expect(error.lde_message).to.be('A totpToken must be provided'); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); + assert.equal(error.lde_message, 'A totpToken must be provided'); }); it('totp check requested - succeeds with empty 2fa if user has no 2fa', async function () { @@ -167,8 +164,8 @@ describe('Directory Server (LDAP)', function () { it('totp check requested - fails with invalid 2fa', async function () { const [error] = await safe(ldapBind(`cn=${admin.id}+totptoken=schlecht,ou=users,dc=cloudron`, admin.password)); - expect(error).to.be.a(ldap.InvalidCredentialsError); - expect(error.lde_message).to.be('Invalid totpToken'); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); + assert.equal(error.lde_message, 'Invalid totpToken'); }); it('totp check requested - succeeds with invalid 2fa if user has no 2fa', async function () { @@ -178,13 +175,13 @@ describe('Directory Server (LDAP)', function () { it('totp check requested - fails with bad password if user has 2fa', async function () { const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' }); const [error] = await safe(ldapBind(`cn=${admin.email}+totpToken=${totpToken},ou=users,dc=cloudron`, admin.password + 'random')); - expect(error.lde_message).to.be('Wrong password'); + assert.equal(error.lde_message, 'Wrong password'); }); it('totp check requested - fails with bad password if user has no 2fa', async function () { const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' }); const [error] = await safe(ldapBind(`cn=${admin.email}+totpToken=${totpToken},ou=users,dc=cloudron`, admin.password + 'random')); - expect(error.lde_message).to.be('Wrong password'); + assert.equal(error.lde_message, 'Wrong password'); }); it('totp check requested - succeeds with valid 2fa', async function () { @@ -196,158 +193,158 @@ describe('Directory Server (LDAP)', function () { describe('search users', function () { it('fails without auth', async function () { const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' })); - expect(error).to.be.a(ldap.InsufficientAccessRightsError); + assert.ok((error) instanceof (ldap.InsufficientAccessRightsError)); }); it('fails with wrong auth DN', async function () { const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, { dn: 'cn=doesnotexist,ou=system,dc=cloudron', secret: 'ldapsecret' })); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('fails with wrong auth secret', async function () { const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, { dn: 'cn=admin,ou=system,dc=cloudron', secret: 'wrongldapsecret' })); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('fails for non existing tree', async function () { const [error] = await safe(ldapSearch('o=example', { filter: '(&(l=Seattle)(email=*@' + domain.domain + '))' }, auth)); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('succeeds with basic filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].mail).to.equal(admin.email.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); - expect(entries[1].mail).to.equal(user.email.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].mail, admin.email.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); + assert.equal(entries[1].mail, user.email.toLowerCase()); }); it('succeeds with pagination', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person', paged: true }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].mail).to.equal(admin.email.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); - expect(entries[1].mail).to.equal(user.email.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].mail, admin.email.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); + assert.equal(entries[1].mail, user.email.toLowerCase()); }); it('succeeds with username wildcard filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=*)' }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); }); it('succeeds with username filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=' + admin.username + ')' }, auth); - expect(entries.length).to.equal(1); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].memberof.length).to.equal(2); + assert.equal(entries.length, 1); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].memberof.length, 2); }); }); describe('group search', function () { it('fails without auth', async function () { const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' })); - expect(error).to.be.a(ldap.InsufficientAccessRightsError); + assert.ok((error) instanceof (ldap.InsufficientAccessRightsError)); }); it('fails with wrong auth DN', async function () { const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' }, { dn: 'cn=doesnotexist,ou=system,dc=cloudron', secret: 'ldapsecret' })); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('fails with wrong auth secret', async function () { const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' }, { dn: 'cn=admin,ou=system,dc=cloudron', secret: 'wrongldapsecret' })); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('succeeds with basic filter', async function () { mockApp.accessRestriction = null; const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group' }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); - expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); + assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); }); it ('succeeds with cn wildcard filter', async function () { const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); - expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); + assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); }); it('succeeds with memberuid filter', async function () { const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(memberuid=' + user.id + ')' }, auth); - expect(entries.length).to.equal(1); + assert.equal(entries.length, 1); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); - expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); + assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); }); it ('succeeds with pagination', async function () { mockApp.accessRestriction = null; const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group', paged: true }, auth); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); - expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); + assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); - expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); - expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); + assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`)); + assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`)); }); }); }); diff --git a/src/test/dns-providers-test.js b/src/test/dns-providers-test.js index dd3a92b47..6dafb5279 100644 --- a/src/test/dns-providers-test.js +++ b/src/test/dns-providers-test.js @@ -1,18 +1,14 @@ +import { describe, it, before, after, beforeEach } from 'node:test'; /* jslint node:true */ import common from './common.js'; import dns from '../dns.js'; import domains from '../domains.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import { DNS as GCDNS } from '@google-cloud/dns'; import nock from 'nock'; import _ from '../underscore.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global beforeEach:false */ -/* global after:false */ describe('dns provider', function () { const { setup, cleanup, auditSource, domain } = common; @@ -36,7 +32,7 @@ describe('dns provider', function () { it('get succeeds', async function () { const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result.length).to.eql(0); + assert.deepEqual(result.length, 0); }); it('del succeeds', async function () { @@ -78,8 +74,8 @@ describe('dns provider', function () { .reply(201, { domain_record: DOMAIN_RECORD_0 }); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('upsert existing record succeeds', async function () { @@ -123,8 +119,8 @@ describe('dns provider', function () { .reply(200, { domain_record: DOMAIN_RECORD_1_NEW }); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', [DOMAIN_RECORD_1_NEW.data]); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('upsert multiple record succeeds', async function () { @@ -204,10 +200,10 @@ describe('dns provider', function () { .reply(201, { domain_record: DOMAIN_RECORD_2_NEW }); await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', [DOMAIN_RECORD_2_NEW.data, DOMAIN_RECORD_1_NEW.data, DOMAIN_RECORD_3_NEW.data]); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); - expect(req3.isDone()).to.be.ok(); - expect(req4.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); + assert.ok(req3.isDone()); + assert.ok(req4.isDone()); }); it('get succeeds', async function () { @@ -238,10 +234,10 @@ describe('dns provider', function () { .reply(200, { domain_records: [DOMAIN_RECORD_0, DOMAIN_RECORD_1] }); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(1); - expect(result[0]).to.eql(DOMAIN_RECORD_1.data); - expect(req1.isDone()).to.be.ok(); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 1); + assert.deepEqual(result[0], DOMAIN_RECORD_1.data); + assert.ok(req1.isDone()); }); it('del succeeds', async function () { @@ -275,8 +271,8 @@ describe('dns provider', function () { .reply(204, {}); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); }); @@ -307,7 +303,7 @@ describe('dns provider', function () { .reply(200, {}); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); + assert.ok(req1.isDone()); }); it('get succeeds', async function () { @@ -323,10 +319,10 @@ describe('dns provider', function () { .reply(200, DOMAIN_RECORD_0); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(1); - expect(result[0]).to.eql(DOMAIN_RECORD_0[0].data); - expect(req1.isDone()).to.be.ok(); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 1); + assert.deepEqual(result[0], DOMAIN_RECORD_0[0].data); + assert.ok(req1.isDone()); }); it('del succeeds', async function () { @@ -346,8 +342,8 @@ describe('dns provider', function () { .reply(204, {}); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); }); @@ -378,7 +374,7 @@ describe('dns provider', function () { .reply(201, { message: 'Zone Record Created' }); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); + assert.ok(req1.isDone()); }); it('get succeeds', async function () { @@ -396,10 +392,10 @@ describe('dns provider', function () { .reply(200, DOMAIN_RECORD_0); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(1); - expect(result[0]).to.eql(DOMAIN_RECORD_0.rrset_values[0]); - expect(req1.isDone()).to.be.ok(); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 1); + assert.deepEqual(result[0], DOMAIN_RECORD_0.rrset_values[0]); + assert.ok(req1.isDone()); }); it('del succeeds', async function () { @@ -410,7 +406,7 @@ describe('dns provider', function () { .reply(204, {}); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req2.isDone()).to.be.ok(); + assert.ok(req2.isDone()); }); }); @@ -447,8 +443,8 @@ describe('dns provider', function () { .reply(200, {}); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('get succeeds', async function () { @@ -466,10 +462,10 @@ describe('dns provider', function () { .reply(200, { records: [DOMAIN_RECORD_0] }); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(1); - expect(result[0]).to.eql(DOMAIN_RECORD_0.answer); - expect(req1.isDone()).to.be.ok(); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 1); + assert.deepEqual(result[0], DOMAIN_RECORD_0.answer); + assert.ok(req1.isDone()); }); it('del succeeds', async function () { @@ -492,8 +488,8 @@ describe('dns provider', function () { .reply(200, {}); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); }); @@ -593,8 +589,8 @@ describe('dns provider', function () { .reply(200, SET_HOSTS_RETURN); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('upsert multiple non-existing records succeeds', async function () { @@ -668,8 +664,8 @@ describe('dns provider', function () { .reply(200, SET_HOSTS_RETURN); await dns.upsertDnsRecords('test', domainCopy.domain, 'TXT', ['1.2.3.4', '2.3.4.5', '3.4.5.6']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('upsert existing record succeeds', async function () { @@ -728,8 +724,8 @@ describe('dns provider', function () { .reply(200, SET_HOSTS_RETURN); await dns.upsertDnsRecords('www', domainCopy.domain, 'CNAME', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('get succeeds', async function () { @@ -763,10 +759,10 @@ describe('dns provider', function () { .reply(200, GET_HOSTS_RETURN); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(req1.isDone()).to.be.ok(); - expect(result).to.be.an(Array); - expect(result.length).to.eql(2); - expect(result).to.eql(['1.2.3.4', '2.3.4.5']); + assert.ok(req1.isDone()); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 2); + assert.deepEqual(result, ['1.2.3.4', '2.3.4.5']); }); it('del succeeds', async function () { @@ -820,8 +816,8 @@ describe('dns provider', function () { .reply(200, SET_HOSTS_RETURN); await dns.removeDnsRecords('www', domainCopy.domain, 'CNAME', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); - expect(req2.isDone()).to.be.ok(); + assert.ok(req1.isDone()); + assert.ok(req2.isDone()); }); it('del succeeds with non-existing domain', async function () { @@ -854,7 +850,7 @@ describe('dns provider', function () { .reply(200, GET_HOSTS_RETURN); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(req1.isDone()).to.be.ok(); + assert.ok(req1.isDone()); }); }); @@ -899,7 +895,7 @@ describe('dns provider', function () { function mockery(queue) { return async function (options) { - expect(options).to.be.an(Object); + assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options)); const elem = queue.shift(); if (!Array.isArray(elem)) throw (new Error('Mock answer required')); @@ -909,11 +905,11 @@ describe('dns provider', function () { } function Route53Mock(cfg) { - expect(cfg.credentials).to.eql({ // retryDelayOptions is a function + assert.deepEqual(cfg.credentials, { // retryDelayOptions is a function accessKeyId: domainCopy.config.accessKeyId, secretAccessKey: domainCopy.config.secretAccessKey, }); - expect(cfg.region).to.be('us-east-1'); + assert.equal(cfg.region, 'us-east-1'); } Route53Mock.prototype.getHostedZone = mockery(awsAnswerQueue); Route53Mock.prototype.getChange = mockery(awsAnswerQueue); @@ -941,7 +937,7 @@ describe('dns provider', function () { }]); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(awsAnswerQueue.length).to.eql(0); + assert.deepEqual(awsAnswerQueue.length, 0); }); it('upsert existing record succeeds', async function () { @@ -955,7 +951,7 @@ describe('dns provider', function () { }]); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(awsAnswerQueue.length).to.eql(0); + assert.deepEqual(awsAnswerQueue.length, 0); }); it('upsert multiple record succeeds', async function () { @@ -969,7 +965,7 @@ describe('dns provider', function () { }]); await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', ['first', 'second', 'third']); - expect(awsAnswerQueue.length).to.eql(0); + assert.deepEqual(awsAnswerQueue.length, 0); }); it('get succeeds', async function () { @@ -985,10 +981,10 @@ describe('dns provider', function () { }]); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(1); - expect(result[0]).to.eql('1.2.3.4'); - expect(awsAnswerQueue.length).to.eql(0); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 1); + assert.deepEqual(result[0], '1.2.3.4'); + assert.deepEqual(awsAnswerQueue.length, 0); }); it('del succeeds', async function () { @@ -1002,7 +998,7 @@ describe('dns provider', function () { }]); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(awsAnswerQueue.length).to.eql(0); + assert.deepEqual(awsAnswerQueue.length, 0); }); }); @@ -1059,7 +1055,7 @@ describe('dns provider', function () { zoneQueue.push([null, { id: '1' }]); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(zoneQueue.length).to.eql(0); + assert.deepEqual(zoneQueue.length, 0); }); it('upsert existing record succeeds', async function () { @@ -1068,7 +1064,7 @@ describe('dns provider', function () { zoneQueue.push([null, { id: '2' }]); await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(zoneQueue.length).to.eql(0); + assert.deepEqual(zoneQueue.length, 0); }); it('upsert multiple record succeeds', async function () { @@ -1077,7 +1073,7 @@ describe('dns provider', function () { zoneQueue.push([null, { id: '3' }]); await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', ['first', 'second', 'third']); - expect(zoneQueue.length).to.eql(0); + assert.deepEqual(zoneQueue.length, 0); }); it('get succeeds', async function () { @@ -1085,10 +1081,10 @@ describe('dns provider', function () { zoneQueue.push([null, [new GCDNS().zone('test').record('A', { 'name': 'test', data: ['1.2.3.4', '5.6.7.8'], ttl: 1 })]]); const result = await dns.getDnsRecords('test', domainCopy.domain, 'A'); - expect(result).to.be.an(Array); - expect(result.length).to.eql(2); - expect(result).to.eql(['1.2.3.4', '5.6.7.8']); - expect(zoneQueue.length).to.eql(0); + assert.ok(Array.isArray(result)); + assert.deepEqual(result.length, 2); + assert.deepEqual(result, ['1.2.3.4', '5.6.7.8']); + assert.deepEqual(zoneQueue.length, 0); }); it('del succeeds', async function () { @@ -1097,7 +1093,7 @@ describe('dns provider', function () { zoneQueue.push([null, { id: '5' }]); await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']); - expect(zoneQueue.length).to.eql(0); + assert.deepEqual(zoneQueue.length, 0); }); }); }); diff --git a/src/test/dns-test.js b/src/test/dns-test.js index 8c9af9cd4..838be6ffb 100644 --- a/src/test/dns-test.js +++ b/src/test/dns-test.js @@ -1,12 +1,9 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import dns from '../dns.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('DNS', function () { const { setup, cleanup, app, domain:domainObject } = common; @@ -19,34 +16,34 @@ describe('DNS', function () { describe('validateHostname', function () { it('cannot have >63 length subdomains', function () { const s = Array(64).fill('s').join(''); - expect(dns.validateHostname(s, domain)).to.be.an(Error); - expect(dns.validateHostname(`dev.${s}`, domain)).to.be.an(Error); + assert.ok((dns.validateHostname(s, domain)) instanceof (Error)); + assert.ok((dns.validateHostname(`dev.${s}`, domain)) instanceof (Error)); }); it('allows only alphanumerics and hypen', function () { - expect(dns.validateHostname('#2r', domain)).to.be.an(Error); - expect(dns.validateHostname('a%b', domain)).to.be.an(Error); - expect(dns.validateHostname('ab_', domain)).to.be.an(Error); - expect(dns.validateHostname('ab.', domain)).to.be.an(Error); - expect(dns.validateHostname('ab..c', domain)).to.be.an(Error); - expect(dns.validateHostname('.ab', domain)).to.be.an(Error); - expect(dns.validateHostname('-ab', domain)).to.be.an(Error); - expect(dns.validateHostname('ab-', domain)).to.be.an(Error); + assert.ok((dns.validateHostname('#2r', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('a%b', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('ab_', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('ab.', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('ab..c', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('.ab', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('-ab', domain)) instanceof (Error)); + assert.ok((dns.validateHostname('ab-', domain)) instanceof (Error)); }); it('total length cannot exceed 255', function () { let s = ''; for (let i = 0; i < (255 - 'example.com'.length); i++) s += 's'; - expect(dns.validateHostname(s, domain)).to.be.an(Error); + assert.ok((dns.validateHostname(s, domain)) instanceof (Error)); }); it('allow valid domains', function () { - expect(dns.validateHostname('a', domain)).to.be(null); - expect(dns.validateHostname('a0-x', domain)).to.be(null); - expect(dns.validateHostname('a0.x', domain)).to.be(null); - expect(dns.validateHostname('a0.x.y', domain)).to.be(null); - expect(dns.validateHostname('01', domain)).to.be(null); + assert.equal(dns.validateHostname('a', domain), null); + assert.equal(dns.validateHostname('a0-x', domain), null); + assert.equal(dns.validateHostname('a0.x', domain), null); + assert.equal(dns.validateHostname('a0.x.y', domain), null); + assert.equal(dns.validateHostname('01', domain), null); }); }); @@ -58,15 +55,15 @@ describe('DNS', function () { config: {} }; - expect(dns.getName(d, '', 'A')).to.be(''); - expect(dns.getName(d, 'www', 'A')).to.be('www'); - expect(dns.getName(d, 'www.dev', 'A')).to.be('www.dev'); + assert.equal(dns.getName(d, '', 'A'), ''); + assert.equal(dns.getName(d, 'www', 'A'), 'www'); + assert.equal(dns.getName(d, 'www.dev', 'A'), 'www.dev'); - expect(dns.getName(d, '', 'MX')).to.be(''); + assert.equal(dns.getName(d, '', 'MX'), ''); - expect(dns.getName(d, '', 'TXT')).to.be(''); - expect(dns.getName(d, 'www', 'TXT')).to.be('www'); - expect(dns.getName(d, 'www.dev', 'TXT')).to.be('www.dev'); + assert.equal(dns.getName(d, '', 'TXT'), ''); + assert.equal(dns.getName(d, 'www', 'TXT'), 'www'); + assert.equal(dns.getName(d, 'www.dev', 'TXT'), 'www.dev'); }); it('works when zoneName!=domain', function () { @@ -76,15 +73,15 @@ describe('DNS', function () { config: {} }; - expect(dns.getName(d, '', 'A')).to.be('dev'); - expect(dns.getName(d, 'www', 'A')).to.be('www.dev'); - expect(dns.getName(d, 'www.dev', 'A')).to.be('www.dev.dev'); + assert.equal(dns.getName(d, '', 'A'), 'dev'); + assert.equal(dns.getName(d, 'www', 'A'), 'www.dev'); + assert.equal(dns.getName(d, 'www.dev', 'A'), 'www.dev.dev'); - expect(dns.getName(d, '', 'MX')).to.be('dev'); + assert.equal(dns.getName(d, '', 'MX'), 'dev'); - expect(dns.getName(d, '', 'TXT')).to.be('dev'); - expect(dns.getName(d, 'www', 'TXT')).to.be('www.dev'); - expect(dns.getName(d, 'www.dev', 'TXT')).to.be('www.dev.dev'); + assert.equal(dns.getName(d, '', 'TXT'), 'dev'); + assert.equal(dns.getName(d, 'www', 'TXT'), 'www.dev'); + assert.equal(dns.getName(d, 'www.dev', 'TXT'), 'www.dev.dev'); }); }); diff --git a/src/test/docker-test.js b/src/test/docker-test.js index 906d91b27..754ccaef0 100644 --- a/src/test/docker-test.js +++ b/src/test/docker-test.js @@ -1,14 +1,11 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; import docker from '../docker.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; -/* global it:false */ -/* global before:false */ -/* global after:false */ -/* global describe:false */ describe('docker', function () { const { setup, cleanup } = common; @@ -22,15 +19,15 @@ describe('docker', function () { it('can df', async function () { const output = await docker.df({}); - expect(output).to.be.ok(); + assert.ok(output); }); it('parseImageRef', async function () { - expect(docker.parseImageRef('cloudron/base')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: null }); - expect(docker.parseImageRef('cloudron/base:4.2.0')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: null }); - expect(docker.parseImageRef('cloudron/base@sha256:xx')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: 'xx' }); - expect(docker.parseImageRef('cloudron/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: 'xx' }); - expect(docker.parseImageRef('registry.com/cloudron/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'registry.com/cloudron/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); - expect(docker.parseImageRef('registry.com/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'registry.com/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); // optional namespace + assert.deepEqual(docker.parseImageRef('cloudron/base'), { fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: null }); + assert.deepEqual(docker.parseImageRef('cloudron/base:4.2.0'), { fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: null }); + assert.deepEqual(docker.parseImageRef('cloudron/base@sha256:xx'), { fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: 'xx' }); + assert.deepEqual(docker.parseImageRef('cloudron/base:4.2.0@sha256:xx'), { fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: 'xx' }); + assert.deepEqual(docker.parseImageRef('registry.com/cloudron/base:4.2.0@sha256:xx'), { fullRepositoryName: 'registry.com/cloudron/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); + assert.deepEqual(docker.parseImageRef('registry.com/base:4.2.0@sha256:xx'), { fullRepositoryName: 'registry.com/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); // optional namespace }); }); diff --git a/src/test/dockerproxy-test.js b/src/test/dockerproxy-test.js index e9e3e2e64..c96aac473 100644 --- a/src/test/dockerproxy-test.js +++ b/src/test/dockerproxy-test.js @@ -1,18 +1,14 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import child_process from 'node:child_process'; import common from './common.js'; import constants from '../constants.js'; import dockerProxy from '../dockerproxy.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import syslogServer from '../../syslog.js'; -/* global it:false */ -/* global xit:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ const DOCKER = `docker -H tcp://172.18.0.1:${constants.DOCKER_PROXY_PORT} `; @@ -55,39 +51,33 @@ describe('Dockerproxy', function () { it('can get info', async function () { const stdout = await exec(DOCKER + ' info'); - expect(stdout).to.contain('Containers:'); - // expect(stderr).to.be.empty(); // on some machines, i get 'No swap limit support' + assert.ok(stdout.includes('Containers:')); + // assert.equal((stderr).length, 0); // on some machines, i get 'No swap limit support' }); it('can create container', async function () { const cmd = `${DOCKER} run ${BASE_IMAGE} "/bin/bash" "-c" "echo 'hello'"`; const stdout = await exec(cmd); - expect(stdout).to.contain('hello'); + assert.ok(stdout.includes('hello')); }); it('proxy overwrites the container network option', async function () { const cmd = `${DOCKER} run --network ifnotrewritethiswouldfail ${BASE_IMAGE} "/bin/bash" "-c" "echo 'hello'"`; const stdout = await exec(cmd); - expect(stdout).to.contain('hello'); + assert.ok(stdout.includes('hello')); }); - xit('cannot see logs through docker logs, since syslog is configured', function (done) { - exec(`${DOCKER} logs ${containerId}`, function (error, stdout, stderr) { - expect(error.message).to.contain('configured logging driver does not support reading'); - expect(stderr).to.contain('configured logging driver does not support reading'); - expect(stdout).to.be.empty(); - - done(); - }); + it.skip('cannot see logs through docker logs, since syslog is configured', async function () { + // kept skipped: docker logs output differs by host and logging driver }); it('can use PUT to upload archive into a container', async function () { const stdout = await exec(`${DOCKER} cp ${import.meta.dirname}/proxytestarchive.tar ${containerId}:/tmp/`); - expect(stdout).to.be.empty(); + assert.equal((stdout).length, 0); }); it('can exec into a container', async function () { const stdout = await exec(`${DOCKER} exec ${containerId} ls`); - expect(stdout).to.equal('bin\nboot\ndev\netc\nhome\nlib\nlib32\nlib64\nlibx32\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n'); + assert.equal(stdout, 'bin\nboot\ndev\netc\nhome\nlib\nlib32\nlib64\nlibx32\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n'); }); }); diff --git a/src/test/dockerregistries-test.js b/src/test/dockerregistries-test.js index 3bc6a193f..c562517b8 100644 --- a/src/test/dockerregistries-test.js +++ b/src/test/dockerregistries-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import dockerRegistries from '../dockerregistries.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Docker Registries', function () { const { setup, cleanup, auditSource } = common; @@ -21,45 +18,45 @@ describe('Docker Registries', function () { it('cannot get random', async function () { const registry = await dockerRegistries.get('srandom'); - expect(registry).to.be(null); + assert.equal(registry, null); }); it('can add', async function () { id = await dockerRegistries.add({ provider: 'devops', serverAddress: 'registry.devops.test', password: 'hushhush' }, auditSource); - expect(id).to.be.a('string'); + assert.equal(typeof id, 'string'); }); it('can get', async function () { const registry = await dockerRegistries.get(id); - expect(registry.provider).to.be('devops'); - expect(registry.serverAddress).to.be('registry.devops.test'); - expect(registry.password).to.be('hushhush'); + assert.equal(registry.provider, 'devops'); + assert.equal(registry.serverAddress, 'registry.devops.test'); + assert.equal(registry.password, 'hushhush'); }); it('can list', async function () { const registries = await dockerRegistries.list(); - expect(registries.length).to.be(1); - expect(registries[0].provider).to.be('devops'); - expect(registries[0].serverAddress).to.be('registry.devops.test'); - expect(registries[0].password).to.be('hushhush'); + assert.equal(registries.length, 1); + assert.equal(registries[0].provider, 'devops'); + assert.equal(registries[0].serverAddress, 'registry.devops.test'); + assert.equal(registries[0].password, 'hushhush'); }); it('can update', async function () { await dockerRegistries.update(await dockerRegistries.get(id), { provider: 'cicd', serverAddress: 'registry.cicd' }, auditSource); const registry = await dockerRegistries.get(id); - expect(registry.provider).to.be('cicd'); - expect(registry.serverAddress).to.be('registry.cicd'); - expect(registry.password).to.be('hushhush'); // injected from the older one + assert.equal(registry.provider, 'cicd'); + assert.equal(registry.serverAddress, 'registry.cicd'); + assert.equal(registry.password, 'hushhush'); // injected from the older one }); it('can del', async function () { await dockerRegistries.del(await dockerRegistries.get(id), auditSource); const registries = await dockerRegistries.list(); - expect(registries.length).to.be(0); + assert.equal(registries.length, 0); }); it('cannot del random', async function () { const [error] = await safe(dockerRegistries.del({ id: 'fake' }, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); diff --git a/src/test/domains-test.js b/src/test/domains-test.js index ad0c20c14..1e26f1bc5 100644 --- a/src/test/domains-test.js +++ b/src/test/domains-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import apps from '../apps.js'; import BoxError from '../boxerror.js'; import common from './common.js'; import domains from '../domains.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Domains', function () { const { setup, cleanup, domain, app, auditSource } = common; @@ -36,19 +33,19 @@ describe('Domains', function () { it('cannot add same domain twice', async function () { const [error] = await safe(domains.add(DOMAIN_0.domain, DOMAIN_0, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('can get domain', async function () { const result = await domains.get(DOMAIN_0.domain); - expect(result.domain).to.equal(DOMAIN_0.domain); - expect(result.zoneName).to.equal(DOMAIN_0.zoneName); - expect(result.config).to.eql(DOMAIN_0.config); + assert.equal(result.domain, DOMAIN_0.domain); + assert.equal(result.zoneName, DOMAIN_0.zoneName); + assert.deepEqual(result.config, DOMAIN_0.config); }); it('cannot get non-existent domain', async function () { const result = await domains.get('random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can set domain config', async function () { @@ -59,11 +56,11 @@ describe('Domains', function () { await domains.setConfig(DOMAIN_0.domain, newDomain, auditSource); const result = await domains.get(DOMAIN_0.domain); - expect(result.domain).to.equal(DOMAIN_0.domain); - expect(result.zoneName).to.equal(DOMAIN_0.zoneName); - expect(result.provider).to.equal(DOMAIN_0.provider); - expect(result.config).to.eql(newConfig); - expect(result.tlsConfig).to.eql(newTlsConfig); + assert.equal(result.domain, DOMAIN_0.domain); + assert.equal(result.zoneName, DOMAIN_0.zoneName); + assert.equal(result.provider, DOMAIN_0.provider); + assert.deepEqual(result.config, newConfig); + assert.deepEqual(result.tlsConfig, newTlsConfig); DOMAIN_0.config = newConfig; DOMAIN_0.tlsConfig = newTlsConfig; @@ -72,42 +69,42 @@ describe('Domains', function () { it('can set domain wellknown', async function () { await domains.setWellKnown(DOMAIN_0.domain, { service: 'some.service' }, auditSource); let result = await domains.get(DOMAIN_0.domain); - expect(result.wellKnown).to.eql({ service: 'some.service' }); + assert.deepEqual(result.wellKnown, { service: 'some.service' }); await domains.setWellKnown(DOMAIN_0.domain, null, auditSource); result = await domains.get(DOMAIN_0.domain); - expect(result.wellKnown).to.eql(null); + assert.deepEqual(result.wellKnown, null); }); it('can get all domains', async function () { const result = await domains.list(); - expect(result.length).to.equal(2); + assert.equal(result.length, 2); // sorted by domain - expect(result[0].domain).to.equal(domain.domain); - expect(result[0].zoneName).to.equal(domain.zoneName); - expect(result[0].provider).to.equal(domain.provider); - expect(result[0].config).to.eql(domain.config); - expect(result[0].tlsConfig).to.eql(domain.tlsConfig); + assert.equal(result[0].domain, domain.domain); + assert.equal(result[0].zoneName, domain.zoneName); + assert.equal(result[0].provider, domain.provider); + assert.deepEqual(result[0].config, domain.config); + assert.deepEqual(result[0].tlsConfig, domain.tlsConfig); - expect(result[1].domain).to.equal(DOMAIN_0.domain); - expect(result[1].zoneName).to.equal(DOMAIN_0.zoneName); - expect(result[1].provider).to.equal(DOMAIN_0.provider); - expect(result[1].config).to.eql(DOMAIN_0.config); - expect(result[1].tlsConfig).to.eql(DOMAIN_0.tlsConfig); + assert.equal(result[1].domain, DOMAIN_0.domain); + assert.equal(result[1].zoneName, DOMAIN_0.zoneName); + assert.equal(result[1].provider, DOMAIN_0.provider); + assert.deepEqual(result[1].config, DOMAIN_0.config); + assert.deepEqual(result[1].tlsConfig, DOMAIN_0.tlsConfig); }); it('cannot delete non-existing domain', async function () { const [error] = await safe(domains.del('not.exists', auditSource)); - expect(error).to.be.a(BoxError); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.ok((error) instanceof (BoxError)); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('cannot delete dashboard domain', async function () { const [error] = await safe(domains.del(domain.domain, auditSource)); - expect(error).to.be.a(BoxError); - expect(error.reason).to.equal(BoxError.CONFLICT); - expect(error.message).to.equal('Cannot remove admin domain'); + assert.ok((error) instanceof (BoxError)); + assert.equal(error.reason, BoxError.CONFLICT); + assert.equal(error.message, 'Cannot remove admin domain'); }); it('cannot delete referenced domain', async function () { @@ -116,8 +113,8 @@ describe('Domains', function () { await apps.add(appCopy.id, appCopy.appStoreId, '', appCopy.manifest, appCopy.subdomain, appCopy.domain, appCopy.portBindings, appCopy); const [error] = await safe(domains.del(DOMAIN_0.domain, auditSource)); - expect(error.reason).to.equal(BoxError.CONFLICT); - expect(error.message).to.contain('Domain is in use in an app\'s location'); + assert.equal(error.reason, BoxError.CONFLICT); + assert.ok(error.message.includes('Domain is in use in an app\'s location')); await apps.del(appCopy.id); }); @@ -126,6 +123,6 @@ describe('Domains', function () { await domains.del(DOMAIN_0.domain, auditSource); const result = await domains.get(DOMAIN_0.domain); - expect(result).to.be(null); + assert.equal(result, null); }); }); diff --git a/src/test/eventlog-test.js b/src/test/eventlog-test.js index be22c7d51..948afa537 100644 --- a/src/test/eventlog-test.js +++ b/src/test/eventlog-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; import database from '../database.js'; import eventlog from '../eventlog.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import notifications from '../notifications.js'; import timers from 'timers/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Eventlog', function () { const { setup, cleanup } = common; @@ -26,55 +23,55 @@ describe('Eventlog', function () { it('add succeeds', async function () { const id = await eventlog.add('some.event', { ip: '1.2.3.4' }, { appId: 'thatapp' }); - expect(id).to.be.a('string'); + assert.equal(typeof id, 'string'); eventId = id; }); it('get succeeds', async function () { const result = await eventlog.get(eventId); - expect(result.id).to.be(eventId); - expect(result.action).to.be('some.event'); - expect(result.creationTime).to.be.a(Date); + assert.equal(result.id, eventId); + assert.equal(result.action, 'some.event'); + assert.ok((result.creationTime) instanceof (Date)); - expect(result.source).to.be.eql({ ip: '1.2.3.4' }); - expect(result.data).to.be.eql({ appId: 'thatapp' }); + assert.deepEqual(result.source, { ip: '1.2.3.4' }); + assert.deepEqual(result.data, { appId: 'thatapp' }); }); it('get of unknown id fails', async function () { const result = await eventlog.get('notfoundid'); - expect(result).to.be(null); + assert.equal(result, null); }); it('listPaged succeeds', async function () { const results = await eventlog.listPaged({ actions: [], search: null }, 1, 1); - expect(results).to.be.an(Array); - expect(results.length).to.be(1); + assert.ok(Array.isArray(results)); + assert.equal(results.length, 1); - expect(results[0].id).to.be(eventId); - expect(results[0].action).to.be('some.event'); - expect(results[0].source).to.be.eql({ ip: '1.2.3.4' }); - expect(results[0].data).to.be.eql({ appId: 'thatapp' }); + assert.equal(results[0].id, eventId); + assert.equal(results[0].action, 'some.event'); + assert.deepEqual(results[0].source, { ip: '1.2.3.4' }); + assert.deepEqual(results[0].data, { appId: 'thatapp' }); }); it('listPaged succeeds with source search', async function () { const results = await eventlog.listPaged({ actions: [], search: '1.2.3.4' }, 1, 1); - expect(results).to.be.an(Array); - expect(results.length).to.be(1); - expect(results[0].id).to.be(eventId); - expect(results[0].action).to.be('some.event'); - expect(results[0].source).to.be.eql({ ip: '1.2.3.4' }); - expect(results[0].data).to.be.eql({ appId: 'thatapp' }); + assert.ok(Array.isArray(results)); + assert.equal(results.length, 1); + assert.equal(results[0].id, eventId); + assert.equal(results[0].action, 'some.event'); + assert.deepEqual(results[0].source, { ip: '1.2.3.4' }); + assert.deepEqual(results[0].data, { appId: 'thatapp' }); }); it('listPaged succeeds with data search', async function () { const results = await eventlog.listPaged({ actions: [], search: 'thatapp' }, 1, 1); - expect(results).to.be.an(Array); - expect(results.length).to.be(1); - expect(results[0].id).to.be(eventId); - expect(results[0].action).to.be('some.event'); - expect(results[0].source).to.be.eql({ ip: '1.2.3.4' }); - expect(results[0].data).to.be.eql({ appId: 'thatapp' }); + assert.ok(Array.isArray(results)); + assert.equal(results.length, 1); + assert.equal(results[0].id, eventId); + assert.equal(results[0].action, 'some.event'); + assert.deepEqual(results[0].source, { ip: '1.2.3.4' }); + assert.deepEqual(results[0].data, { appId: 'thatapp' }); }); it('listPaged succeeds with from/to time filter', async function () { @@ -84,9 +81,9 @@ describe('Eventlog', function () { const to = new Date(creationTime.getTime() + 60000); // 1 min after const results = await eventlog.listPaged({ actions: [], search: null, from, to }, 1, 10); - expect(results).to.be.an(Array); - expect(results.length).to.be.above(0); - expect(results.some((r) => r.id === eventId)).to.be(true); + assert.ok(Array.isArray(results)); + assert.ok((results.length) > (0)); + assert.equal(results.some((r) => r.id === eventId), true); }); it('listPaged returns empty with from after event', async function () { @@ -94,13 +91,13 @@ describe('Eventlog', function () { const from = new Date(event.creationTime.getTime() + 86400000); // 1 day after const results = await eventlog.listPaged({ actions: [], search: null, from }, 1, 10); - expect(results.some((r) => r.id === eventId)).to.be(false); + assert.equal(results.some((r) => r.id === eventId), false); }); let loginEventId; it('upsert with no existing entry succeeds', async function () { const result = await eventlog.upsertLoginEvent('user.login', { ip: '1.2.3.4' }, { appId: 'thatapp' }); - expect(result).to.be.a('string'); + assert.equal(typeof result, 'string'); loginEventId = result; }); @@ -110,11 +107,11 @@ describe('Eventlog', function () { await timers.setTimeout(2000); result = await eventlog.upsertLoginEvent('user.login', { ip: '1.2.3.4' }, { appId: 'thatapp' }); - expect(result).to.equal(loginEventId); + assert.equal(result, loginEventId); result = await eventlog.get(loginEventId); // should have changed - expect(oldCreationTime).to.not.equal(result.creationTime); + assert.notEqual(oldCreationTime, result.creationTime); }); it('upsert with existing old entry succeeds', async function () { @@ -124,7 +121,7 @@ describe('Eventlog', function () { await database.query('INSERT INTO eventlog (id, action, sourceJson, dataJson, creationTime) VALUES (?, ?, ?, ?, ?)', [ 'anotherid', 'user.login2', JSON.stringify({ ip: '1.2.3.4' }), JSON.stringify({ appId: 'thatapp' }), yesterday ]); const result = await eventlog.upsertLoginEvent('user.login2', { ip: '1.2.3.4' }, { appId: 'thatapp' }); - expect(result).to.not.equal('anotherid'); + assert.notEqual(result, 'anotherid'); }); it('cleans up', async function () { @@ -142,13 +139,13 @@ describe('Eventlog', function () { await eventlog.cleanup({ creationTime: new Date(Date.now() - 1000) }); // 1 second ago let results = await eventlog.listPaged({ actions: [], search: null }, 1, 100); - expect(results.length).to.be(1); + assert.equal(results.length, 1); - expect(results[0].id).to.be(id); - expect(results[0].action).to.be(eventlog.ACTION_USER_LOGIN); - expect(results[0].creationTime).to.be.a(Date); + assert.equal(results[0].id, id); + assert.equal(results[0].action, eventlog.ACTION_USER_LOGIN); + assert.ok((results[0].creationTime) instanceof (Date)); results = await notifications.list({}, 1, 10); - expect(results.length).to.be(0); + assert.equal(results.length, 0); }); }); diff --git a/src/test/externalldap-test.js b/src/test/externalldap-test.js index 7b0c868f4..0692fe7e8 100644 --- a/src/test/externalldap-test.js +++ b/src/test/externalldap-test.js @@ -1,18 +1,15 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import async from 'async'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import externalLdap from '../externalldap.js'; import groups from '../groups.js'; import ldap from 'ldapjs'; import safe from 'safetydance'; import users from '../users.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ const LDAP_SHARED_PASSWORD = 'validpassword'; const LDAP_SHARED_TOTP_TOKEN = '1234'; @@ -221,18 +218,18 @@ describe('External LDAP', function () { const { setup, cleanup, admin, auditSource } = common; const ldapServer = new LdapServer(LDAP_CONFIG.provider); - before(function (done) { - async.series([ + before(async function () { + await async.series([ ldapServer.start.bind(ldapServer), setup - ], done); + ]); }); - after(function (done) { - async.series([ + after(async function () { + await async.series([ ldapServer.stop.bind(ldapServer), cleanup - ], done); + ]); }); describe('settings', function () { @@ -241,7 +238,7 @@ describe('External LDAP', function () { delete conf.url; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling fails with empty url', async function () { @@ -249,7 +246,7 @@ describe('External LDAP', function () { conf.url = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling fails with missing baseDn', async function () { @@ -257,7 +254,7 @@ describe('External LDAP', function () { delete conf.baseDn; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling fails with empty baseDn', async function () { @@ -265,7 +262,7 @@ describe('External LDAP', function () { conf.baseDn = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling fails with missing filter', async function () { @@ -273,7 +270,7 @@ describe('External LDAP', function () { delete conf.filter; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling fails with empty filter', async function () { @@ -281,7 +278,7 @@ describe('External LDAP', function () { conf.filter = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling succeeds', async function () { @@ -299,7 +296,7 @@ describe('External LDAP', function () { delete conf.groupBaseDn; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups fails with empty groupBaseDn', async function () { @@ -308,7 +305,7 @@ describe('External LDAP', function () { conf.groupBaseDn = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups fails with missing groupFilter', async function () { @@ -317,7 +314,7 @@ describe('External LDAP', function () { delete conf.groupFilter; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups fails with empty groupFilter', async function () { @@ -326,7 +323,7 @@ describe('External LDAP', function () { conf.groupFilter = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups fails with missing groupnameField', async function () { @@ -335,7 +332,7 @@ describe('External LDAP', function () { delete conf.groupnameField; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups fails with empty groupnameField', async function () { @@ -344,7 +341,7 @@ describe('External LDAP', function () { conf.groupnameField = ''; const [error] = await safe(externalLdap.setConfig(conf, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('enabling with groups succeeds', async function () { @@ -367,17 +364,17 @@ describe('External LDAP', function () { it('fails for unknown user', async function () { const [error] = await safe(externalLdap.verifyPassword('badusername', 'badpassword', {})); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails for bad password', async function () { const [error] = await safe(externalLdap.verifyPassword('maximus', 'badpassword', {})); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds for valid password', async function () { const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, {}); - expect(u.username).to.be('maximus'); + assert.equal(u.username, 'maximus'); }); }); @@ -396,12 +393,12 @@ describe('External LDAP', function () { it('succeeds when skip totp', async function () { const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: true }); - expect(u.username).to.be('maximus'); + assert.equal(u.username, 'maximus'); }); it('succeeds when not skipping totp since totpToken is ignored for non-cloudron provider', async function () { const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: 'random' }); - expect(u.username).to.be('maximus'); + assert.equal(u.username, 'maximus'); }); }); @@ -420,22 +417,22 @@ describe('External LDAP', function () { it('succeeds when skip totp (e.g. some cloudron app)', async function () { const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: true }); - expect(u.username).to.be('maximus'); + assert.equal(u.username, 'maximus'); }); it('fails when not skipping totp (e.g. cloudron dashboard)', async function () { const [error] = await safe(externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: 'badtotp' })); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('fails when totp required and empty totp (e.g cloudron dashboard)', async function () { const [error] = await safe(externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: '' })); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds when totp required and good totp', async function () { const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: LDAP_SHARED_TOTP_TOKEN }); - expect(u.username).to.be('maximus'); + assert.equal(u.username, 'maximus'); }); }); }); @@ -454,7 +451,7 @@ describe('External LDAP', function () { it('fails if disabled', async function () { const [error] = await safe(externalLdap.sync(function progress() {})); - expect(error.reason).to.equal(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('enable', async function () { @@ -470,9 +467,9 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.username === 'firstuser' && u.email === 'first@user.com' && u.displayName === 'First User' && u.source === 'ldap'; - })).to.be.ok(); + })); }); it('succeeds for updated users', async function () { @@ -481,9 +478,9 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.username === 'firstuser' && u.email === 'first@changed.com' && u.displayName === 'User First' && u.source === 'ldap'; - })).to.be.ok(); + })); }); it('maps already existing users with same username', async function () { @@ -495,9 +492,9 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.email === 'foobar@bar.com' || u.displayName === 'Something Else'; - })).to.be.ok(); + })); }); it('does not sync group if group sync is disabled', async function () { @@ -507,7 +504,7 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.list(); - expect(result.length).to.equal(0); + assert.equal(result.length, 0); ldapGroups.splice(0, 1); // clear the group in-place }); @@ -525,7 +522,7 @@ describe('External LDAP', function () { it('succeeds with groups enabled', async function () { await externalLdap.sync(function progress() {}); const result = await groups.list(); - expect(result.length).to.equal(0); + assert.equal(result.length, 0); }); it('succeeds with groups enabled and new group', async function () { @@ -535,9 +532,9 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.list(); - expect(result.find(function (g) { + assert.ok(result.find(function (g) { return g.name === 'extgroup1' && g.source === 'ldap'; - })).to.be.ok(); + })); }); it('succeeds with groups enabled and second new group', async function () { @@ -547,10 +544,10 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.list(); - expect(result.length).to.be(2); - expect(result.find(function (g) { + assert.equal(result.length, 2); + assert.ok(result.find(function (g) { return g.name === 'extgroup2' && g.source === 'ldap'; - })).to.be.ok(); + })); }); it('does not create or change already existing group', async function () { @@ -562,10 +559,10 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.list(); - expect(result.length).to.equal(3); - expect(result.find(function (g) { + assert.equal(result.length, 3); + assert.ok(result.find(function (g) { return g.name === 'internalgroup' && g.source === 'ldap'; // source is updated to LDAP - })).to.be.ok(); + })); }); it('adds users of groups', async function () { @@ -576,10 +573,10 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.getByName('nonemptygroup'); - expect(result).to.be.ok(); + assert.ok(result); const result2 = await groups.getMemberIds(result.id); - expect(result2.length).to.equal(2); + assert.equal(result2.length, 2); }); it('adds new users of groups', async function () { @@ -590,10 +587,10 @@ describe('External LDAP', function () { await externalLdap.sync(function progress() {}); const result = await groups.getByName('nonemptygroup'); - expect(result).to.be.ok(); + assert.ok(result); const result2 = await groups.getMemberIds(result.id); - expect(result2.length).to.equal(2); + assert.equal(result2.length, 2); }); it('succeeds with only one group member (string instead of array)', async function () { @@ -606,16 +603,16 @@ describe('External LDAP', function () { const result = await groups.getByName('onemembergroup'); const result2 = await groups.getMemberIds(result.id); - expect(result2.length).to.equal(1); + assert.equal(result2.length, 1); const u = await users.get(result2[0]); - expect(u.username).to.equal(ldapUsers[0].username); + assert.equal(u.username, ldapUsers[0].username); }); it('cannot update profile of external user', async function () { const user = await users.getByUsername(ldapUsers[0].username); const [error] = await safe(users.updateProfile(user, { displayName: 'another name'}, auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); }); @@ -639,10 +636,10 @@ describe('External LDAP', function () { }); const [error] = await safe(users.verifyWithUsername('autologinuser0', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {})); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.username === 'autologinuser0'; })).to.not.be.ok(); }); @@ -655,12 +652,12 @@ describe('External LDAP', function () { it('fails for unknown user', async function () { const [error] = await safe(users.verifyWithUsername('doesnotexist', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {})); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(!(result.find(function (u) { return u.username === 'doesnotexist'; - })).to.not.be.ok(); + }))); }); it('succeeds for known user with wrong password', async function () { @@ -671,12 +668,12 @@ describe('External LDAP', function () { }); const [error] = await safe(users.verifyWithUsername('autologinuser1', 'wrongpassword', users.AP_WEBADMIN, {})); - expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.username === 'autologinuser1'; - })).to.be.ok(); + })); }); it('succeeds for known user with correct password', async function () { @@ -690,9 +687,9 @@ describe('External LDAP', function () { await users.verifyWithUsername('autologinuser2', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {}); const result = await users.list(); - expect(result.find(function (u) { + assert.ok(result.find(function (u) { return u.username === 'autologinuser2'; - })).to.be.ok(); + })); }); }); }); diff --git a/src/test/groups-test.js b/src/test/groups-test.js index c1a8453e4..4d4f69ed2 100644 --- a/src/test/groups-test.js +++ b/src/test/groups-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import groups from '../groups.js'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Groups', function () { const { setup, cleanup, admin, user, auditSource, app } = common; @@ -25,72 +22,72 @@ describe('Groups', function () { describe('add', function () { it('cannot add group - too small', async function () { const [error] = await safe(groups.add({ name: '' }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add group - too big', async function () { const [error] = await safe(groups.add({ name: new Array(256).join('a') }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add group - bad name', async function () { const [error] = await safe(groups.add({ name: 'bad:name' }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add group - reserved', async function () { const [error] = await safe(groups.add({ name: 'users' }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add group - invalid', async function () { const [error] = await safe(groups.add({ name: 'cloudron+admin' }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add group - invalid source', async function () { const [error] = await safe(groups.add({ name: 'somegroup', source: 'unknownsource' }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can add valid groups', async function () { let [error, result] = await safe(groups.add({ name: group0Name }, auditSource)); - expect(error).to.be(null); + assert.equal(error, null); group0Object = result; [error, result] = await safe(groups.add({ name: group1Name}, auditSource)); - expect(error).to.be(null); + assert.equal(error, null); group1Object = result; }); it('cannot add existing group with mixed case', async function () { const name = group0Name[0].toUpperCase() + group0Name.slice(1); const [error] = await safe(groups.add({ name }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cannot add existing group', async function () { const [error] = await safe(groups.add({name: group0Name }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); }); describe('get', function () { it('cannot get invalid group', async function () { const result = await groups.get('sometrandom'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can get valid group', async function () { const result = await groups.get(group0Object.id); - expect(result.name).to.equal(group0Name); + assert.equal(result.name, group0Name); }); }); describe('members', function () { it('isMember returns false', async function () { const isMember = await groups.isMember(group0Object.id, admin.id); - expect(isMember).to.be(false); + assert.equal(isMember, false); }); it('can set members', async function () { @@ -99,34 +96,34 @@ describe('Groups', function () { it('cannot set duplicate members', async function () { const [error] = await safe(groups.setMembers(group0Object, [ admin.id, user.id, admin.id ], {}, auditSource)); - expect(error.reason).to.be(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); }); it('can list users of group', async function () { const result = await groups.getMemberIds(group0Object.id); - expect(result.sort()).to.eql([ admin.id, user.id ].sort()); + assert.deepEqual(result.sort(), [ admin.id, user.id ].sort()); }); it('cannot list members of non-existent group', async function () { const result = await groups.getMemberIds('randomgroup'); - expect(result.length).to.be(0); // currently, we cannot differentiate invalid groups and empty groups + assert.equal(result.length, 0); // currently, we cannot differentiate invalid groups and empty groups }); it('can getWithMembers', async function () { const result = await groups.getWithMembers(group0Object.id); - expect(result.name).to.be(group0Name); - expect(result.userIds.sort()).to.eql([ admin.id, user.id ].sort()); + assert.equal(result.name, group0Name); + assert.deepEqual(result.userIds.sort(), [ admin.id, user.id ].sort()); }); it('can set group membership', async function () { await groups.setLocalMembership(admin, [ group0Object.id ], auditSource); const groupIds = await groups._getMembership(admin.id); - expect(groupIds.length).to.be(1); + assert.equal(groupIds.length, 1); }); it('cannot set user to same group twice', async function () { const [error] = await safe(groups.setLocalMembership(admin, [ group0Object.id, group0Object.id ], auditSource)); - expect(error.reason).to.be(BoxError.CONFLICT); + assert.equal(error.reason, BoxError.CONFLICT); }); it('can set user to multiple groups', async function () { @@ -135,32 +132,32 @@ describe('Groups', function () { it('can get groups membership', async function () { const groupIds = await groups._getMembership(admin.id); - expect(groupIds.length).to.be(2); - expect(groupIds.sort()).to.eql([ group0Object.id, group1Object.id ].sort()); + assert.equal(groupIds.length, 2); + assert.deepEqual(groupIds.sort(), [ group0Object.id, group1Object.id ].sort()); }); }); describe('list', function () { it('can list', async function () { const result = await groups.list(); - expect(result.length).to.be(2); - expect(result[0].name).to.be(group0Name); - expect(result[1].name).to.be(group1Name); + assert.equal(result.length, 2); + assert.equal(result[0].name, group0Name); + assert.equal(result[1].name, group1Name); }); it('can listWithMembers', async function () { const result = await groups.listWithMembers(); - expect(result.length).to.be(2); - expect(result[0].name).to.be(group0Name); - expect(result[1].userIds).to.eql([ admin.id ]); - expect(result[1].name).to.be(group1Name); + assert.equal(result.length, 2); + assert.equal(result[0].name, group0Name); + assert.deepEqual(result[1].userIds, [ admin.id ]); + assert.equal(result[1].name, group1Name); }); }); describe('delete', function () { it('cannot delete invalid group', async function () { const [error] = await safe(groups.del({ id: 'random' }, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can delete valid group', async function () { @@ -174,24 +171,24 @@ describe('Groups', function () { before(async function () { const [error, result] = await safe(groups.add({ name: 'kootam' }, auditSource)); - expect(error).to.be(null); + assert.equal(error, null); groupObject = result; }); it('cannot set empty group name', async function () { const [error] = await safe(groups.setName(groupObject, '', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot set bad group name', async function () { const [error] = await safe(groups.setName(groupObject, '!kootam', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set group name', async function () { await groups.setName(groupObject, 'kootam2', auditSource); groupObject = await groups.get(groupObject.id); - expect(groupObject.name).to.be('kootam2'); + assert.equal(groupObject.name, 'kootam2'); }); }); @@ -200,55 +197,55 @@ describe('Groups', function () { before(async function () { const [error, result] = await safe(groups.add({ name: 'kootam' }, auditSource)); - expect(error).to.be(null); + assert.equal(error, null); groupObject = result; }); it('has no app access', async function () { - expect(groupObject.appIds).to.eql([]); + assert.deepEqual(groupObject.appIds, []); const g1 = await groups.get(groupObject.id); - expect(g1.appIds).to.eql([]); + assert.deepEqual(g1.appIds, []); const g2 = await groups.getByName(groupObject.name); - expect(g2.appIds).to.eql([]); + assert.deepEqual(g2.appIds, []); const g3 = await groups.getWithMembers(groupObject.id); - expect(g3.appIds).to.eql([]); + assert.deepEqual(g3.appIds, []); }); it('set app access', async function () { await groups.setAllowedApps(groupObject, [ app.id ], auditSource); const g1 = await groups.get(groupObject.id); - expect(g1.appIds).to.eql([ app.id ]); + assert.deepEqual(g1.appIds, [ app.id ]); const g2 = await groups.getByName(groupObject.name); - expect(g2.appIds).to.eql([ app.id ]); + assert.deepEqual(g2.appIds, [ app.id ]); const g3 = await groups.getWithMembers(groupObject.id); - expect(g3.appIds).to.eql([ app.id ]); + assert.deepEqual(g3.appIds, [ app.id ]); const allGroups = await groups.listWithMembers(); const g4 = allGroups.filter(g => g.id === groupObject.id)[0]; - expect(g4.appIds).to.eql([ app.id ]); + assert.deepEqual(g4.appIds, [ app.id ]); }); it('cleared app access', async function () { await groups.setAllowedApps(groupObject, [ ], auditSource); const g1 = await groups.get(groupObject.id); - expect(g1.appIds).to.eql([ ]); + assert.deepEqual(g1.appIds, [ ]); const g2 = await groups.getByName(groupObject.name); - expect(g2.appIds).to.eql([ ]); + assert.deepEqual(g2.appIds, [ ]); const g3 = await groups.getWithMembers(groupObject.id); - expect(g3.appIds).to.eql([ ]); + assert.deepEqual(g3.appIds, [ ]); const allGroups = await groups.listWithMembers(); const g4 = allGroups.filter(g => g.id === groupObject.id)[0]; - expect(g4.appIds).to.eql([ ]); + assert.deepEqual(g4.appIds, [ ]); }); }); @@ -261,17 +258,17 @@ describe('Groups', function () { it('cannot change name', async function () { const [error] = await safe(groups.setName(ldapGroup, 'ldap-kootam2', auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('cannot set members', async function () { const [error] = await safe(groups.setMembers(ldapGroup, [ admin.id ], { skipSourceSkip: false }, auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('cannot set membership', async function () { const [error] = await safe(groups.setLocalMembership(admin, [ ldapGroup.id ], auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('does not clear remote membership', async function () { @@ -279,8 +276,8 @@ describe('Groups', function () { await groups.setLocalMembership(admin, [ group1Object.id ], auditSource); const groupIds = await groups._getMembership(admin.id); - expect(groupIds.length).to.be(2); - expect(groupIds.sort()).to.eql([ group1Object.id, ldapGroup.id ].sort()); + assert.equal(groupIds.length, 2); + assert.deepEqual(groupIds.sort(), [ group1Object.id, ldapGroup.id ].sort()); }); }); }); diff --git a/src/test/ipaddr-test.js b/src/test/ipaddr-test.js index 297270da1..3c69e6b34 100644 --- a/src/test/ipaddr-test.js +++ b/src/test/ipaddr-test.js @@ -1,6 +1,6 @@ -/* global it, describe */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import ipaddr from '../ipaddr.js'; describe('ipaddr', function () { @@ -9,11 +9,11 @@ describe('ipaddr', function () { const badIPv4s = [ '1.2.3', '1.2.3.256', '-1.2.3.4', '1e2.5.6.7', 'x.7.8.9', '1..2.4' ]; for (const goodIPv4 of goodIPv4s) { - it(`isValid returns true ${goodIPv4}`, () => expect(ipaddr.isValid(goodIPv4)).to.be(true)); + it(`isValid returns true ${goodIPv4}`, () => assert.equal(ipaddr.isValid(goodIPv4), true)); } for (const badIPv4 of badIPv4s) { - it(`isValid returns false ${badIPv4}`, () => expect(ipaddr.isValid(badIPv4)).to.be(false)); + it(`isValid returns false ${badIPv4}`, () => assert.equal(ipaddr.isValid(badIPv4), false)); } const goodCIDRs = [ @@ -28,22 +28,22 @@ describe('ipaddr', function () { ]; for (const goodCIDR of goodCIDRs) { - it(`isValidCIDR returns true ${goodCIDR}`, () => expect(ipaddr.isValidCIDR(goodCIDR)).to.be(true)); + it(`isValidCIDR returns true ${goodCIDR}`, () => assert.equal(ipaddr.isValidCIDR(goodCIDR), true)); } for (const badCIDR of badCIDRs) { - it(`isValidCIDR returns false ${badCIDR}`, () => expect(ipaddr.isValidCIDR(badCIDR)).to.be(false)); + it(`isValidCIDR returns false ${badCIDR}`, () => assert.equal(ipaddr.isValidCIDR(badCIDR), false)); } it('isEqual', function () { - expect(ipaddr.isEqual('1.2.3.4', '1.2.3.4')).to.be(true); - expect(ipaddr.isEqual('1.2.3.4', '1.2.3.5')).to.be(false); - expect(ipaddr.isEqual('1.2.3.4', '1.2.3.')).to.be(false); + assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.4'), true); + assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.5'), false); + assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.'), false); }); it('includes', function () { - expect(ipaddr.includes('1.2.3.0/8', '1.2.3.4')).to.be(true); - expect(ipaddr.includes('1.2.0.0/16', '1.3.0.0')).to.be(false); + assert.equal(ipaddr.includes('1.2.3.0/8', '1.2.3.4'), true); + assert.equal(ipaddr.includes('1.2.0.0/16', '1.3.0.0'), false); }); }); @@ -68,11 +68,11 @@ describe('ipaddr', function () { ]; for (const goodIPv6 of goodIPv6s) { - it(`isValid returns true ${goodIPv6}`, () => expect(ipaddr.isValid(goodIPv6)).to.be(true)); + it(`isValid returns true ${goodIPv6}`, () => assert.equal(ipaddr.isValid(goodIPv6), true)); } for (const badIPv6 of badIPv6s) { - it(`isValid returns false ${badIPv6}`, () => expect(ipaddr.isValid(badIPv6)).to.be(false)); + it(`isValid returns false ${badIPv6}`, () => assert.equal(ipaddr.isValid(badIPv6), false)); } const goodCIDRs = [ @@ -86,26 +86,26 @@ describe('ipaddr', function () { ]; for (const goodCIDR of goodCIDRs) { - it(`isValidCIDR returns true ${goodCIDR}`, () => expect(ipaddr.isValidCIDR(goodCIDR)).to.be(true)); + it(`isValidCIDR returns true ${goodCIDR}`, () => assert.equal(ipaddr.isValidCIDR(goodCIDR), true)); } for (const badCIDR of badCIDRs) { - it(`isValidCIDR returns false ${badCIDR}`, () => expect(ipaddr.isValidCIDR(badCIDR)).to.be(false)); + it(`isValidCIDR returns false ${badCIDR}`, () => assert.equal(ipaddr.isValidCIDR(badCIDR), false)); } it('isEqual', function () { - expect(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(true); // same - expect(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:0370:7334')).to.be(true); // shorthand - expect(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:370:7334')).to.be(true); // casing change and no 0 prefix - expect(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '1.2.3.4')).to.be(false); - expect(ipaddr.isEqual('::ffff:1.2.3.4', '1.2.3.4')).to.be(true); // ipv6 mapped ipv4 - expect(ipaddr.isEqual('2002:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(false); + assert.equal(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), true); // same + assert.equal(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:0370:7334'), true); // shorthand + assert.equal(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:370:7334'), true); // casing change and no 0 prefix + assert.equal(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '1.2.3.4'), false); + assert.equal(ipaddr.isEqual('::ffff:1.2.3.4', '1.2.3.4'), true); // ipv6 mapped ipv4 + assert.equal(ipaddr.isEqual('2002:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), false); }); it('includes', function () { - expect(ipaddr.includes('2001:0db8:85a3::/64', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(true); - expect(ipaddr.includes('2001:0db8:85a3::/64', '2002:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(false); - expect(ipaddr.includes('::ffff:0:0/96', '1.2.3.4')).to.be(true); // ipv6 mapped ipv4 + assert.equal(ipaddr.includes('2001:0db8:85a3::/64', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), true); + assert.equal(ipaddr.includes('2001:0db8:85a3::/64', '2002:0db8:85a3:0000:0000:8a2e:0370:7334'), false); + assert.equal(ipaddr.includes('::ffff:0:0/96', '1.2.3.4'), true); // ipv6 mapped ipv4 }); }); }); diff --git a/src/test/janitor-test.js b/src/test/janitor-test.js index e6b3c26f4..f27f0504d 100644 --- a/src/test/janitor-test.js +++ b/src/test/janitor-test.js @@ -1,14 +1,11 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import janitor from '../janitor.js'; import tokens from '../tokens.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('janitor', function () { const { setup, cleanup } = common; @@ -49,12 +46,12 @@ describe('janitor', function () { it('did not remove the non-expired token', async function () { const result = await tokens.getByAccessToken(token1.accessToken); - expect(result).to.be.eql(token1); + assert.deepEqual(result, token1); }); it('did remove the non-expired token', async function () { const result = await tokens.getByAccessToken(token2.accessToken); - expect(result).to.be(null); + assert.equal(result, null); }); }); diff --git a/src/test/ldapserver-test.js b/src/test/ldapserver-test.js index bfa5e0e32..17ba74ce4 100644 --- a/src/test/ldapserver-test.js +++ b/src/test/ldapserver-test.js @@ -1,20 +1,17 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import addonConfigs from '../addonconfigs.js'; import async from 'async'; import common from './common.js'; import constants from '../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import groups from '../groups.js'; import ldap from 'ldapjs'; import ldapServer from '../ldapserver.js'; import mail from '../mail.js'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ async function ldapBind(dn, password) { return new Promise((resolve, reject) => { @@ -70,8 +67,10 @@ describe('Ldap Server', function () { const mailAliasWildcardName = 'help'; const mailAliasWildcard = `helpmeplz@${domain.domain}`; - before(function (done) { - async.series([ + before(async function () { + ldapServer._setMockApp(mockApp); + + await async.series([ setup, async () => await mail.addMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, storageQuota: 0, messagesQuota: 0, enablePop3: false }, auditSource), async () => await mail.setAliases(mailboxName, domain.domain, [ { name: mailAliasName, domain: domain.domain}, { name: mailAliasWildcardName + '*', domain: domain.domain } ], auditSource), @@ -84,38 +83,36 @@ describe('Ldap Server', function () { group2 = await groups.add({ name: 'ldap-test-2' }, auditSource); await groups.setMembers(group2, [ admin.id ], {}, auditSource); } - ], done); - - ldapServer._setMockApp(mockApp); + ]); }); - after(function (done) { - async.series([ + after(async function () { + await async.series([ ldapServer.stop, cleanup - ], done); + ]); }); describe('root DSE', function () { it('can get root DSE', async function () { const entries = await ldapSearch('', { filter: 'objectcategory=person' }); - expect(entries.length).to.be(1); - expect(entries[0].dn).to.be(''); - expect(entries[0].supportedLDAPVersion).to.be('3'); - expect(entries[0].vendorName).to.be('Cloudron LDAP'); - expect(entries[0].vendorVersion).to.be('1.0.0'); + assert.equal(entries.length, 1); + assert.equal(entries[0].dn, ''); + assert.equal(entries[0].supportedLDAPVersion, '3'); + assert.equal(entries[0].vendorName, 'Cloudron LDAP'); + assert.equal(entries[0].vendorVersion, '1.0.0'); }); }); describe('admin bind', function () { it('cn= fails for nonexisting user', async function () { const [error] = await safe(ldapBind('cn=doesnotexist,ou=users,dc=cloudron', 'password')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('cn= fails with wrong password', async function () { const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, 'wrongpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('cn= succeeds with id', async function () { @@ -132,7 +129,7 @@ describe('Ldap Server', function () { it('mail= fails with bad email', async function () { const [error] = await safe(ldapBind('mail=random,ou=users,dc=cloudron', admin.password)); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('mail= succeeds with email', async function () { @@ -149,7 +146,7 @@ describe('Ldap Server', function () { it('fails without accessRestriction', async function () { mockApp.accessRestriction = { users: [], groups: [] }; const [error] = await safe(ldapBind(`cn=${user.id},ou=users,dc=cloudron`, user.password)); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('succeeds with accessRestriction', async function () { @@ -161,60 +158,60 @@ describe('Ldap Server', function () { describe('search users', function () { it('fails for non existing tree', async function () { const [error] = await safe(ldapSearch('o=example', { filter: '(&(l=Seattle)(email=*@' + domain.domain + '))' })); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('succeeds with basic filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].mail).to.equal(admin.email.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); - expect(entries[1].mail).to.equal(user.email.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].mail, admin.email.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); + assert.equal(entries[1].mail, user.email.toLowerCase()); }); it('succeeds with pagination', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person', paged: true }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].mail).to.equal(admin.email.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); - expect(entries[1].mail).to.equal(user.email.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].mail, admin.email.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); + assert.equal(entries[1].mail, user.email.toLowerCase()); }); it('succeeds with username wildcard filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=*)' }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); }); it('succeeds with username filter', async function () { const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=' + admin.username + ')' }); - expect(entries.length).to.equal(1); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].memberof.length).to.equal(2); + assert.equal(entries.length, 1); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].memberof.length, 2); }); it('can always lists admins', async function () { mockApp.accessRestriction = { users: [], groups: [] }; const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }); - expect(entries.length).to.equal(1); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[0].memberof.length).to.equal(2); + assert.equal(entries.length, 1); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[0].memberof.length, 2); }); it ('does only list users who have access', async function () { mockApp.accessRestriction = { users: [], groups: [ group.id ] }; const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); entries.sort(function (a, b) { return a.username > b.username; }); - expect(entries[0].username).to.equal(admin.username.toLowerCase()); - expect(entries[1].username).to.equal(user.username.toLowerCase()); + assert.equal(entries[0].username, admin.username.toLowerCase()); + assert.equal(entries[1].username, user.username.toLowerCase()); }); }); @@ -223,107 +220,107 @@ describe('Ldap Server', function () { mockApp.accessRestriction = null; const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group' }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); }); it ('succeeds with cn wildcard filter', async function () { const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); }); it('succeeds with memberuid filter', async function () { const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(memberuid=' + user.id + ')' }); - expect(entries.length).to.equal(1); + assert.equal(entries.length, 1); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); }); it ('does only list groups who have access', async function () { mockApp.accessRestriction = { users: [], groups: [ group.id ] }; const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' }); - expect(entries.length).to.equal(1); + assert.equal(entries.length, 1); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); }); it ('succeeds with pagination', async function () { mockApp.accessRestriction = null; const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group', paged: true }); - expect(entries.length).to.equal(2); + assert.equal(entries.length, 2); // ensure order for testability entries.sort(function (a, b) { return a.cn < b.cn; }); - expect(entries[0].cn).to.equal('ldap-test-1'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid).to.contain(admin.id); - expect(entries[0].memberuid).to.contain(user.id); + assert.equal(entries[0].cn, 'ldap-test-1'); + assert.equal(entries[0].memberuid.length, 2); + assert.ok(entries[0].memberuid.includes(admin.id)); + assert.ok(entries[0].memberuid.includes(user.id)); - expect(entries[1].cn).to.equal('ldap-test-2'); - expect(entries[1].memberuid).to.equal(admin.id); + assert.equal(entries[1].cn, 'ldap-test-2'); + assert.equal(entries[1].memberuid, admin.id); }); }); describe('mailbox search', function () { it('get specific mailbox by email', async function () { const entries = await ldapSearch(`cn=${mailbox},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox'); - expect(entries.length).to.equal(1); - expect(entries[0].cn).to.equal(mailbox); + assert.equal(entries.length, 1); + assert.equal(entries[0].cn, mailbox); }); it('cannot get mailbox with just name', async function () { const [error] = await safe(ldapSearch(`cn=${mailboxName},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('cannot get alias as a mailbox', async function () { const [error] = await safe(ldapSearch(`cn=${mailAlias},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('non-existent mailbox', async function () { const [error] = await safe(ldapSearch(`cn=random@${domain.domain},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('cannot get inactive mailbox', async function () { await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource); const [error] = await safe(ldapSearch(`cn=${mailbox},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource); }); @@ -332,26 +329,26 @@ describe('Ldap Server', function () { describe('search aliases', function () { it('get specific alias', async function () { const entries = await ldapSearch(`cn=${mailAlias},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias'); - expect(entries.length).to.equal(1); - expect(entries[0].cn).to.equal(mailAlias); - expect(entries[0].rfc822MailMember).to.equal(mailbox); + assert.equal(entries.length, 1); + assert.equal(entries[0].cn, mailAlias); + assert.equal(entries[0].rfc822MailMember, mailbox); }); it('get alias matching wildcard', async function () { const entries = await ldapSearch(`cn=${mailAliasWildcard},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias'); - expect(entries.length).to.equal(1); - expect(entries[0].cn).to.equal(mailAliasWildcard); - expect(entries[0].rfc822MailMember).to.equal(mailbox); + assert.equal(entries.length, 1); + assert.equal(entries[0].cn, mailAliasWildcard); + assert.equal(entries[0].rfc822MailMember, mailbox); }); it('cannot get mailbox as alias', async function () { const [error] = await safe(ldapSearch(`cn=${mailbox},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('non-existent alias', async function () { const [error] = await safe(ldapSearch(`cn=random@${domain.domain},ou=mailaliases,dc=cloudron`, 'objectclass=mailbox')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); }); @@ -364,33 +361,33 @@ describe('Ldap Server', function () { it('get specific list', async function () { const entries = await ldapSearch(`cn=${LIST},ou=mailinglists,dc=cloudron`, 'objectclass=mailGroup'); - expect(entries.length).to.equal(1); - expect(entries[0].cn).to.equal(LIST); - expect(entries[0].mgrpRFC822MailMember).to.eql([ mailbox, 'outsider@external.com' ]); + assert.equal(entries.length, 1); + assert.equal(entries[0].cn, LIST); + assert.deepEqual(entries[0].mgrpRFC822MailMember, [ mailbox, 'outsider@external.com' ]); }); it('non-existent list', async function () { const [error] = await safe(ldapSearch('cn=random@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('inactive list', async function () { await mail.updateMailingList(LIST_NAME, domain.domain, { members: [ mailbox , 'outsider@external.com' ], membersOnly: false, active: false }, auditSource); const [error] = await safe(ldapSearch('cn=devs@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); }); describe('sogo mailbox bind', function () { it('email disabled - cannot auth', async function () { const [error] = await safe(ldapBind(`cn=${mailbox},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('email enabled - does not allow with invalid password', async function () { await mail._updateDomain(domain.domain, { enabled: true }); const [error] = await safe(ldapBind(`cn=${mailbox},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); await mail._updateDomain(domain.domain, { enabled: false }); }); @@ -403,7 +400,7 @@ describe('Ldap Server', function () { it('email enabled - cannot auth with alias', async function () { await mail._updateDomain(domain.domain, { enabled: true }); const [error] = await safe(ldapBind(`cn=${mailAlias},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); await mail._updateDomain(domain.domain, { enabled: false }); }); }); @@ -412,7 +409,7 @@ describe('Ldap Server', function () { it('email disabled - cannot find domain email', async function () { await mail._updateDomain(domain.domain, { enabled: false }); const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('email enabled - allows with valid email', async function () { @@ -424,7 +421,7 @@ describe('Ldap Server', function () { it('email enabled - does not allow with invalid password', async function () { await mail._updateDomain(domain.domain, { enabled: true }); const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); await mail._updateDomain(domain.domain, { enabled: false }); }); @@ -432,7 +429,7 @@ describe('Ldap Server', function () { await mail._updateDomain(domain.domain, { enabled: true }); await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource); const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource); }); }); @@ -445,12 +442,12 @@ describe('Ldap Server', function () { it('does not allow with invalid app', async function () { const [error] = await safe(ldapBind(`cn=hacker.app@${domain.domain},ou=msa,dc=cloudron`, 'nope')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('does not allow with invalid password', async function () { const [error] = await safe(ldapBind(`cn=${app.subdomain}.app@${domain.domain},ou=msa,dc=cloudron`, 'nope')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('allows with valid password', async function () { @@ -464,7 +461,7 @@ describe('Ldap Server', function () { it('email disabled - cannot find domain email', async function () { await mail._updateDomain(domain.domain, { enabled: false }); const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('email enabled - allows with valid email', async function () { @@ -475,14 +472,14 @@ describe('Ldap Server', function () { it('email enabled - does not allow with invalid password', async function () { await mail._updateDomain(domain.domain, { enabled: true }); const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('does not allow for inactive mailbox', async function () { await mail._updateDomain(domain.domain, { enabled: true }); await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource); const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); await mail._updateDomain(domain.domain, { enabled: false }); await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource); }); @@ -495,19 +492,19 @@ describe('Ldap Server', function () { it('does not allow with invalid app', async function () { const [error] = await safe(ldapBind(`cn=hacker.app@${domain.domain},ou=imap,dc=cloudron`, 'nope')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('does not allow with valid password (missing mailbox)', async function () { await addonConfigs.set(app.id, 'recvmail', [{ name: 'MAIL_IMAP_USERNAME', value : `${app.subdomain}.app@${domain.domain}` }, { name: 'MAIL_IMAP_PASSWORD', value : 'imappassword' }]); const [error] = await safe(ldapBind(`cn=${app.subdomain}.app@${domain.domain},ou=imap,dc=cloudron`, 'imappassword')); - expect(error).to.be.a(ldap.NoSuchObjectError); + assert.ok((error) instanceof (ldap.NoSuchObjectError)); }); it('does not allow with invalid password', async function () { await addonConfigs.set(app.id, 'recvmail', [{ name: 'MAIL_IMAP_USERNAME', value : `${mailboxName}@${domain.domain}` }, { name: 'MAIL_IMAP_PASSWORD', value : 'imappassword' }]); const [error] = await safe(ldapBind(`cn=${mailboxName}@${domain.domain},ou=imap,dc=cloudron`, 'nope')); - expect(error).to.be.a(ldap.InvalidCredentialsError); + assert.ok((error) instanceof (ldap.InvalidCredentialsError)); }); it('allows with valid password', async function () { diff --git a/src/test/locks-test.js b/src/test/locks-test.js index eb1a758c6..163c7e9fc 100644 --- a/src/test/locks-test.js +++ b/src/test/locks-test.js @@ -1,13 +1,12 @@ -/* global it, describe, before, after */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import locks from '../locks.js'; -describe('Locks', function () { - this.timeout(20000); +describe('Locks', { timeout: 20000 }, function () { const { setup, cleanup } = common; @@ -24,7 +23,7 @@ describe('Locks', function () { it('cannot reacquire lock foo', async function () { const [error] = await safe(locks.acquire('foo')); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('cannot reacquire after release', async function () { @@ -43,7 +42,7 @@ describe('Locks', function () { const startTime = Date.now(); await locks.wait('tasklock'); // retries only in 10s const endTime = Date.now(); - expect(endTime - startTime).to.be.greaterThan(9900); - expect(endTime - startTime).to.be.lessThan(10100); + assert.ok((endTime - startTime) > (9900)); + assert.ok((endTime - startTime) < (10100)); }); }); diff --git a/src/test/logs-test.js b/src/test/logs-test.js index 3b7280ddd..b573feb3a 100644 --- a/src/test/logs-test.js +++ b/src/test/logs-test.js @@ -1,28 +1,29 @@ -/* global it:false */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import logs from '../logs.js'; import stream from 'node:stream'; -/* global describe:false */ describe('log stream', function () { - it('can create stream', function (done) { + it('can create stream', async function () { fs.writeFileSync('/tmp/test-input.log', '2022-10-09T15:19:48.740Z message', 'utf8'); const input = fs.createReadStream('/tmp/test-input.log'); const log = new logs.LogStream({ format: 'json', source: 'test' }); const output = fs.createWriteStream('/tmp/test-output.log'); - stream.pipeline(input, log, output, function (error) { - expect(error).to.not.be.ok(); - - const out = fs.readFileSync('/tmp/test-output.log', 'utf8'); - const firstLine = JSON.parse(out.split('\n')[0]); - expect(firstLine.realtimeTimestamp).to.be.a('number'); - expect(firstLine.message).to.be('message'); - expect(firstLine.source).to.be('test'); - done(); + await new Promise((resolve, reject) => { + stream.pipeline(input, log, output, function (error) { + if (error) return reject(error); + resolve(); + }); }); + + const out = fs.readFileSync('/tmp/test-output.log', 'utf8'); + const firstLine = JSON.parse(out.split('\n')[0]); + assert.equal(typeof firstLine.realtimeTimestamp, 'number'); + assert.equal(firstLine.message, 'message'); + assert.equal(firstLine.source, 'test'); }); }); diff --git a/src/test/mail-test.js b/src/test/mail-test.js index 506bcd287..be3f18eaa 100644 --- a/src/test/mail-test.js +++ b/src/test/mail-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import BoxError from '../boxerror.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import mail from '../mail.js'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Mail', function () { const { setup, cleanup, domain, auditSource } = common; @@ -19,36 +16,36 @@ describe('Mail', function () { describe('settings', function () { it('can get default', async function () { const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.enabled).to.be(false); - expect(mailConfig.mailFromValidation).to.be(true); - expect(mailConfig.catchAll).to.eql([]); - expect(mailConfig.relay).to.eql({ provider: 'cloudron-smtp' }); + assert.equal(mailConfig.enabled, false); + assert.equal(mailConfig.mailFromValidation, true); + assert.deepEqual(mailConfig.catchAll, []); + assert.deepEqual(mailConfig.relay, { provider: 'cloudron-smtp' }); }); it('can get all domains', async function () { const result = await mail.listDomains(); - expect(result).to.be.an(Array); - expect(result[0]).to.be.an('object'); - expect(result[0].domain).to.eql(domain.domain); + assert.ok(Array.isArray(result)); + assert.equal(typeof result[0], 'object'); + assert.deepEqual(result[0].domain, domain.domain); }); it('can set mail from validation', async function () { await mail.setMailFromValidation(domain.domain, false); const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.mailFromValidation).to.be(false); + assert.equal(mailConfig.mailFromValidation, false); }); it('cannot set invalid catch all address', async function () { const [error] = await safe(mail.setCatchAllAddress(domain.domain, [ 'user1' ])); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set invalid catch all address', async function () { await mail.setCatchAllAddress(domain.domain, [ `user1@${domain.domain}`, `user2@${domain.domain}` ]); const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.catchAll).to.eql([ `user1@${domain.domain}`, `user2@${domain.domain}` ]); + assert.deepEqual(mailConfig.catchAll, [ `user1@${domain.domain}`, `user2@${domain.domain}` ]); }); it('can set mail relay', async function () { @@ -57,7 +54,7 @@ describe('Mail', function () { await mail.setMailRelay(domain.domain, relay, { skipVerify: true }); const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.relay).to.eql(relay); + assert.deepEqual(mailConfig.relay, relay); }); it('can set banner', async function () { @@ -66,52 +63,52 @@ describe('Mail', function () { await mail.setBanner(domain.domain, banner); const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.banner).to.eql(banner); + assert.deepEqual(mailConfig.banner, banner); }); it('can enable mail', async function () { await mail.setMailEnabled(domain.domain, true, auditSource); const mailConfig = await mail.getDomain(domain.domain); - expect(mailConfig.enabled).to.be(true); + assert.equal(mailConfig.enabled, true); }); }); describe('mailbox name', function () { it('allows valid names', function () { - expect(mail.validateName('1')).to.be(null); // single char - expect(mail.validateName('ap')).to.be(null); // alpha - expect(mail.validateName('aP')).to.be(null); // caps - expect(mail.validateName('0P')).to.be(null); // number - expect(mail.validateName('a.p.x')).to.be(null); // dot - expect(mail.validateName('a-p-x')).to.be(null); // hyphen - expect(mail.validateName('a-p_x')).to.be(null); // underscore + assert.equal(mail.validateName('1'), null); // single char + assert.equal(mail.validateName('ap'), null); // alpha + assert.equal(mail.validateName('aP'), null); // caps + assert.equal(mail.validateName('0P'), null); // number + assert.equal(mail.validateName('a.p.x'), null); // dot + assert.equal(mail.validateName('a-p-x'), null); // hyphen + assert.equal(mail.validateName('a-p_x'), null); // underscore }); it('disallows invalid names', function () { - expect(mail.validateName('@')).to.be.an(Error); - expect(mail.validateName('a+p')).to.be.an(Error); - expect(mail.validateName('a#p')).to.be.an(Error); - expect(mail.validateName('a!')).to.be.an(Error); + assert.ok((mail.validateName('@')) instanceof (Error)); + assert.ok((mail.validateName('a+p')) instanceof (Error)); + assert.ok((mail.validateName('a#p')) instanceof (Error)); + assert.ok((mail.validateName('a!')) instanceof (Error)); }); }); describe('mailbox display name', function () { it('allows valid names', function () { - expect(mail.validateDisplayName('1')).to.be(null); // single char - expect(mail.validateDisplayName('ap')).to.be(null); // alpha - expect(mail.validateDisplayName('aP')).to.be(null); // caps - expect(mail.validateDisplayName('0P')).to.be(null); // number - expect(mail.validateDisplayName('a p.x')).to.be(null); // space - expect(mail.validateDisplayName('a-p-x')).to.be(null); // hyphen - expect(mail.validateDisplayName('a-p_x')).to.be(null); // underscore + assert.equal(mail.validateDisplayName('1'), null); // single char + assert.equal(mail.validateDisplayName('ap'), null); // alpha + assert.equal(mail.validateDisplayName('aP'), null); // caps + assert.equal(mail.validateDisplayName('0P'), null); // number + assert.equal(mail.validateDisplayName('a p.x'), null); // space + assert.equal(mail.validateDisplayName('a-p-x'), null); // hyphen + assert.equal(mail.validateDisplayName('a-p_x'), null); // underscore }); it('disallows invalid names', function () { - expect(mail.validateDisplayName('@')).to.be.an(Error); - expect(mail.validateDisplayName('ap')).to.be.an(Error); - expect(mail.validateDisplayName('a"x"')).to.be.an(Error); + assert.ok((mail.validateDisplayName('@')) instanceof (Error)); + assert.ok((mail.validateDisplayName('ap')) instanceof (Error)); + assert.ok((mail.validateDisplayName('a"x"')) instanceof (Error)); }); }); @@ -122,7 +119,7 @@ describe('Mail', function () { it('cannot add dup entry', async function () { const [error] = await safe(mail.addMailbox('girish', domain.domain, { ownerId: 'uid-1', ownerType: mail.OWNERTYPE_GROUP, active: true, enablePop3: false, storageQuota: 0, messagesQuota: 0 }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('add app mailbox succeeds', async function () { @@ -131,48 +128,48 @@ describe('Mail', function () { it('get succeeds', async function () { const mailbox = await mail.getMailbox('support', domain.domain); - expect(mailbox.name).to.equal('support'); - expect(mailbox.ownerId).to.equal('osticket'); - expect(mailbox.domain).to.equal(domain.domain); - expect(mailbox.creationTime).to.be.a(Date); - expect(mailbox.storageQuota).to.be(10); - expect(mailbox.messagesQuota).to.be(20); - expect(mailbox.enablePop3).to.be(true); + assert.equal(mailbox.name, 'support'); + assert.equal(mailbox.ownerId, 'osticket'); + assert.equal(mailbox.domain, domain.domain); + assert.ok((mailbox.creationTime) instanceof (Date)); + assert.equal(mailbox.storageQuota, 10); + assert.equal(mailbox.messagesQuota, 20); + assert.equal(mailbox.enablePop3, true); }); it('get non-existent mailbox', async function () { const mailbox = await mail.getMailbox('random', domain.domain); - expect(mailbox).to.be(null); + assert.equal(mailbox, null); }); it('update app mailbox succeeds', async function () { await mail.updateMailbox('support', domain.domain, { ownerId: 'osticket', ownerType: 'user', active: true, enablePop3: true, storageQuota: 20, messagesQuota: 30}, auditSource); const mailbox = await mail.getMailbox('support', domain.domain); - expect(mailbox.storageQuota).to.be(20); - expect(mailbox.messagesQuota).to.be(30); - expect(mailbox.enablePop3).to.be(true); + assert.equal(mailbox.storageQuota, 20); + assert.equal(mailbox.messagesQuota, 30); + assert.equal(mailbox.enablePop3, true); }); it('list mailboxes by domain succeeds', async function () { const mailboxes = await mail.listMailboxesByDomain(domain.domain, 1, 10); - expect(mailboxes.length).to.be(2); - expect(mailboxes[0].name).to.be('girish'); - expect(mailboxes[1].name).to.be('support'); + assert.equal(mailboxes.length, 2); + assert.equal(mailboxes[0].name, 'girish'); + assert.equal(mailboxes[1].name, 'support'); }); it('list all mailboxes succeeds', async function () { const mailboxes = await mail.listMailboxes(1, 10); - expect(mailboxes.length).to.be(2); - expect(mailboxes[0].name).to.be('girish'); - expect(mailboxes[0].domain).to.be(domain.domain); - expect(mailboxes[1].name).to.be('support'); - expect(mailboxes[1].domain).to.be(domain.domain); + assert.equal(mailboxes.length, 2); + assert.equal(mailboxes[0].name, 'girish'); + assert.equal(mailboxes[0].domain, domain.domain); + assert.equal(mailboxes[1].name, 'support'); + assert.equal(mailboxes[1].domain, domain.domain); }); it('mailbox count succeeds', async function () { const stats = await mail.getStats(domain.domain); - expect(stats.mailboxCount).to.be(2); + assert.equal(stats.mailboxCount, 2); }); it('can set alias', async function () { @@ -181,11 +178,11 @@ describe('Mail', function () { it('can get aliases of name', async function () { const results = await mail.getAliases('support', domain.domain); - expect(results.length).to.be(2); - expect(results[0].name).to.be('help'); - expect(results[0].domain).to.be(domain.domain); - expect(results[1].name).to.be('support2'); - expect(results[1].domain).to.be(domain.domain); + assert.equal(results.length, 2); + assert.equal(results[0].name, 'help'); + assert.equal(results[0].domain, domain.domain); + assert.equal(results[1].name, 'support2'); + assert.equal(results[1].domain, domain.domain); }); it('can set wildcard alias', async function () { @@ -194,18 +191,18 @@ describe('Mail', function () { it('can get aliases of name', async function () { const results = await mail.getAliases('support', domain.domain); - expect(results.length).to.be(2); - expect(results[0].name).to.be('help'); - expect(results[0].domain).to.be(domain.domain); - expect(results[1].name).to.be('support*'); - expect(results[1].domain).to.be(domain.domain); + assert.equal(results.length, 2); + assert.equal(results[0].name, 'help'); + assert.equal(results[0].domain, domain.domain); + assert.equal(results[1].name, 'support*'); + assert.equal(results[1].domain, domain.domain); }); it('unset aliases', async function () { await mail.setAliases('support', domain.domain, [], auditSource); const results = await mail.getAliases('support', domain.domain); - expect(results.length).to.be(0); + assert.equal(results.length, 0); }); it('add list succeeds', async function () { @@ -214,34 +211,34 @@ describe('Mail', function () { it('cannot add dup list', async function () { const [error] = await safe(mail.addMailingList('people', domain.domain, { members: [ 'admin@cloudron.io' ], membersOnly: false, active: true }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cannot get non-existing list', async function () { const result = await mail.getMailingList('random', domain.domain); - expect(result).to.be(null); + assert.equal(result, null); }); it('del list succeeds', async function () { await mail.delMailingList('people', domain.domain, auditSource); const result = await mail.getMailingList('people', domain.domain); - expect(result).to.be(null); + assert.equal(result, null); }); it('del non-existent list fails', async function () { const [error] = await safe(mail.delMailingList('people', domain.domain, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('del mailbox succeeds', async function () { await mail.delMailbox('girish', domain.domain, {/*options*/}, auditSource); const result = await mail.getMailbox('girish', domain.domain); - expect(result).to.be(null); + assert.equal(result, null); }); it('del non-existent mailbox fails', async function () { const [error] = await safe(mail.delMailbox('girish', domain.domain, {/*options*/}, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); }); diff --git a/src/test/mailpasswords-test.js b/src/test/mailpasswords-test.js index 8c6044ae5..0f9adcdc4 100644 --- a/src/test/mailpasswords-test.js +++ b/src/test/mailpasswords-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import mailPasswords from '../mailpasswords.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Mail passwords', function () { const { setup, cleanup, admin, app } = common; @@ -19,48 +16,48 @@ describe('Mail passwords', function () { it('cannot add with empty appId', async function () { const [error] = await safe(mailPasswords.add('', admin.id, 'token123')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add with empty userId', async function () { const [error] = await safe(mailPasswords.add(app.id, '', 'token123')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add with empty password', async function () { const [error] = await safe(mailPasswords.add(app.id, admin.id, '')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can add mail password', async function () { const result = await mailPasswords.add(app.id, admin.id, 'secret-token'); - expect(result.appId).to.be(app.id); - expect(result.userId).to.be(admin.id); + assert.equal(result.appId, app.id); + assert.equal(result.userId, admin.id); }); it('can get mail password', async function () { const result = await mailPasswords.get(app.id, admin.id); - expect(result).to.be.ok(); - expect(result.appId).to.be(app.id); - expect(result.userId).to.be(admin.id); - expect(result.password).to.be('secret-token'); + assert.ok(result); + assert.equal(result.appId, app.id); + assert.equal(result.userId, admin.id); + assert.equal(result.password, 'secret-token'); }); it('cannot get random mail password', async function () { const result = await mailPasswords.get('random', 'random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can list mail passwords for user', async function () { const results = await mailPasswords.list(admin.id); - expect(results.length).to.be(1); - expect(results[0].appId).to.be(app.id); - expect(results[0].userId).to.be(admin.id); + assert.equal(results.length, 1); + assert.equal(results[0].appId, app.id); + assert.equal(results[0].userId, admin.id); }); it('cannot add duplicate appId and userId', async function () { const [error] = await safe(mailPasswords.add(app.id, admin.id, 'another-token')); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('can del mail password', async function () { @@ -69,16 +66,16 @@ describe('Mail passwords', function () { it('cannot del random mail password', async function () { const [error] = await safe(mailPasswords.del('random', 'random')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('cannot add with non-existent appId', async function () { const [error] = await safe(mailPasswords.add('nonexistent-app-id', admin.id, 'token')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('cannot add with non-existent userId', async function () { const [error] = await safe(mailPasswords.add(app.id, 'nonexistent-user-id', 'token')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); diff --git a/src/test/network-test.js b/src/test/network-test.js index 642b88973..da59316a7 100644 --- a/src/test/network-test.js +++ b/src/test/network-test.js @@ -1,16 +1,13 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import network from '../network.js'; import paths from '../paths.js'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Network', function () { const { setup, cleanup, auditSource } = common; @@ -25,111 +22,111 @@ describe('Network', function () { it('can get empty blocklist', async function () { const result = await network.getBlocklist(); - expect(result).to.equal(''); + assert.equal(result, ''); }); it('can set empty blocklist', async function () { await network.setBlocklist('', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal(''); + assert.equal(result, ''); }); it('can set single IPv4 in blocklist', async function () { await network.setBlocklist('192.168.178.1', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('192.168.178.1'); + assert.equal(result, '192.168.178.1'); }); it('can set single IPv6 in blocklist', async function () { await network.setBlocklist('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8'); + assert.equal(result, '2a02:8106:2f:bb00:7afc:5703:ee71:3ef8'); }); it('can set mixed IPs with comment in blocklist', async function () { await network.setBlocklist('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1'); + assert.equal(result, '2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1'); }); it('can set single IPv4 range in blocklist', async function () { await network.setBlocklist('192.168.178.1/24', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('192.168.178.1/24'); + assert.equal(result, '192.168.178.1/24'); }); it('can set single IPv6 range in blocklist', async function () { await network.setBlocklist('2001:db8::', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('2001:db8::'); + assert.equal(result, '2001:db8::'); }); it('cannot set IPv4 in blocklist if source is same', async function () { const [error] = await safe(network.setBlocklist('127.0.0.1', { ip: '127.0.0.1' })); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot set IPv6 in blocklist if source is same', async function () { const [error] = await safe(network.setBlocklist('2001:db8:1234::1', { ip: '2001:db8:1234::1' })); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot set IPv4 range in blocklist if source is same', async function () { const [error] = await safe(network.setBlocklist('127.0.0.1/32', { ip: '127.0.0.1' })); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot set IPv6 range in blocklist if source is same', async function () { const [error] = await safe(network.setBlocklist('2001:db8:1234:::', { ip: '2001:db8:1234::1' })); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set IPv4 in blocklist if source is IPv6', async function () { await network.setBlocklist('192.168.178.1', { ip: '2001:db8:1234::1' }); const result = await network.getBlocklist(); - expect(result).to.equal('192.168.178.1'); + assert.equal(result, '192.168.178.1'); }); it('can set IPv6 in blocklist if source is IPv4', async function () { await network.setBlocklist('2001:db8:1234::1', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('2001:db8:1234::1'); + assert.equal(result, '2001:db8:1234::1'); }); it('can set IPv4 range in blocklist if source is IPv6', async function () { await network.setBlocklist('192.168.178.1/32', { ip: '2001:db8:1234::1' }); const result = await network.getBlocklist(); - expect(result).to.equal('192.168.178.1/32'); + assert.equal(result, '192.168.178.1/32'); }); it('can set IPv6 range in blocklist if source is IPv4', async function () { await network.setBlocklist('2001:db8:1234::', auditSource); const result = await network.getBlocklist(); - expect(result).to.equal('2001:db8:1234::'); + assert.equal(result, '2001:db8:1234::'); }); }); describe('IPv6 config', function () { it('can get default IPv6 setting', async function () { const config = await network.getIPv6Config(); - expect(config.provider).to.be('noop'); + assert.equal(config.provider, 'noop'); }); it('can set IPv6 setting', async function () { await network.setIPv6Config({ provider: 'generic' }); const config = await network.getIPv6Config(); - expect(config.provider).to.be('generic'); + assert.equal(config.provider, 'generic'); }); it('test machine has IPv6 support', function () { - expect(network.hasIPv6()).to.equal(true); + assert.equal(network.hasIPv6(), true); }); }); describe('Dynamic DNS', function () { it('can get default dyndns', async function () { - expect(await network.getDynamicDns()).to.be(false); + assert.equal(await network.getDynamicDns(), false); }); it('can set dyndns', async function () { @@ -137,13 +134,13 @@ describe('Network', function () { }); it('can get dyndns', async function () { - expect(await network.getDynamicDns()).to.be(true); + assert.equal(await network.getDynamicDns(), true); }); }); describe('Default interface', function () { it('can get default interface', async function () { - expect(await network.getDefaultInterface()).to.be.ok(); + assert.ok(await network.getDefaultInterface()); }); }); }); diff --git a/src/test/notifications-test.js b/src/test/notifications-test.js index b3dfdada8..8366e87cf 100644 --- a/src/test/notifications-test.js +++ b/src/test/notifications-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import notifications from '../notifications.js'; import safe from 'safetydance'; import timers from 'timers/promises'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ const EVENT_0 = { id: 'event_0', @@ -30,8 +27,8 @@ describe('Notifications', function () { it('can add notifications', async function () { for (let i = 0; i < 3; i++) { const [error, id] = await safe(notifications._add(notifications.TYPE_APP_UPDATED, `title ${i}`, `message ${i}`, { eventId: EVENT_0.id })); - expect(error).to.equal(null); - expect(id).to.be.a('string'); + assert.equal(error, null); + assert.equal(typeof id, 'string'); notificationIds.push(id); await timers.setTimeout(1000); } @@ -39,39 +36,39 @@ describe('Notifications', function () { it('can get by id', async function () { const [error, result] = await safe(notifications.get(notificationIds[0])); - expect(error).to.be(null); - expect(result.title).to.be('title 0'); - expect(result.type).to.be(notifications.TYPE_APP_UPDATED); - expect(result.message).to.be('message 0'); - expect(result.acknowledged).to.be(false); + assert.equal(error, null); + assert.equal(result.title, 'title 0'); + assert.equal(result.type, notifications.TYPE_APP_UPDATED); + assert.equal(result.message, 'message 0'); + assert.equal(result.acknowledged, false); }); it('cannot get non-existent id', async function () { const result = await notifications.get('random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can list notifications', async function () { const result = await notifications.list({}, 1, 10); - expect(result.length).to.be(3); - expect(result[0].title).to.be('title 2'); - expect(result[1].title).to.be('title 1'); - expect(result[2].title).to.be('title 0'); + assert.equal(result.length, 3); + assert.equal(result[0].title, 'title 2'); + assert.equal(result[1].title, 'title 1'); + assert.equal(result[2].title, 'title 0'); }); it('can update notification', async function () { await notifications.update({ id: notificationIds[0] }, { type: notifications.TYPE_APP_OOM, title: 'updated title 0', message: 'updated message 0', acknowledged: true }); const result = await notifications.get(notificationIds[0]); - expect(result.title).to.be('updated title 0'); - expect(result.type).to.be(notifications.TYPE_APP_OOM); - expect(result.message).to.be('updated message 0'); - expect(result.acknowledged).to.be(true); + assert.equal(result.title, 'updated title 0'); + assert.equal(result.type, notifications.TYPE_APP_OOM); + assert.equal(result.message, 'updated message 0'); + assert.equal(result.acknowledged, true); }); it('cannot update non-existent notification', async function () { const [error] = await safe(notifications.update({ id: '1245' }, { title: 'updated title 0', message: 'updated message 0', acknowledged: true })); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); @@ -81,7 +78,7 @@ describe('Notifications', function () { it('cannot delete non-existent notification', async function () { const [error] = await safe(notifications.del('5213')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); let pinId; @@ -90,40 +87,40 @@ describe('Notifications', function () { pinId = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xx is available', 'Awesome changelog', { context: 'xx' }); const result = await notifications.get(pinId); - expect(result.title).to.be('Cloudron xx is available'); - expect(result.message).to.be('Awesome changelog'); - expect(result.acknowledged).to.be(false); + assert.equal(result.title, 'Cloudron xx is available'); + assert.equal(result.message, 'Awesome changelog'); + assert.equal(result.acknowledged, false); }); it('updating pin with same message does nothing', async function () { await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert const id = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xx is available', 'Awesome changelog', { context: 'xx' }); - expect(id).to.be(pinId); + assert.equal(id, pinId); const result = await notifications.get(pinId); - expect(result.title).to.be('Cloudron xx is available'); - expect(result.message).to.be('Awesome changelog'); - expect(result.acknowledged).to.be(true); // notification does not resurface + assert.equal(result.title, 'Cloudron xx is available'); + assert.equal(result.message, 'Awesome changelog'); + assert.equal(result.acknowledged, true); // notification does not resurface }); it('updating pin with new message resurfaces', async function () { await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert const id = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xy is available', 'Awesome new changelog', { context: 'xx' }); - expect(id).to.be(pinId); + assert.equal(id, pinId); const result = await notifications.get(pinId); - expect(result.title).to.be('Cloudron xy is available'); - expect(result.message).to.be('Awesome new changelog'); - expect(result.acknowledged).to.be(false); // notification resurfaces + assert.equal(result.title, 'Cloudron xy is available'); + assert.equal(result.message, 'Awesome new changelog'); + assert.equal(result.acknowledged, false); // notification resurfaces }); it('can unpin', async function () { await notifications.unpin(notifications.TYPE_BOX_UPDATE, { context: 'xx' }); const result = await notifications.get(pinId); - expect(result.acknowledged).to.be(true); + assert.equal(result.acknowledged, true); }); }); @@ -132,28 +129,28 @@ describe('Notifications', function () { pinId = await notifications.pin(notifications.TYPE_REBOOT, 'Reboot required', 'Do it now', {}); const result = await notifications.get(pinId); - expect(result.title).to.be('Reboot required'); - expect(result.message).to.be('Do it now'); - expect(result.acknowledged).to.be(false); + assert.equal(result.title, 'Reboot required'); + assert.equal(result.message, 'Do it now'); + assert.equal(result.acknowledged, false); }); it('can update the alert', async function () { await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert const id = await notifications.pin(notifications.TYPE_REBOOT, 'Reboot required', 'Do it now', {}); - expect(id).to.be(pinId); + assert.equal(id, pinId); const result = await notifications.get(pinId); - expect(result.title).to.be('Reboot required'); - expect(result.message).to.be('Do it now'); - expect(result.acknowledged).to.be(false); // resurfaces + assert.equal(result.title, 'Reboot required'); + assert.equal(result.message, 'Do it now'); + assert.equal(result.acknowledged, false); // resurfaces }); it('can unpin', async function () { await notifications.unpin(notifications.TYPE_REBOOT, {}); const result = await notifications.get(pinId); - expect(result.acknowledged).to.be(true); + assert.equal(result.acknowledged, true); }); }); }); diff --git a/src/test/oidcclients-test.js b/src/test/oidcclients-test.js index 2c58a49f3..27febcd82 100644 --- a/src/test/oidcclients-test.js +++ b/src/test/oidcclients-test.js @@ -1,8 +1,8 @@ -/* global describe, before, it, after */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import oidcClients from '../oidcclients.js'; import safe from 'safetydance'; @@ -24,25 +24,25 @@ describe('OIDC Clients', function () { const result = await oidcClients.add(CLIENT_0); id = result.id; secret = result.secret; - expect(id).to.be.a('string'); - expect(secret).to.be.a('string'); + assert.equal(typeof id, 'string'); + assert.equal(typeof secret, 'string'); }); it('cannot get client', async function () { const client = await oidcClients.get(id); - expect(client.appId).to.be('someappid'); - expect(client.secret).to.be(secret); + assert.equal(client.appId, 'someappid'); + assert.equal(client.secret, secret); }); it('cannot get random client', async function () { const client = await oidcClients.get('random'); - expect(client).to.be(null); + assert.equal(client, null); }); it('can list clients', async function () { const clients = await oidcClients.list(); - expect(clients.length).to.be(1); - expect(clients[0].secret).to.be(secret); + assert.equal(clients.length, 1); + assert.equal(clients[0].secret, secret); }); it('can update client', async function () { @@ -51,14 +51,14 @@ describe('OIDC Clients', function () { await oidcClients.update(id, clientCopy); const client = await oidcClients.get(id); - expect(client.name).to.be('newname'); + assert.equal(client.name, 'newname'); }); it('cannot update random client', async function () { const clientCopy = Object.assign({}, CLIENT_0); clientCopy.name = 'newname'; const [error] = await safe(oidcClients.update('random', clientCopy)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can del client', async function () { @@ -67,6 +67,6 @@ describe('OIDC Clients', function () { it('cannot del random client', async function () { const [error] = await safe(oidcClients.del(id)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); diff --git a/src/test/openssl-test.js b/src/test/openssl-test.js index 6615e3f88..622b7130d 100644 --- a/src/test/openssl-test.js +++ b/src/test/openssl-test.js @@ -1,11 +1,10 @@ -/* global it:false */ +import { describe, it } from 'node:test'; import BoxError from '../boxerror.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import openssl from '../openssl.js'; import safe from 'safetydance'; -/* global describe:false */ describe('openssl', function () { describe('validateCertificate', function () { @@ -49,30 +48,30 @@ describe('openssl', function () { it('does not allow empty string for cert', async function () { const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: '', key: 'key' })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('does not allow empty string for key', async function () { const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: 'cert', key: '' })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('does not allow invalid cert', async function () { const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: 'someinvalidcert', key: validKey0 })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('does not allow invalid key', async function () { const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: 'invalidkey' })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('does not allow cert without matching domain', async function () { const [error] = await safe(openssl.validateCertificate('', 'cloudron.io', { cert: validCert0, key: validKey0 })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); const [error2] = await safe(openssl.validateCertificate('cloudron.io', foobarDomain, { cert: validCert0, key: validKey0 })); - expect(error2.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error2.reason, BoxError.BAD_FIELD); }); it('allows valid cert with matching domain', async function () { @@ -85,10 +84,10 @@ describe('openssl', function () { it('does now allow cert without matching domain (wildcard)', async function () { const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: validCert1, key: validKey1 })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); const [error2] = await safe(openssl.validateCertificate('bar.abc', foobarDomain, { cert: validCert1, key: validKey1 })); - expect(error2.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error2.reason, BoxError.BAD_FIELD); }); it('allows valid cert with matching domain (subdomain)', async function () { @@ -97,11 +96,11 @@ describe('openssl', function () { it('does not allow cert without matching domain (subdomain)', async function () { const [error] = await safe(openssl.validateCertificate('baz', foobarDomain, { cert: validCert0, key: validKey0 })); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('does not allow invalid cert/key tuple', async function () { - //expect(openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: validKey1 })).to.be.an(Error); + //assert.ok((openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: validKey1 })) instanceof (Error)); }); it('picks certificate in SAN', async function () { @@ -120,7 +119,7 @@ describe('openssl', function () { it('can generate fallback certs', async function () { result = await openssl.generateCertificate(domain); - expect(result).to.be.ok(); + assert.ok(result); }); it('can validate the certs', async function () { diff --git a/src/test/passkeys-test.js b/src/test/passkeys-test.js index 61e027d6e..b4f5ad816 100644 --- a/src/test/passkeys-test.js +++ b/src/test/passkeys-test.js @@ -1,17 +1,14 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import passkeys from '../passkeys.js'; import safe from 'safetydance'; import speakeasy from 'speakeasy'; import users from '../users.js'; import webauthnHelper from './webauthn-helper.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Passkeys', function () { const { domainSetup, cleanup, admin, auditSource, dashboardFqdn } = common; @@ -37,87 +34,87 @@ describe('Passkeys', function () { it('list returns empty', async function () { const result = await passkeys.listByUserId(admin.id); - expect(result).to.be.an(Array); - expect(result.length).to.be(0); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); }); it('can add a passkey', async function () { const { id } = await passkeys.add(admin.id, 'credId123', 'pubKeyBase64', 0, ['internal'], 'Test Key'); - expect(id).to.be.a('string'); - expect(id).to.match(/^pk-/); + assert.equal(typeof id, 'string'); + assert.match(String(id), /^pk-/); }); it('list returns one passkey', async function () { const result = await passkeys.listByUserId(admin.id); - expect(result.length).to.be(1); - expect(result[0].userId).to.be(admin.id); - expect(result[0].credentialId).to.be('credId123'); - expect(result[0].publicKey).to.be('pubKeyBase64'); - expect(result[0].counter).to.be(0); - expect(result[0].transports).to.eql(['internal']); - expect(result[0].name).to.be('Test Key'); + assert.equal(result.length, 1); + assert.equal(result[0].userId, admin.id); + assert.equal(result[0].credentialId, 'credId123'); + assert.equal(result[0].publicKey, 'pubKeyBase64'); + assert.equal(result[0].counter, 0); + assert.deepEqual(result[0].transports, ['internal']); + assert.equal(result[0].name, 'Test Key'); }); it('can get by id', async function () { const list = await passkeys.listByUserId(admin.id); const result = await passkeys.get(list[0].id); - expect(result).to.not.be(null); - expect(result.credentialId).to.be('credId123'); + assert.notEqual(result, null); + assert.equal(result.credentialId, 'credId123'); }); it('can get by credentialId', async function () { const result = await passkeys.getByCredentialId('credId123'); - expect(result).to.not.be(null); - expect(result.userId).to.be(admin.id); + assert.notEqual(result, null); + assert.equal(result.userId, admin.id); }); it('get returns null for unknown id', async function () { const result = await passkeys.get('pk-nonexistent'); - expect(result).to.be(null); + assert.equal(result, null); }); it('getByCredentialId returns null for unknown', async function () { const result = await passkeys.getByCredentialId('unknownCredId'); - expect(result).to.be(null); + assert.equal(result, null); }); it('rejects duplicate credentialId', async function () { const [error] = await safe(passkeys.add(admin.id, 'credId123', 'otherPubKey', 0, [], 'Dup')); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('can delete a passkey', async function () { const list = await passkeys.listByUserId(admin.id); await passkeys.del(list[0].id); const afterDel = await passkeys.listByUserId(admin.id); - expect(afterDel.length).to.be(0); + assert.equal(afterDel.length, 0); }); it('delete throws for unknown passkey', async function () { const [error] = await safe(passkeys.del('pk-nonexistent')); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('delAll clears all passkeys', async function () { await passkeys.add(admin.id, 'cred1', 'pk1', 0, [], 'Key1'); await passkeys.delAll(); const result = await passkeys.listByUserId(admin.id); - expect(result.length).to.be(0); + assert.equal(result.length, 0); }); it('removePrivateFields strips sensitive data', async function () { const { id } = await passkeys.add(admin.id, 'credStrip', 'pkStrip', 0, ['usb'], 'Strip Test'); const pk = await passkeys.get(id); const filtered = passkeys.removePrivateFields(pk); - expect(filtered.id).to.be(id); - expect(filtered.name).to.be('Strip Test'); - expect(filtered.creationTime).to.not.be(undefined); - expect(filtered.credentialId).to.be(undefined); - expect(filtered.publicKey).to.be(undefined); - expect(filtered.counter).to.be(undefined); - expect(filtered.userId).to.be(undefined); + assert.equal(filtered.id, id); + assert.equal(filtered.name, 'Strip Test'); + assert.notEqual(filtered.creationTime, undefined); + assert.equal(filtered.credentialId, undefined); + assert.equal(filtered.publicKey, undefined); + assert.equal(filtered.counter, undefined); + assert.equal(filtered.userId, undefined); await passkeys.del(id); }); @@ -131,12 +128,12 @@ describe('Passkeys', function () { it('can generate registration options', async function () { const adminUser = await users.get(admin.id); const options = await passkeys.getRegistrationOptions(adminUser); - expect(options).to.be.an(Object); - expect(options.challenge).to.be.a('string'); - expect(options.rp).to.be.an(Object); - expect(options.rp.name).to.be('Cloudron'); - expect(options.rp.id).to.be(dashboardFqdn); - expect(options.user).to.be.an(Object); + assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options)); + assert.equal(typeof options.challenge, 'string'); + assert.ok((options.rp) && typeof (options.rp) === 'object' && !Array.isArray(options.rp)); + assert.equal(options.rp.name, 'Cloudron'); + assert.equal(options.rp.id, dashboardFqdn); + assert.ok((options.user) && typeof (options.user) === 'object' && !Array.isArray(options.user)); }); it('can register with virtual authenticator', async function () { @@ -147,20 +144,20 @@ describe('Passkeys', function () { const response = await webauthnHelper.createRegistrationResponse(authenticator, options, origin); const result = await passkeys.verifyRegistration(adminUser, response, 'My Test Key'); - expect(result).to.be.an(Object); - expect(result.id).to.be.a('string'); - expect(result.id).to.match(/^pk-/); + assert.ok((result) && typeof (result) === 'object' && !Array.isArray(result)); + assert.equal(typeof result.id, 'string'); + assert.match(String(result.id), /^pk-/); const list = await passkeys.listByUserId(admin.id); - expect(list.length).to.be(1); - expect(list[0].name).to.be('My Test Key'); + assert.equal(list.length, 1); + assert.equal(list[0].name, 'My Test Key'); }); it('rejects duplicate registration', async function () { const adminUser = await users.get(admin.id); const [error] = await safe(passkeys.getRegistrationOptions(adminUser)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cleanup passkey for further tests', async function () { @@ -177,7 +174,7 @@ describe('Passkeys', function () { const response = await webauthnHelper.createRegistrationResponse(authenticator, options, origin); const [error] = await safe(passkeys.verifyRegistration(adminUser, response, 'Bad Key')); - expect(error).to.not.be(null); + assert.notEqual(error, null); }); it('rejects registration when TOTP is enabled', async function () { @@ -191,8 +188,8 @@ describe('Passkeys', function () { adminUser.twoFactorAuthenticationEnabled = true; const [error] = await safe(passkeys.getRegistrationOptions(adminUser)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); // disable TOTP for further tests await users.disableTwoFactorAuthentication(adminUser, auditSource); @@ -217,10 +214,10 @@ describe('Passkeys', function () { it('can generate authentication options', async function () { const adminUser = await users.get(admin.id); const options = await passkeys.getAuthenticationOptions(adminUser); - expect(options).to.be.an(Object); - expect(options.challenge).to.be.a('string'); - expect(options.allowCredentials).to.be.an(Array); - expect(options.allowCredentials.length).to.be(1); + assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options)); + assert.equal(typeof options.challenge, 'string'); + assert.ok(Array.isArray(options.allowCredentials)); + assert.equal(options.allowCredentials.length, 1); }); it('can authenticate with virtual authenticator', async function () { @@ -229,15 +226,15 @@ describe('Passkeys', function () { const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin); const result = await passkeys.verifyAuthentication(adminUser, response); - expect(result).to.be.an(Object); - expect(result.verified).to.be(true); - expect(result.passkeyId).to.be.a('string'); + assert.ok((result) && typeof (result) === 'object' && !Array.isArray(result)); + assert.equal(result.verified, true); + assert.equal(typeof result.passkeyId, 'string'); }); it('counter was updated after authentication', async function () { const list = await passkeys.listByUserId(admin.id); - expect(list[0].counter).to.be(1); - expect(list[0].lastUsedTime).to.not.be(null); + assert.equal(list[0].counter, 1); + assert.notEqual(list[0].lastUsedTime, null); }); it('can authenticate again (counter increments)', async function () { @@ -246,10 +243,10 @@ describe('Passkeys', function () { const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin); const result = await passkeys.verifyAuthentication(adminUser, response); - expect(result.verified).to.be(true); + assert.equal(result.verified, true); const list = await passkeys.listByUserId(admin.id); - expect(list[0].counter).to.be(2); + assert.equal(list[0].counter, 2); }); it('rejects authentication with wrong credential', async function () { @@ -261,8 +258,8 @@ describe('Passkeys', function () { const response = await webauthnHelper.createAuthenticationResponse(fakeAuth, options, origin); const [error] = await safe(passkeys.verifyAuthentication(adminUser, response)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('rejects authentication with tampered challenge', async function () { @@ -272,7 +269,7 @@ describe('Passkeys', function () { const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin); const [error] = await safe(passkeys.verifyAuthentication(adminUser, response)); - expect(error).to.not.be(null); + assert.notEqual(error, null); }); it('fails to generate auth options when no passkey registered', async function () { @@ -280,8 +277,8 @@ describe('Passkeys', function () { const adminUser = await users.get(admin.id); const [error] = await safe(passkeys.getAuthenticationOptions(adminUser)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.NOT_FOUND); }); }); @@ -302,8 +299,8 @@ describe('Passkeys', function () { const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' }); const [error] = await safe(users.enableTwoFactorAuthentication(adminUser, totpToken, auditSource)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); await passkeys.delAll(); }); @@ -319,8 +316,8 @@ describe('Passkeys', function () { adminUser.twoFactorAuthenticationEnabled = true; const [error] = await safe(passkeys.getRegistrationOptions(adminUser)); - expect(error).to.not.be(null); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.notEqual(error, null); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); // cleanup await users.disableTwoFactorAuthentication(adminUser, auditSource); diff --git a/src/test/progress-stream-test.js b/src/test/progress-stream-test.js index c1b9ac4f8..1896dbc4b 100644 --- a/src/test/progress-stream-test.js +++ b/src/test/progress-stream-test.js @@ -1,24 +1,24 @@ -/* global it:false */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import ProgressStream from '../progress-stream.js'; import stream from 'node:stream'; -/* global describe:false */ describe('progress stream', function () { - it('can create stream', function (done) { + it('can create stream', async function () { const input = fs.createReadStream(`${import.meta.dirname}/progress-stream-test.js`); const progress = new ProgressStream({ interval: 1000 }); const output = fs.createWriteStream('/dev/null'); - stream.pipeline(input, progress, output, function (error) { - expect(error).to.not.be.ok(); - const size = fs.statSync(`${import.meta.dirname}/progress-stream-test.js`).size; - expect(progress.stats().transferred).to.be(size); - - done(); + await new Promise((resolve, reject) => { + stream.pipeline(input, progress, output, function (error) { + if (error) return reject(error); + resolve(); + }); }); + const size = fs.statSync(`${import.meta.dirname}/progress-stream-test.js`).size; + assert.equal(progress.stats().transferred, size); }); }); diff --git a/src/test/promise-retry-test.js b/src/test/promise-retry-test.js index ed31896a9..510ae331d 100644 --- a/src/test/promise-retry-test.js +++ b/src/test/promise-retry-test.js @@ -1,21 +1,18 @@ +import { describe, it } from 'node:test'; /* jslint node:true */ -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import promiseRetry from '../promise-retry.js'; import safe from 'safetydance'; -/* global it:false */ -/* global describe:false */ describe('promiseRetry', function () { - this.timeout(0); - it('normal return', async function () { const result = await promiseRetry({ times: 5, interval: 1000 }, async () => { return 42; }); - expect(result).to.be(42); + assert.equal(result, 42); }); it('throws error', async function () { @@ -23,7 +20,7 @@ describe('promiseRetry', function () { throw new Error('42'); })); - expect(error.message).to.be('42'); + assert.equal(error.message, '42'); }); it('3 tries', async function () { @@ -32,7 +29,7 @@ describe('promiseRetry', function () { if (++tryCount == 3) return 42; else throw new Error('42'); }); - expect(result).to.be(42); + assert.equal(result, 42); }); it('can abort with 1 try only', async function () { @@ -42,7 +39,7 @@ describe('promiseRetry', function () { throw tryCount; })); - expect(tryCount).to.be(1); - expect(error).to.be(1); + assert.equal(tryCount, 1); + assert.equal(error, 1); }); }); diff --git a/src/test/provision-test.js b/src/test/provision-test.js index 8ff3b0674..e5805a513 100644 --- a/src/test/provision-test.js +++ b/src/test/provision-test.js @@ -1,16 +1,13 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import appstore from '../appstore.js'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import provision from '../provision.js'; import safe from 'safetydance'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Provision', function () { const { domainSetup, auditSource, cleanup } = common; @@ -24,7 +21,7 @@ describe('Provision', function () { it('cannot activate when appstore unreachable', async function () { const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource)); - expect(error.reason).to.be(BoxError.NETWORK_ERROR); + assert.equal(error.reason, BoxError.NETWORK_ERROR); }); it('cannot activate with non-201', async function () { @@ -33,8 +30,8 @@ describe('Provision', function () { .reply(401, {}); const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource)); - expect(error.reason).to.be(BoxError.EXTERNAL_ERROR); - expect(scope1.isDone()).to.be.ok(); + assert.equal(error.reason, BoxError.EXTERNAL_ERROR); + assert.ok(scope1.isDone()); scope1.persist(false); }); @@ -44,8 +41,8 @@ describe('Provision', function () { .reply(201, { id: '32' }); const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource)); - expect(error.reason).to.be(BoxError.EXTERNAL_ERROR); - expect(scope1.isDone()).to.be.ok(); + assert.equal(error.reason, BoxError.EXTERNAL_ERROR); + assert.ok(scope1.isDone()); scope1.persist(false); }); @@ -59,10 +56,10 @@ describe('Provision', function () { .reply(200, { features: {} }); await provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource); - expect(scope1.isDone()).to.be.ok(); + assert.ok(scope1.isDone()); scope1.persist(false); - expect(scope2.isDone()).to.be.ok(); + assert.ok(scope2.isDone()); scope2.persist(false); }); }); diff --git a/src/test/reverseproxy-test.js b/src/test/reverseproxy-test.js index e9eae1f13..f6507b803 100644 --- a/src/test/reverseproxy-test.js +++ b/src/test/reverseproxy-test.js @@ -1,15 +1,12 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; import domains from '../domains.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import paths from '../paths.js'; import reverseProxy from '../reverseproxy.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Reverse Proxy', function () { const { setup, cleanup, domain, auditSource, app } = common; @@ -27,12 +24,14 @@ describe('Reverse Proxy', function () { it('configure nginx correctly', async function () { await reverseProxy.configureApp(app, auditSource); - expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + app.id + '.conf')); + const appConfigDir = `${paths.NGINX_APPCONFIG_DIR}/${app.id}`; + assert.ok(fs.existsSync(appConfigDir)); + assert.ok(fs.readdirSync(appConfigDir).some((f) => f.endsWith('.conf'))); }); it('unconfigure nginx', async function () { await reverseProxy.unconfigureApp(app); - expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + app.id + '.conf')); + assert.ok(!fs.existsSync(`${paths.NGINX_APPCONFIG_DIR}/${app.id}`)); }); }); }); diff --git a/src/test/server-test.js b/src/test/server-test.js index 764df0f76..e6018d1fe 100644 --- a/src/test/server-test.js +++ b/src/test/server-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import constants from '../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import server from '../server.js'; import superagent from '@cloudron/superagent'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ const SERVER_URL = 'http://localhost:' + constants.PORT; @@ -23,12 +20,12 @@ describe('Server', function () { it('is reachable', async function () { const response = await superagent.get(SERVER_URL + '/api/v1/cloudron/status'); - expect(response.status).to.equal(200); + assert.equal(response.status, 200); }); it('should fail because already running', async function () { const [error] = await safe(server.start()); - expect(error).to.be.ok(); + assert.ok(error); }); }); @@ -38,21 +35,21 @@ describe('Server', function () { it('random bad superagents', async function () { const response = await superagent.get(SERVER_URL + '/random').ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); }); it('version', async function () { const response = await superagent.get(SERVER_URL + '/api/v1/cloudron/status'); - expect(response.status).to.equal(200); - expect(response.body.version).to.contain('-test'); + assert.equal(response.status, 200); + assert.ok(response.body.version.includes('-test')); }); it('status route is GET', async function () { const response = await superagent.post(SERVER_URL + '/api/v1/cloudron/status').ok(() => true); - expect(response.status).to.equal(404); + assert.equal(response.status, 404); const response2 = await superagent.get(SERVER_URL + '/api/v1/cloudron/status'); - expect(response2.status).to.equal(200); + assert.equal(response2.status, 200); }); }); @@ -62,12 +59,12 @@ describe('Server', function () { it('config fails due missing token', async function () { const response = await superagent.get(SERVER_URL + '/api/v1/dashboard/config').ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); it('config fails due wrong token', async function () { const response = await superagent.get(SERVER_URL + '/api/v1/dashboard/config').query({ access_token: 'somewrongtoken' }).ok(() => true); - expect(response.status).to.equal(401); + assert.equal(response.status, 401); }); }); @@ -76,7 +73,7 @@ describe('Server', function () { it('is not reachable anymore', async function () { const [error] = await safe(superagent.get(SERVER_URL + '/api/v1/cloudron/status').ok(() => true)); - expect(error).to.not.be(null); + assert.notEqual(error, null); }); }); }); diff --git a/src/test/shell-test.js b/src/test/shell-test.js index bd4c0f349..6a24f0adb 100644 --- a/src/test/shell-test.js +++ b/src/test/shell-test.js @@ -1,15 +1,14 @@ +import { describe, it } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import path from 'node:path'; import safe from 'safetydance'; import shellModule from '../shell.js'; const shell = shellModule('test'); -/* global it:false */ -/* global describe:false */ describe('shell', function () { describe('spawn', function () { @@ -19,12 +18,12 @@ describe('shell', function () { it('fails on invalid program', async function () { const [error] = await safe(shell.spawn('randomprogram', [], {})); - expect(error.reason).to.be(BoxError.SHELL_ERROR); + assert.equal(error.reason, BoxError.SHELL_ERROR); }); it('fails on failing program', async function () { const [error] = await safe(shell.spawn('/usr/bin/false', [], {})); - expect(error.reason).to.be(BoxError.SHELL_ERROR); + assert.equal(error.reason, BoxError.SHELL_ERROR); }); }); @@ -35,56 +34,56 @@ describe('shell', function () { it('maxLines=2 kills the process (stdout)', async function () { const [error] = await safe(shell.bash('for i in {1..10}; do echo $i; sleep 1; done', { encoding: 'utf8', maxLines: 2})); - expect(error).to.be.ok(); - expect(error.stdoutLineCount).to.be(2); + assert.ok(error); + assert.equal(error.stdoutLineCount, 2); }); it('maxLines=2 kills the process (stderr)', async function () { const [error] = await safe(shell.bash('for i in {1..10}; do echo $i >&2; sleep 1; done', { encoding: 'utf8', maxLines: 2})); - expect(error).to.be.ok(); - expect(error.stderrLineCount).to.be(2); + assert.ok(error); + assert.equal(error.stderrLineCount, 2); }); }); describe('sudo', function () { it('cannot sudo invalid program', async function () { const [error] = await safe(shell.sudo([ 'randomprogram' ], {})); - expect(error).to.be.ok(); + assert.ok(error); }); it('can sudo valid program', async function () { const RELOAD_NGINX_CMD = path.join(import.meta.dirname, '../src/scripts/restartservice.sh'); const [error] = await safe(shell.sudo([ RELOAD_NGINX_CMD, 'nginx' ], {})); - expect(error).to.be.ok(); + assert.ok(error); }); }); describe('spawn', function () { it('spawn throws for invalid program', async function () { const [error] = await safe(shell.spawn('cannotexist', [], {})); - expect(error.reason).to.be(BoxError.SHELL_ERROR); + assert.equal(error.reason, BoxError.SHELL_ERROR); }); it('spawn throws for failed program', async function () { const [error] = await safe(shell.spawn('false', [], {})); - expect(error.reason).to.be(BoxError.SHELL_ERROR); + assert.equal(error.reason, BoxError.SHELL_ERROR); }); it('spawn times out properly', async function () { const [error] = await safe(shell.spawn('sleep', ['20'], { timeout: 1000 })); - expect(error.reason).to.be(BoxError.SHELL_ERROR); + assert.equal(error.reason, BoxError.SHELL_ERROR); }); }); describe('bash', function () { it('can bash a shell program', async function () { const out = await shell.bash('ls -l | wc -c', {}); - expect(Buffer.isBuffer(out)).to.be(true); + assert.equal(Buffer.isBuffer(out), true); }); it('can bash a shell program', async function () { const out = await shell.bash('ls -l | wc -c', { encoding: 'utf8' }); - expect(out).to.be.a('string'); + assert.equal(typeof out, 'string'); }); }); }); diff --git a/src/test/storage-provider-test.js b/src/test/storage-provider-test.js index 89e70b832..baa16616b 100644 --- a/src/test/storage-provider-test.js +++ b/src/test/storage-provider-test.js @@ -1,11 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import backupSites from '../backupsites.js'; import BoxError from '../boxerror.js'; import common from './common.js'; import consumers from 'node:stream/consumers'; import { execSync } from 'node:child_process'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import filesystem from '../storage/filesystem.js'; import fs from 'node:fs'; import gcs from '../storage/gcs.js'; @@ -15,10 +15,6 @@ import s3 from '../storage/s3.js'; import safe from 'safetydance'; import stream from 'stream/promises'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ -/* global xit:false */ describe('Storage', function () { const { setup, cleanup, getDefaultBackupSite, auditSource } = common; @@ -44,20 +40,19 @@ describe('Storage', function () { gBackupConfig.backupDir = path.join(gTmpFolder, 'backups/'); }); - after(function (done) { + after(function () { fs.rmSync(gTmpFolder, { recursive: true, force: true }); - done(); }); it('fails to set backup storage for bad folder', async function () { const tmp = Object.assign({}, gBackupConfig, { backupDir: '/root/oof' }); const [error] = await safe(backupSites.setConfig(defaultBackupSite, tmp, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('succeeds to set backup storage', async function () { await backupSites.setConfig(defaultBackupSite, gBackupConfig, auditSource); - expect(fs.existsSync(path.join(gBackupConfig.backupDir, 'someprefix/snapshot'))).to.be(true); // auto-created + assert.equal(fs.existsSync(path.join(gBackupConfig.backupDir, 'someprefix/snapshot')), true); // auto-created }); it('can upload', async function () { @@ -67,19 +62,19 @@ describe('Storage', function () { const uploader = await filesystem.upload(gBackupConfig, {}, 'uploadtest/test.txt'); await stream.pipeline(sourceStream, uploader.createStream()); await uploader.finish(); - expect(fs.existsSync(destFile)); - expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size); + assert.ok(fs.existsSync(destFile)); + assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size); }); - xit('upload waits for empty file to be created', async function () { + it.skip('upload waits for empty file to be created', async function () { const sourceFile = path.join(import.meta.dirname, 'storage/data/empty'); const sourceStream = fs.createReadStream(sourceFile); const destFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/empty'); const uploader = await filesystem.upload(gBackupConfig, {}, destFile); await stream.pipeline(sourceStream, uploader.createStream()); await uploader.finish(); - expect(fs.existsSync(destFile)); - expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size); + assert.ok(fs.existsSync(destFile)); + assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size); }); it('upload unlinks old file', async function () { @@ -90,23 +85,23 @@ describe('Storage', function () { const uploader = await filesystem.upload(gBackupConfig, {}, 'uploadtest/test.txt'); await stream.pipeline(sourceStream, uploader.createStream()); await uploader.finish(); - expect(fs.existsSync(destFile)).to.be(true); - expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size); - expect(oldStat.inode).to.not.be(fs.statSync(destFile).size); + assert.equal(fs.existsSync(destFile), true); + assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size); + assert.notEqual(oldStat.inode, fs.statSync(destFile).size); }); it('can download file', async function () { const sourceFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test.txt'); const [error, downloadStream] = await safe(filesystem.download(gBackupConfig, 'uploadtest/test.txt')); - expect(error).to.be(null); - expect(downloadStream).to.be.an('object'); + assert.equal(error, null); + assert.equal(typeof downloadStream, 'object'); const data = await consumers.buffer(downloadStream); - expect(fs.readFileSync(sourceFile)).to.eql(data); // buffer compare + assert.deepEqual(fs.readFileSync(sourceFile), data); // buffer compare }); it('download errors for missing file', async function () { const [error] = await safe(filesystem.download(gBackupConfig, 'uploadtest/missing')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('list dir lists the source dir', async function () { @@ -122,7 +117,7 @@ describe('Storage', function () { } const expectedFiles = execSync(`find . -type f -printf '%P\n'`, { cwd: sourceDir, encoding: 'utf8' }).trim().split('\n').map(p => `storage/${p}`); - expect(allFiles.map(function (f) { return f.path; }).sort()).to.eql(expectedFiles.sort()); + assert.deepEqual(allFiles.map(function (f) { return f.path; }).sort(), expectedFiles.sort()); }); it('can copy', async function () { @@ -130,14 +125,14 @@ describe('Storage', function () { const destFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test-hardlink.txt'); await filesystem.copy(gBackupConfig, 'uploadtest/test.txt', 'uploadtest/test-hardlink.txt', () => {}); - expect(fs.statSync(destFile).nlink).to.be(2); // created a hardlink + assert.equal(fs.statSync(destFile).nlink, 2); // created a hardlink }); it('can remove file', async function () { const sourceFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test-hardlink.txt'); await filesystem.remove(gBackupConfig, 'uploadtest/test-hardlink.txt'); - expect(fs.existsSync(sourceFile)).to.be(false); + assert.equal(fs.existsSync(sourceFile), false); }); it('can remove empty dir', async function () { @@ -145,7 +140,7 @@ describe('Storage', function () { fs.mkdirSync(sourceDir); await filesystem.remove(gBackupConfig, 'emptydir', () => {}); - expect(fs.existsSync(sourceDir)).to.be(false); + assert.equal(fs.existsSync(sourceDir), false); }); }); @@ -181,21 +176,21 @@ describe('Storage', function () { class S3Mock { constructor(cfg) { - expect(cfg.credentials).to.eql({ // retryDelayOptions is a function + assert.deepEqual(cfg.credentials, { // retryDelayOptions is a function accessKeyId: backupConfig.accessKeyId, secretAccessKey: backupConfig.secretAccessKey }); - expect(cfg.region).to.be(backupConfig.region); + assert.equal(cfg.region, backupConfig.region); } async headObject(params) { - expect(params.Bucket).to.be(backupConfig.bucket); + assert.equal(params.Bucket, backupConfig.bucket); const stat = await fs.promises.stat(path.join(bucketPathNoPrefix, params.Key)); return { ContentLength: stat.size }; } async listObjectsV2(params) { - expect(params.Bucket).to.be(backupConfig.bucket); + assert.equal(params.Bucket, backupConfig.bucket); return { Contents: [{ Key: `${backupConfig.prefix}/uploadtest/test.txt`, @@ -218,12 +213,12 @@ describe('Storage', function () { } async deleteObject(params) { - expect(params.Bucket).to.be(backupConfig.bucket); + assert.equal(params.Bucket, backupConfig.bucket); fs.rmSync(path.join(bucketPathNoPrefix, params.Key)); } async deleteObjects(params) { - expect(params.Bucket).to.be(backupConfig.bucket); + assert.equal(params.Bucket, backupConfig.bucket); params.Delete.Objects.forEach(o => fs.rmSync(path.join(bucketPathNoPrefix, o.Key))); } } @@ -247,15 +242,15 @@ describe('Storage', function () { const uploader = await s3.upload(backupConfig, {}, destKey); await stream.pipeline(sourceStream, uploader.createStream()); await uploader.finish(); - expect(fs.existsSync(path.join(bucketPath, destKey))).to.be(true); - expect(fs.statSync(path.join(bucketPath, destKey)).size).to.be(fs.statSync(sourceFile).size); + assert.equal(fs.existsSync(path.join(bucketPath, destKey)), true); + assert.equal(fs.statSync(path.join(bucketPath, destKey)).size, fs.statSync(sourceFile).size); }); it('can download file', async function () { const sourceKey = 'uploadtest/test.txt'; const [error, outstream] = await safe(s3.download(backupConfig, sourceKey)); - expect(error).to.be(null); - expect(outstream).to.be.an('object'); + assert.equal(error, null); + assert.equal(typeof outstream, 'object'); }); it('list dir lists contents of source dir', async function () { @@ -268,7 +263,7 @@ describe('Storage', function () { marker = result.marker; } - expect(allFiles.map(function (f) { return f.path; })).to.contain('uploadtest/test.txt'); + assert.ok(allFiles.map(function (f) { return f.path; }).includes('uploadtest/test.txt')); }); it('can copy', async function () { @@ -276,18 +271,18 @@ describe('Storage', function () { await s3.copyDir(backupConfig, {}, 'uploadtest', 'uploadtest-copy', () => {}); const sourceFile = path.join(import.meta.dirname, 'storage/data/test.txt'); - expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size).to.be(fs.statSync(sourceFile).size); - expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size).to.be(7); + assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size, fs.statSync(sourceFile).size); + assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size, 7); }); it('can remove file', async function () { await s3.remove(backupConfig, 'uploadtest/test.txt'); - expect(fs.existsSync(path.join(bucketPath, 'uploadtest/test.txt'))).to.be(false); + assert.equal(fs.existsSync(path.join(bucketPath, 'uploadtest/test.txt')), false); }); it('cannot remove non-existent file', async function () { const [error] = await safe(s3.remove(backupConfig, 'blah')); - expect(error).to.be.ok(); + assert.ok(error); }); }); @@ -310,7 +305,7 @@ describe('Storage', function () { class GCSMockBucket { constructor(name) { - expect(name).to.be(backupConfig.bucket); + assert.equal(name, backupConfig.bucket); } file(key) { // already has prefix // console.log('gcs file object:', key); @@ -344,8 +339,8 @@ describe('Storage', function () { }; } async getFiles(q) { - expect(q.maxResults).to.be.a('number'); - expect(q.prefix).to.be.a('string'); + assert.equal(typeof q.maxResults, 'number'); + assert.equal(typeof q.prefix, 'string'); const files = [{ name: `${backupConfig.prefix}/uploadtest/test.txt`, @@ -359,8 +354,8 @@ describe('Storage', function () { class GCSMock { constructor(config) { - expect(config.projectId).to.be(backupConfig.projectId); - expect(config.credentials.private_key).to.be(backupConfig.credentials.private_key); + assert.equal(config.projectId, backupConfig.projectId); + assert.equal(config.credentials.private_key, backupConfig.credentials.private_key); } bucket(name) { @@ -384,15 +379,15 @@ describe('Storage', function () { const uploader = await gcs.upload(backupConfig, {}, destKey); await stream.pipeline(sourceStream, uploader.createStream()); await uploader.finish(); - expect(fs.existsSync(path.join(bucketPath, destKey))).to.be(true); - expect(fs.statSync(path.join(bucketPath, destKey)).size).to.be(fs.statSync(sourceFile).size); + assert.equal(fs.existsSync(path.join(bucketPath, destKey)), true); + assert.equal(fs.statSync(path.join(bucketPath, destKey)).size, fs.statSync(sourceFile).size); }); it('can download file', async function () { const sourceKey = 'uploadtest/test.txt'; const [error, downloadStream] = await safe(gcs.download(backupConfig, sourceKey)); - expect(error).to.be(null); - expect(downloadStream).to.be.an('object'); + assert.equal(error, null); + assert.equal(typeof downloadStream, 'object'); }); it('list dir lists contents of source dir', async function () { @@ -405,7 +400,7 @@ describe('Storage', function () { marker = result.marker; } - expect(allFiles.map(function (f) { return f.path; })).to.contain('uploadtest/test.txt'); + assert.ok(allFiles.map(function (f) { return f.path; }).includes('uploadtest/test.txt')); }); it('can copy', async function () { @@ -413,13 +408,13 @@ describe('Storage', function () { await gcs.copyDir(backupConfig, {}, 'uploadtest', 'uploadtest-copy', () => {}); const sourceFile = path.join(import.meta.dirname, 'storage/data/test.txt'); - expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size).to.be(fs.statSync(sourceFile).size); - expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size).to.be(7); + assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size, fs.statSync(sourceFile).size); + assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size, 7); }); it('can remove file', async function () { await gcs.remove(backupConfig, 'uploadtest-copy/test.txt'); - expect(fs.existsSync(path.join(basePath, 'uploadtest-copy/test.txt'))).to.be(false); + assert.equal(fs.existsSync(path.join(basePath, 'uploadtest-copy/test.txt')), false); }); it('can remove non-existent dir', async function () { diff --git a/src/test/superagent-test.js b/src/test/superagent-test.js index eca5954d4..804af73cd 100644 --- a/src/test/superagent-test.js +++ b/src/test/superagent-test.js @@ -1,10 +1,9 @@ -/* global it:false */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import superagent from '@cloudron/superagent'; -/* global describe:false */ describe('Superagent', function () { it('can get URL', async function () { @@ -13,40 +12,40 @@ describe('Superagent', function () { it('cannot get invalid URL', async function () { const [error] = await safe(superagent.get('htt://www.cloudron.io')); - expect(error).to.be.ok(); + assert.ok(error); }); it('cannot get non-existent domain', async function () { const [error] = await safe(superagent.get('https://www.cloudron.io.nxdomain')); - expect(error).to.be.ok(); + assert.ok(error); }); it('throws for 404', async function () { const [error] = await safe(superagent.get('https://www.cloudron.io/no-such-page')); - expect(error).to.be.ok(); - expect(error.status).to.be(404); - expect(error.text).to.be.a('string'); + assert.ok(error); + assert.equal(error.status, 404); + assert.equal(typeof error.text, 'string'); }); it('can catch a 404', async function () { const response = await superagent.get('https://www.cloudron.io/no-such-page').ok(({status}) => status === 404); - expect(response.status).to.be(404); - expect(response.text).to.be.a('string'); + assert.equal(response.status, 404); + assert.equal(typeof response.text, 'string'); }); it('did parse json', async function () { const response = await superagent.get('https://ipv4.api.cloudron.io/api/v1/helper/public_ip'); - expect(response.body.ip).to.be.ok(); + assert.ok(response.body.ip); }); it('follows redirect', async function () { const response = await superagent.get('https://cloudron.io').set('User-Agent', 'Mozilla').timeout(10*1000); - expect(response.url.toString()).to.be('https://www.cloudron.io/'); + assert.equal(response.url.toString(), 'https://www.cloudron.io/'); }); it('can disable redirects', async function () { const [error] = await safe(superagent.get('https://cloudron.io').set('User-Agent', 'Mozilla').timeout(10*1000).redirects(0)); - expect(error).to.be.ok(); + assert.ok(error); }); it('can disable certs', async function () { diff --git a/src/test/syncer-test.js b/src/test/syncer-test.js index 2153e7ef3..b1a7e35e4 100644 --- a/src/test/syncer-test.js +++ b/src/test/syncer-test.js @@ -1,10 +1,10 @@ -/* global it:false */ +import { describe, it, before } from 'node:test'; import common from './common.js'; const { createTree } = common; import DataLayout from '../datalayout.js'; import { execSync } from 'node:child_process'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; @@ -12,8 +12,6 @@ import paths from '../paths.js'; import safe from 'safetydance'; import syncer from '../syncer.js'; -/* global describe:false */ -/* global before:false */ const gTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'syncer-test')), gCacheFile = path.join(paths.BACKUP_INFO_DIR, 'syncer-test.sync.cache'); @@ -49,11 +47,11 @@ describe('Syncer', function () { // for every 'delete' operation, there must be no entry in the cache file for (const change of changes) { if (change.operation === 'add') { - expect(pathMap.get(change.path).integrity.sha256).to.be('fake-sha256'); - expect(pathMap.get(change.path).stat).to.be.an('object'); + assert.equal(pathMap.get(change.path).integrity.sha256, 'fake-sha256'); + assert.equal(typeof pathMap.get(change.path).stat, 'object'); } else if (change.operation === 'remove') { // if a file was removed, it won't be in pathMap. but if the file became a dir, it can be in pathMap without integrity info - expect(!pathMap.has(change.path) || !pathMap.get(change.path).integrity).to.be(true); + assert.equal(!pathMap.has(change.path) || !pathMap.get(change.path).integrity, true); } } } @@ -64,9 +62,9 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); const changes = await getChanges(dataLayout); - expect(changes).to.eql([{ operation: 'removedir', path: '', reason: 'nocache' }]); + assert.deepEqual(changes, [{ operation: 'removedir', path: '', reason: 'nocache' }]); - expect(fs.readFileSync(gCacheFile, 'utf8')).to.be(''); + assert.equal(fs.readFileSync(gCacheFile, 'utf8'), ''); }); it('empty cache - adds all', async function () { @@ -76,7 +74,7 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); const changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'add', path: 'src/index.js', reason: 'new', position: 0 }, { operation: 'add', path: 'test/test.js', reason: 'new', position: 1 }, { operation: 'add', path: 'walrus', reason: 'new', position: 2 } @@ -92,7 +90,7 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); const changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'add', path: 'a/b/c/d/e', reason: 'new', position: 0 } ]); @@ -106,7 +104,7 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); const changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'add', path: 'readme', reason: 'new', position: 0 } ]); @@ -120,13 +118,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(3); + assert.equal(changes.length, 3); execSync('touch src/index.js test/test.js', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'add', path: 'src/index.js', reason: 'changed', position: 0 }, { operation: 'add', path: 'test/test.js', reason: 'changed', position: 1 } ]); @@ -141,13 +139,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(3); + assert.equal(changes.length, 3); execSync('rm src/index.js walrus', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'remove', path: 'src/index.js', reason: 'missing' }, { operation: 'remove', path: 'walrus', reason: 'missing' } ]); @@ -162,13 +160,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(3); + assert.equal(changes.length, 3); execSync('rm -rf src test', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'removedir', path: 'src', reason: 'missing' }, { operation: 'removedir', path: 'test', reason: 'missing' } ]); @@ -183,13 +181,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(3); + assert.equal(changes.length, 3); execSync('find . -delete', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'removedir', path: 'src', reason: 'missing' }, { operation: 'removedir', path: 'test', reason: 'missing' }, { operation: 'remove', path: 'walrus', reason: 'missing' } @@ -205,13 +203,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(1); + assert.equal(changes.length, 1); execSync('rm -r a/b; touch a/f', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'removedir', path: 'a/b', reason: 'missing' }, { operation: 'add', path: 'a/f', reason: 'new', position: 0 } ]); @@ -226,13 +224,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(3); + assert.equal(changes.length, 3); execSync('rm data/test/test.js; mkdir data/test/test.js; touch data/test/test.js/trick', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'remove', path: 'data/test/test.js', reason: 'wasfile' }, { operation: 'add', path: 'data/test/test.js/trick', reason: 'new', position: 0 } ]); @@ -247,13 +245,13 @@ describe('Syncer', function () { const dataLayout = new DataLayout(gTmpDir, []); let changes = await getChanges(dataLayout); - expect(changes.length).to.be(4); + assert.equal(changes.length, 4); execSync('rm -r test; touch test', { cwd: gTmpDir }); changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'removedir', path: 'test', reason: 'wasdir' }, { operation: 'add', path: 'test', reason: 'wasdir', position: 0 } ]); @@ -296,7 +294,7 @@ describe('Syncer', function () { changes = await getChanges(dataLayout); - expect(changes).to.eql([ + assert.deepEqual(changes, [ { operation: 'remove', path: 'a', reason: 'wasfile' }, { operation: 'remove', path: 'a2', reason: 'missing' }, { operation: 'remove', path: 'file', reason: 'missing' }, @@ -311,7 +309,7 @@ describe('Syncer', function () { changes = await getChanges(dataLayout); - expect(changes.length).to.be(0); + assert.equal(changes.length, 0); checkCache(gCacheFile, changes); }); diff --git a/src/test/syslog-test.js b/src/test/syslog-test.js index d9e37a176..eed93b461 100644 --- a/src/test/syslog-test.js +++ b/src/test/syslog-test.js @@ -1,7 +1,7 @@ #!/usr/bin/env node -/* global it:false */ +import { describe, it, after } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import net from 'node:net'; import path from 'node:path'; @@ -10,8 +10,6 @@ import safe from 'safetydance'; import syslogServer from '../../syslog.js'; import timers from 'timers/promises'; -/* global describe:false */ -/* global after:false */ async function sendMessage(message) { const client = net.createConnection(paths.SYSLOG_SOCKET_FILE); @@ -34,8 +32,7 @@ async function verifyMessage(pattern, fileName) { if (found === null) throw new Error(`${pattern} not found in ${fileName}`); } -describe('Syslog', function () { - this.timeout(5000); +describe('Syslog', { timeout: 5000 }, function () { after(async function () { await syslogServer.stop(); @@ -57,7 +54,7 @@ describe('Syslog', function () { const invalidLine = 'foobar'; await sendMessage(invalidLine); const [error] = await safe(verifyMessage(/foobar/, 'testapp/app.log')); - expect(error).to.be.ok(); + assert.ok(error); }); it('can handle message with colons', async function () { diff --git a/src/test/system-test.js b/src/test/system-test.js index c2b3eb87d..4071eb52d 100644 --- a/src/test/system-test.js +++ b/src/test/system-test.js @@ -1,15 +1,12 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import child_process from 'node:child_process'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import system from '../system.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('System', function () { const { setup, cleanup } = common; @@ -25,8 +22,8 @@ describe('System', function () { if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return; const filesystems = await system.getFilesystems(); - expect(filesystems).to.be.ok(); - expect(filesystems.some(fs => fs.mountpoint === '/')).to.be(true); + assert.ok(filesystems); + assert.equal(filesystems.some(fs => fs.mountpoint === '/'), true); }); it('can get swaps', async function () { @@ -34,8 +31,8 @@ describe('System', function () { if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return; const swaps = await system.getSwaps(); - expect(swaps).to.be.ok(); - expect(Object.keys(swaps).some(n => swaps[n].type === 'partition' || swaps[n].type === 'file')).to.be.ok(); + assert.ok(swaps); + assert.ok(Object.keys(swaps).some(n => swaps[n].type === 'partition' || swaps[n].type === 'file')); }); it('can check for disk space', async function () { @@ -47,49 +44,49 @@ describe('System', function () { it('can get memory', async function () { const memory = await system.getMemory(); - expect(memory.memory).to.be.a('number'); - expect(memory.swap).to.be.a('number'); + assert.equal(typeof memory.memory, 'number'); + assert.equal(typeof memory.swap, 'number'); }); it('can get CPUs', async function () { const cpus = await system.getCpus(); - expect(cpus).to.be.an(Array); - expect(cpus[0].model).to.be.a('string'); + assert.ok(Array.isArray(cpus)); + assert.equal(typeof cpus[0].model, 'string'); }); it('can get ubuntu version', async function () { const v = await system.getUbuntuVersion(); - expect(v).to.be.ok(); + assert.ok(v); }); it('can get kernel version', async function () { const v = await system.getKernelVersion(); - expect(v).to.be.ok(); + assert.ok(v); }); it('can get info', async function () { const info = await system.getInfo(); - expect(info.sysVendor).to.be.a('string'); - expect(info.productName).to.be.a('string'); - expect(info.uptimeSecs).to.be.a('number'); - expect(info.rebootRequired).to.be.a('boolean'); + assert.equal(typeof info.sysVendor, 'string'); + assert.equal(typeof info.productName, 'string'); + assert.equal(typeof info.uptimeSecs, 'number'); + assert.equal(typeof info.rebootRequired, 'boolean'); }); it('can get block devices', async function () { const devices = await system.getBlockDevices(); - expect(devices).to.be.ok(); + assert.ok(devices); }); it('can get filesystems', async function () { const filesystems = await system.getFilesystems(); - expect(filesystems.find(v => v.mountpoint === '/')).to.be.ok(); + assert.ok(filesystems.find(v => v.mountpoint === '/')); }); it('can get filesystemUsage', async function () { const filesystems = await system.getFilesystems(); const rootFs = filesystems.find(v => v.mountpoint === '/'); - expect(rootFs.filesystem).to.be.ok(); + assert.ok(rootFs.filesystem); const usageTask = await system.getFilesystemUsage(rootFs.filesystem); diff --git a/src/test/tasks-test.js b/src/test/tasks-test.js index 52cf94b0a..1842c2f75 100644 --- a/src/test/tasks-test.js +++ b/src/test/tasks-test.js @@ -1,18 +1,15 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import fs from 'node:fs'; import paths from '../paths.js'; import safe from 'safetydance'; import tasks from '../tasks.js'; import _ from '../underscore.js'; -/* global it:false */ -/* global before:false */ -/* global after:false */ -/* global describe:false */ describe('task', function () { const { setup, cleanup } = common; @@ -31,18 +28,18 @@ describe('task', function () { it('add succeeds', async function () { const id = await tasks.add(TASK.type, TASK.args); - expect(id).to.be.ok(); + assert.ok(id); taskId = id; }); it('get succeeds', async function () { const task = await tasks.get(taskId); - expect(_.pick(task, Object.keys(TASK))).to.eql(TASK); + assert.deepEqual(_.pick(task, Object.keys(TASK)), TASK); }); it('get random task fails', async function () { const task = await tasks.get('random'); - expect(task).to.be(null); + assert.equal(task, null); }); it('update succeeds', async function () { @@ -50,35 +47,35 @@ describe('task', function () { TASK.message = 'almost ther'; await tasks.update(taskId, { percent: TASK.percent, message: TASK.message }); const task = await tasks.get(taskId); - expect(_.pick(task, Object.keys(TASK))).to.eql(TASK); + assert.deepEqual(_.pick(task, Object.keys(TASK)), TASK); }); it('list succeeds - does not exist', async function () { const result = await tasks.list(1, 1, { type: 'randomtask' }); - expect(result.length).to.be(0); + assert.equal(result.length, 0); }); it('list succeeds - by type', async function () { const result = await tasks.list(1, 1, { type: TASK.type }); - expect(result.length).to.be(1); - expect(_.pick(result[0], Object.keys(TASK))).to.eql(TASK); + assert.equal(result.length, 1); + assert.deepEqual(_.pick(result[0], Object.keys(TASK)), TASK); }); it('list succeeds - all', async function () { const result = await tasks.list(1, 1, { type: null }); - expect(result.length).to.be(1); - expect(_.pick(result[0], Object.keys(TASK))).to.eql(TASK); + assert.equal(result.length, 1); + assert.deepEqual(_.pick(result[0], Object.keys(TASK)), TASK); }); it('del succeeds', async function () { await tasks._del(taskId); const task = await tasks.get(taskId); - expect(task).to.be(null); + assert.equal(task, null); }); it('del missing task fails', async function () { const [error] = await safe(tasks._del('1235')); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can run valid task - success', async function () { @@ -86,7 +83,7 @@ describe('task', function () { const [error, result] = await safe(tasks.startTask(successTaskId, {})); if (error) throw error; - expect(result).to.equal('ping'); + assert.equal(result, 'ping'); }); it('can run valid task - error', async function () { @@ -94,8 +91,8 @@ describe('task', function () { const [error, result] = await safe(tasks.startTask(errorTaskId, {})); if (!error) throw new Error('expecting task to fail'); - expect(error.message).to.be('Task crashed. Failed for arg: ping'); - expect(result).to.not.be.ok(); + assert.equal(error.message, 'Task crashed. Failed for arg: ping'); + assert.ok(!(result)); }); it('can get logs of crash', async function () { @@ -103,11 +100,11 @@ describe('task', function () { const [error, result] = await safe(tasks.startTask(crashTaskId, {})); if (!error) throw new Error('expecting task to crash'); - expect(error.message).to.contain(`Task ${crashTaskId} crashed`); - expect(result).to.not.be.ok(); + assert.ok(error.message.includes(`Task ${crashTaskId} crashed`)); + assert.ok(!(result)); const logs = fs.readFileSync(`${paths.TASKS_LOG_DIR}/${crashTaskId}.log`, 'utf8'); - expect(logs).to.contain('Crashing for arg: ping'); + assert.ok(logs.includes('Crashing for arg: ping')); }); it('can stop task', async function () { @@ -119,9 +116,9 @@ describe('task', function () { const [error, result] = await safe(tasks.startTask(sleepTaskId, {})); if (!error) throw new Error('expecting task to stop'); - expect(error.message).to.contain('stopped'); - expect(error.code).to.be(tasks.ESTOPPED); - expect(result).to.not.be.ok(); + assert.ok(error.message.includes('stopped')); + assert.equal(error.code, tasks.ESTOPPED); + assert.ok(!(result)); }); it('task timesout', async function () { @@ -129,8 +126,8 @@ describe('task', function () { const [error, result] = await safe(tasks.startTask(timeoutTaskId, { timeout: 2000 })); if (!error) throw new Error('expecting task to timeout'); - expect(error.code).to.be(tasks.ETIMEOUT); - expect(error.message).to.contain('timed out'); - expect(result).to.not.be.ok(); + assert.equal(error.code, tasks.ETIMEOUT); + assert.ok(error.message.includes('timed out')); + assert.ok(!(result)); }); }); diff --git a/src/test/tokens-test.js b/src/test/tokens-test.js index 6ae303378..647b7be11 100644 --- a/src/test/tokens-test.js +++ b/src/test/tokens-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import oidcClients from '../oidcclients.js'; import safe from 'safetydance'; import tokens from '../tokens.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Tokens', function () { const { setup, cleanup } = common; @@ -34,35 +31,35 @@ describe('Tokens', function () { const badToken = Object.assign({}, TOKEN_0); badToken.name = new Array(100).fill('x').join(''); const [error] = await safe(tokens.add(badToken)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('add fails with unknown scope', async function () { const badToken = Object.assign({}, TOKEN_0); badToken.scope = { 'foobar': 'rw', '*': 'r' }; const [error] = await safe(tokens.add(badToken)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('add fails with invalid scope rule', async function () { const badToken = Object.assign({}, TOKEN_0); badToken.scope = { '*': 'rw ' }; const [error] = await safe(tokens.add(badToken)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('add fails with bad name', async function () { const badToken = Object.assign({}, TOKEN_0); badToken.name = new Array(100).fill('x').join(''); const [error] = await safe(tokens.add(badToken)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('add fails for bad allowed ips', async function () { const badToken = Object.assign({}, TOKEN_0); badToken.allowedIpRanges = '1.2.3./4'; const [error] = await safe(tokens.add(badToken)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('add succeeds', async function () { @@ -73,31 +70,31 @@ describe('Tokens', function () { it('get succeeds', async function () { const result = await tokens.get(TOKEN_0.id); - expect(result).to.be.eql(TOKEN_0); + assert.deepEqual(result, TOKEN_0); }); it('getByAccessToken succeeds', async function () { const result = await tokens.getByAccessToken(TOKEN_0.accessToken); - expect(result).to.be.eql(TOKEN_0); + assert.deepEqual(result, TOKEN_0); }); it('get of nonexisting token fails', async function () { const result = await tokens.getByAccessToken('somerandomaccesstoken'); - expect(result).to.be(null); + assert.equal(result, null); }); it('listByUserId succeeds', async function () { const result = await tokens.listByUserId(TOKEN_0.identifier); - expect(result).to.be.an(Array); - expect(result.length).to.equal(1); - expect(result[0]).to.be.an('object'); - expect(result[0]).to.be.eql(TOKEN_0); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(typeof result[0], 'object'); + assert.deepEqual(result[0], TOKEN_0); }); it('delete fails', async function () { const [error] = await safe(tokens.del(TOKEN_0.id + 'x')); - expect(error).to.be.a(BoxError); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.ok((error) instanceof (BoxError)); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('delete succeeds', async function () { @@ -106,13 +103,13 @@ describe('Tokens', function () { it('get returns null after token deletion', async function () { const result = await tokens.get(TOKEN_0.id); - expect(result).to.be(null); + assert.equal(result, null); }); it('cannot delete previously delete record', async function () { const [error] = await safe(tokens.del(TOKEN_0.id)); - expect(error).to.be.a(BoxError); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.ok((error) instanceof (BoxError)); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('delExpired succeeds', async function () { @@ -145,10 +142,10 @@ describe('Tokens', function () { await tokens.delExpired(); result = await tokens.getByAccessToken(token2.accessToken); - expect(result).to.be(null); + assert.equal(result, null); result = await tokens.getByAccessToken(token1.accessToken); - expect(result).to.eql(token1); + assert.deepEqual(result, token1); }); it('delByUserIdAndType succeeds', async function () { @@ -175,11 +172,11 @@ describe('Tokens', function () { await tokens.delByUserIdAndType('user2', oidcClients.ID_WEBADMIN); let result = await tokens.listByUserId('user1'); - expect(result.length).to.be(2); // should not have deleted user1 tokens + assert.equal(result.length, 2); // should not have deleted user1 tokens await tokens.delByUserIdAndType('user1', oidcClients.ID_WEBADMIN); result = await tokens.listByUserId('user1'); - expect(result.length).to.be(1); - expect(result[0].name).to.be(token2.name); + assert.equal(result.length, 1); + assert.equal(result[0].name, token2.name); }); }); diff --git a/src/test/translations-test.js b/src/test/translations-test.js index 28639066b..e7bb25a79 100644 --- a/src/test/translations-test.js +++ b/src/test/translations-test.js @@ -1,10 +1,9 @@ +import { describe, it } from 'node:test'; /* jslint node:true */ -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import translations from '../translations.js'; -/* global it:false */ -/* global describe:false */ describe('translation', function () { @@ -12,31 +11,31 @@ describe('translation', function () { it('nonexisting token', function () { const assets = { translations: {}, fallback: {} }; const out = translations.translate('Foo {{ bar }}', assets); - expect(out).to.contain('{{ bar }}'); + assert.ok(out.includes('{{ bar }}')); }); it('existing token', function () { const assets = { translations: { bar: 'here' }, fallback: {} }; const out = translations.translate('Foo {{ bar }}', assets); - expect(out).to.contain('here'); + assert.ok(out.includes('here')); }); it('existing token as fallback', function () { const assets = { translations: {}, fallback: { bar: 'here' } }; const out = translations.translate('Foo {{ bar }}', assets); - expect(out).to.contain('here'); + assert.ok(out.includes('here')); }); it('existing token deep', function () { const assets = { translations: { bar: { baz: { foo: 'here' }}}, fallback: {} }; const out = translations.translate('Foo {{ bar.baz.foo }}', assets); - expect(out).to.contain('here'); + assert.ok(out.includes('here')); }); it('existing token deep as fallback', function () { const assets = { translations: { bar: '' }, fallback: { bar: { baz: { foo: 'here' } } } }; const out = translations.translate('Foo {{ bar.baz.foo }}', assets); - expect(out).to.contain('here'); + assert.ok(out.includes('here')); }); it('with whitespace tokens', function () { @@ -57,11 +56,11 @@ describe('translation', function () { const input = 'Hello {{ something.missing.there}} and some more {{here}} and {{ there }} with odd spacing {{foo }} lots of{{ bar }}'; const out = translations.translate(input, assets); - expect(out).to.contain('1'); - expect(out).to.contain('2'); - expect(out).to.contain('3'); - expect(out).to.contain('4'); - expect(out).to.contain('5'); + assert.ok(out.includes('1')); + assert.ok(out.includes('2')); + assert.ok(out.includes('3')); + assert.ok(out.includes('4')); + assert.ok(out.includes('5')); }); }); }); diff --git a/src/test/underscore-test.js b/src/test/underscore-test.js index d3e25a652..d1a6e03b8 100644 --- a/src/test/underscore-test.js +++ b/src/test/underscore-test.js @@ -1,49 +1,49 @@ -/* global it, describe */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import _ from '../underscore.js'; describe('Underscore', function () { it('pick', function () { - expect(_.pick({ x: 1, y: 2 }, ['x'])).to.eql({x: 1}); - expect(_.pick({ x: 1, y: 2 }, ['x', 'y', 'z'])).to.eql({x: 1, y:2}); - expect(_.pick({ x: 1, y: 2 }, ['z'])).to.eql({}); - expect(_.pick({ x: 1, y: 2 }, [])).to.eql({}); + assert.deepEqual(_.pick({ x: 1, y: 2 }, ['x']), {x: 1}); + assert.deepEqual(_.pick({ x: 1, y: 2 }, ['x', 'y', 'z']), {x: 1, y:2}); + assert.deepEqual(_.pick({ x: 1, y: 2 }, ['z']), {}); + assert.deepEqual(_.pick({ x: 1, y: 2 }, []), {}); }); it('omit', function () { - expect(_.omit({ x: 1, y: 2 }, ['x'])).to.eql({ y: 2 }); - expect(_.omit({ x: 1, y: 2 }, ['x', 'y', 'z'])).to.eql({}); - expect(_.omit({ x: 1, y: 2 }, ['z'])).to.eql({ x: 1, y: 2 }); - expect(_.omit({ x: 1, y: 2 }, [])).to.eql({ x: 1, y: 2 }); + assert.deepEqual(_.omit({ x: 1, y: 2 }, ['x']), { y: 2 }); + assert.deepEqual(_.omit({ x: 1, y: 2 }, ['x', 'y', 'z']), {}); + assert.deepEqual(_.omit({ x: 1, y: 2 }, ['z']), { x: 1, y: 2 }); + assert.deepEqual(_.omit({ x: 1, y: 2 }, []), { x: 1, y: 2 }); }); it('intersection', function () { - expect(_.intersection([], [2,3])).to.eql([]); - expect(_.intersection([1,2], [2,3])).to.eql([2]); - expect(_.intersection([1,2], [3])).to.eql([]); - expect(_.intersection([1,2], [1,2])).to.eql([1,2]); + assert.deepEqual(_.intersection([], [2,3]), []); + assert.deepEqual(_.intersection([1,2], [2,3]), [2]); + assert.deepEqual(_.intersection([1,2], [3]), []); + assert.deepEqual(_.intersection([1,2], [1,2]), [1,2]); }); it('isEqual', function () { - expect(_.isEqual(null, null)).to.be(true); + assert.equal(_.isEqual(null, null), true); - expect(_.isEqual(1, 1)).to.be(true); - expect(_.isEqual(1, 2)).to.be(false); + assert.equal(_.isEqual(1, 1), true); + assert.equal(_.isEqual(1, 2), false); - expect(_.isEqual([], [])).to.be(true); - expect(_.isEqual([2,3,4], [3,4,2])).to.be(false); + assert.equal(_.isEqual([], []), true); + assert.equal(_.isEqual([2,3,4], [3,4,2]), false); - expect(_.isEqual({x:1}, {y:2})).to.be(false); - expect(_.isEqual({x:1}, {x:1})).to.be(true); - expect(_.isEqual({x:1,z:2}, {z:1,x:1})).to.be(false); - expect(_.isEqual({x:1,y:3,z:2}, {y:3,z:2,x:1})).to.be(true); + assert.equal(_.isEqual({x:1}, {y:2}), false); + assert.equal(_.isEqual({x:1}, {x:1}), true); + assert.equal(_.isEqual({x:1,z:2}, {z:1,x:1}), false); + assert.equal(_.isEqual({x:1,y:3,z:2}, {y:3,z:2,x:1}), true); }); it('difference', function () { - expect(_.difference([1,2], [2,3])).to.eql([1]); - expect(_.difference([1,2], [3])).to.eql([1,2]); - expect(_.difference([1,2], [1,2])).to.eql([]); - expect(_.difference([], [1,2])).to.eql([]); + assert.deepEqual(_.difference([1,2], [2,3]), [1]); + assert.deepEqual(_.difference([1,2], [3]), [1,2]); + assert.deepEqual(_.difference([1,2], [1,2]), []); + assert.deepEqual(_.difference([], [1,2]), []); }); }); diff --git a/src/test/updater-test.js b/src/test/updater-test.js index 9235f9afe..c5129ad3d 100644 --- a/src/test/updater-test.js +++ b/src/test/updater-test.js @@ -1,19 +1,16 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import apps from '../apps.js'; import BoxError from '../boxerror.js'; import common from './common.js'; import constants from '../constants.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import nock from 'nock'; import paths from '../paths.js'; import safe from 'safetydance'; import semver from 'semver'; import updater from '../updater.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ const UPDATE_VERSION = semver.inc(constants.VERSION, 'major'); @@ -26,12 +23,12 @@ describe('updater', function () { it('can get default autoupdate_pattern', async function () { const pattern = await updater.getAutoupdatePattern(); - expect(pattern).to.be('00 00 1,3,5,23 * * *'); + assert.equal(pattern, '00 00 1,3,5,23 * * *'); }); it('cannot set invalid autoupdate_pattern', async function () { const [error] = await safe(updater.setAutoupdatePattern('02 * 1 *')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set default autoupdate_pattern', async function () { @@ -61,8 +58,8 @@ describe('updater', function () { await updater.checkBoxUpdate({ stableOnly: false }); const boxUpdateInfo = await updater.getBoxUpdate(); - expect(boxUpdateInfo).to.be(null); - expect(scope.isDone()).to.be.ok(); + assert.equal(boxUpdateInfo, null); + assert.ok(scope.isDone()); }); it('new version', async function () { @@ -76,10 +73,10 @@ describe('updater', function () { await updater.checkBoxUpdate({ stableOnly: false }); const boxUpdateInfo = await updater.getBoxUpdate(); - expect(boxUpdateInfo).to.be.ok(); - expect(boxUpdateInfo.version).to.be(UPDATE_VERSION); - expect(boxUpdateInfo.sourceTarballUrl).to.be('box.tar.gz'); - expect(scope.isDone()).to.be.ok(); + assert.ok(boxUpdateInfo); + assert.equal(boxUpdateInfo.version, UPDATE_VERSION); + assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz'); + assert.ok(scope.isDone()); }); it('bad response offers whatever was last valid', async function () { @@ -93,9 +90,9 @@ describe('updater', function () { await safe(updater.checkBoxUpdate({ stableOnly: false })); // ignore error const boxUpdateInfo = await updater.getBoxUpdate(); - expect(boxUpdateInfo.version).to.be(UPDATE_VERSION); - expect(boxUpdateInfo.sourceTarballUrl).to.be('box.tar.gz'); - expect(scope.isDone()).to.be.ok(); + assert.equal(boxUpdateInfo.version, UPDATE_VERSION); + assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz'); + assert.ok(scope.isDone()); }); }); @@ -113,11 +110,11 @@ describe('updater', function () { .reply(204, { } ); const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false }); - expect(appUpdateInfo).to.eql(null); - expect(scope.isDone()).to.be.ok(); + assert.deepEqual(appUpdateInfo, null); + assert.ok(scope.isDone()); const tmp = await apps.get(app.id); - expect(tmp.updateInfo).to.be(null); + assert.equal(tmp.updateInfo, null); }); it('bad response', async function () { @@ -129,8 +126,8 @@ describe('updater', function () { .reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } ); const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false })); - expect(error).to.be.ok(); - expect(scope.isDone()).to.be.ok(); + assert.ok(error); + assert.ok(scope.isDone()); }); it('offers new version', async function () { @@ -149,11 +146,11 @@ describe('updater', function () { }; const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false }); - expect(appUpdateInfo.manifest).to.eql(expectedUpdateInfo.manifest); - expect(scope.isDone()).to.be.ok(); + assert.deepEqual(appUpdateInfo.manifest, expectedUpdateInfo.manifest); + assert.ok(scope.isDone()); const tmp = await apps.get(app.id); - expect(tmp.updateInfo).to.eql(expectedUpdateInfo); + assert.deepEqual(tmp.updateInfo, expectedUpdateInfo); }); it('does not offer old version', async function () { @@ -167,10 +164,10 @@ describe('updater', function () { }; const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false })); - expect(error).to.be.ok(); + assert.ok(error); const tmp = await apps.get(app.id); - expect(tmp.updateInfo).to.eql(expectedUpdateInfo); + assert.deepEqual(tmp.updateInfo, expectedUpdateInfo); }); }); }); diff --git a/src/test/user-directory-test.js b/src/test/user-directory-test.js index 794e7e5a8..96caeb84a 100644 --- a/src/test/user-directory-test.js +++ b/src/test/user-directory-test.js @@ -1,14 +1,11 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import oidcClients from '../oidcclients.js'; import tokens from '../tokens.js'; import userDirectory from '../user-directory.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('User Directory', function () { const { setup, cleanup, admin, auditSource } = common; @@ -19,18 +16,18 @@ describe('User Directory', function () { describe('profile config', function () { it('can get default profile config', async function () { const profileConfig = await userDirectory.getProfileConfig(); - expect(profileConfig.lockUserProfiles).to.be(false); - expect(profileConfig.mandatory2FA).to.be(false); + assert.equal(profileConfig.lockUserProfiles, false); + assert.equal(profileConfig.mandatory2FA, false); }); it('can set default profile config', async function () { await tokens.add({ name: 'token1', identifier: admin.id, clientId: oidcClients.ID_WEBADMIN, expires: Number.MAX_SAFE_INTEGER, lastUsedTime: null, allowedIpRanges: '' }); let result = await tokens.listByUserId(admin.id); - expect(result.length).to.be(1); // just confirm the token was really added! + assert.equal(result.length, 1); // just confirm the token was really added! await userDirectory.setProfileConfig({ mandatory2FA: true, lockUserProfiles: true }, { persistUserIdSessions: 'random' }, auditSource); result = await tokens.listByUserId(admin.id); - expect(result.length).to.be(0); // should have been removed by mandatory 2fa setting change + assert.equal(result.length, 0); // should have been removed by mandatory 2fa setting change }); }); }); diff --git a/src/test/users-test.js b/src/test/users-test.js index 4a62755ee..b7bd7ceb3 100644 --- a/src/test/users-test.js +++ b/src/test/users-test.js @@ -1,16 +1,13 @@ -/* global it:false */ +import { describe, it, before, after } from 'node:test'; import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import safe from 'safetydance'; import speakeasy from 'speakeasy'; import users from '../users.js'; import _ from '../underscore.js'; -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('User', function () { const { domainSetup, cleanup, admin, user, auditSource, checkMails, clearMailQueue } = common; @@ -32,61 +29,61 @@ describe('User', function () { after(cleanup); function checkUser(a, b) { - expect(a.creationTime).to.be.a(Date); - expect(a.resetTokenCreationTime).to.be.a(Date); + assert.ok((a.creationTime) instanceof (Date)); + assert.ok((a.resetTokenCreationTime) instanceof (Date)); const fields = [ 'id', 'username', 'email', 'fallbackEmail', 'role', 'displayName', 'source', 'permissions', 'active' ]; - expect(_.pick(a, fields)).to.be.eql(_.pick(b, fields)); + assert.deepEqual(_.pick(a, fields), _.pick(b, fields)); } describe('add', function () { it('fails due to short password', async function () { const testUser = Object.assign({}, admin, { password: 'Fo$%23' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to reserved username', async function () { const testUser = Object.assign({}, admin, { username: 'admin' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to invalid username', async function () { const testUser = Object.assign({}, admin, { username: 'moo+daemon' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to empty username', async function () { const testUser = Object.assign({}, admin, { username: '' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to long username', async function () { const testUser = Object.assign({}, admin, { username: new Array(257).fill('Z').join('') }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to reserved app pattern', async function () { const testUser = Object.assign({}, admin, { username: 'maybe.app' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails because password is empty', async function () { const testUser = Object.assign({}, admin, { password: '' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails because fallbackEmail is not an email', async function () { const testUser = Object.assign({}, admin, { fallbackEmail: 'notanemail' }); const [error] = await safe(users.add(testUser.email, testUser, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can add user', async function () { @@ -96,14 +93,14 @@ describe('User', function () { it('cannot add user with same email again', async function () { const [error] = await safe(users.add(admin.email, admin, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); - expect(error.message).to.equal('email already exists'); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); + assert.equal(error.message, 'email already exists'); }); it('cannot add user with same username again', async function () { const [error] = await safe(users.add('somethingelse@not.taken', admin, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); - expect(error.message).to.equal('username already exists'); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); + assert.equal(error.message, 'username already exists'); }); }); @@ -112,12 +109,12 @@ describe('User', function () { it('cannot get by bad user id', async function () { const result = await users.get('random'); - expect(result).to.be(null); + assert.equal(result, null); }); it('fails because there is no owner', async function () { const owner = await users.getOwner(); - expect(owner).to.be(null); + assert.equal(owner, null); }); it('getOwner succeeds', async function () { @@ -151,25 +148,25 @@ describe('User', function () { it('getSuperadmins succeeds', async function () { const results = await users.getSuperadmins(); - expect(results.length).to.be(1); + assert.equal(results.length, 1); checkUser(results[0], admin); }); it('getAdmins succeeds', async function () { const results = await users.getAdmins(); - expect(results.length).to.be(2); + assert.equal(results.length, 2); checkUser(results[0], admin); // owner is always the first checkUser(results[1], user); }); it('getByResetToken fails for empty resetToken', async function () { const [error] = await safe(users.getByResetToken('')); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('getByResetToken fails for bad resetToken', async function () { const result = await users.getByResetToken(new Array(64).fill('Z').join('')); - expect(result).to.be(null); + assert.equal(result, null); }); it('can get by resetToken', async function () { @@ -181,24 +178,24 @@ describe('User', function () { it('can list', async function () { const results = await users.list(); - expect(results.length).to.be(2); + assert.equal(results.length, 2); checkUser(results[0], admin); checkUser(results[1], user); }); it('can listPaged', async function () { let results = await users.listPaged(null, null, 1, 1); - expect(results.length).to.be(1); + assert.equal(results.length, 1); checkUser(results[0], admin); results = await users.listPaged(null, null, 2, 1); - expect(results.length).to.be(1); + assert.equal(results.length, 1); checkUser(results[0], user); }); it('can listPaged (search)', async function () { const results = await users.listPaged(admin.email.slice(0, 8), null, 1, 1); - expect(results.length).to.be(1); + assert.equal(results.length, 1); checkUser(results[0], admin); }); }); @@ -209,12 +206,12 @@ describe('User', function () { it('fails due to unknown userid', async function () { const unknownUser = Object.assign({}, admin, { id: 'random' }); const [error] = await safe(users.update(unknownUser, { displayName: 'full name' }, auditSource)); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails due to invalid email', async function () { const [error] = await safe(users.update(admin, { email: 'brokenemailaddress' }, auditSource)); - expect(error.reason).to.equal(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot update the user with already existing email', async function () { @@ -222,21 +219,21 @@ describe('User', function () { user.id = result; const [error] = await safe(users.update(admin, { email: user.email }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); - expect(error.message).to.equal('email already exists'); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); + assert.equal(error.message, 'email already exists'); }); it('cannot update username', async function () { const [error] = await safe(users.update(admin, { username: user.username }, auditSource)); - expect(error.reason).to.be(BoxError.CONFLICT); - expect(error.message).to.equal('Username cannot be changed'); + assert.equal(error.reason, BoxError.CONFLICT); + assert.equal(error.message, 'Username cannot be changed'); }); it('can update the user', async function () { await users.update(admin, { email: 'some@thing.com', displayName: 'Heiter' }, auditSource); const updatedUser = await users.get(admin.id); - expect(updatedUser.email).to.equal('some@thing.com'); - expect(updatedUser.displayName).to.equal('Heiter'); + assert.equal(updatedUser.email, 'some@thing.com'); + assert.equal(updatedUser.displayName, 'Heiter'); }); }); @@ -245,52 +242,52 @@ describe('User', function () { it('fails due to non existing user', async function () { const [error] = await safe(users.verifyWithId('somerandomid', 'somepassword', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails due to empty password', async function () { const [error] = await safe(users.verifyWithId(admin.id, '', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('fails due to wrong password', async function () { const [error] = await safe(users.verifyWithId(admin.id, admin.password+'x', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds', async function () { const result = await users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {}); - expect(result).to.be.ok(); - expect(result.appPassword).to.not.be.ok(); - expect(result.ghost).to.not.be.ok(); + assert.ok(result); + assert.ok(!(result.appPassword)); + assert.ok(!(result.ghost)); }); it('fails for ghost if not enabled', async function () { const [error] = await safe(users.verifyWithId(admin.id, 'foobar', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('fails for ghost with wrong password', async function () { await users.setGhost(admin, 'testpassword', 0); const [error] = await safe(users.verifyWithId(admin.id, 'foobar', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds for ghost', async function () { await users.setGhost(admin, 'testpassword', 0); const result = await users.verifyWithId(admin.id, 'testpassword', users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); - expect(result.ghost).to.be(true); + assert.equal(result.id, admin.id); + assert.equal(result.ghost, true); }); it('succeeds for normal user password when ghost file exists', async function () { await users.setGhost(admin, 'testpassword', 0); const result = await users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); - expect(result.ghost).to.not.be.ok(); + assert.equal(result.id, admin.id); + assert.ok(!(result.ghost)); }); }); @@ -299,42 +296,42 @@ describe('User', function () { it('fails due to non existing username', async function () { const [error] = await safe(users.verifyWithUsername('someusername', 'somepass', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails due to empty password', async function () { const [error] = await safe(users.verifyWithUsername(admin.username, '', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('fails due to wrong password', async function () { const [error] = await safe(users.verifyWithUsername(admin.username, 'somepass', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds', async function () { const result = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); + assert.equal(result.id, admin.id); }); it('succeeds for different username case', async function () { const result = await users.verifyWithUsername(admin.username.toUpperCase(), admin.password, users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); + assert.equal(result.id, admin.id); }); it('fails for ghost with wrong password', async function () { await users.setGhost(admin, 'testpassword', 0); const [error] = await safe(users.verifyWithUsername(admin.username, 'foobar', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds for ghost', async function () { await users.setGhost(admin, 'testpassword', 0); const result = await users.verifyWithUsername(admin.username, 'testpassword', users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); - expect(result.ghost).to.be(true); + assert.equal(result.id, admin.id); + assert.equal(result.ghost, true); }); }); @@ -343,42 +340,42 @@ describe('User', function () { it('fails due to non existing user', async function () { const [error] = await safe(users.verifyWithEmail('bad@email.com', admin.password, users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails due to empty password', async function () { const [error] = await safe(users.verifyWithEmail(admin.email, '', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('fails due to wrong password', async function () { const [error] = await safe(users.verifyWithEmail(admin.email, 'badpassword', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds', async function () { const result = await users.verifyWithEmail(admin.email, admin.password, users.AP_WEBADMIN, {}); - expect(result.id).to.be(admin.id); + assert.equal(result.id, admin.id); }); it('succeeds for different email case', async function () { const result = await users.verifyWithEmail(admin.email.toUpperCase(), admin.password, users.AP_WEBADMIN, {}); - expect(result.id).to.be(admin.id); + assert.equal(result.id, admin.id); }); it('fails for ghost with wrong password', async function () { await users.setGhost(admin, 'testpassword', 0); const [error] = await safe(users.verifyWithEmail(admin.email, 'foobar', users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('succeeds for ghost', async function () { await users.setGhost(admin, 'testpassword', 0); const result = await users.verifyWithEmail(admin.email, 'testpassword', users.AP_WEBADMIN, {}); - expect(result.id).to.equal(admin.id); - expect(result.ghost).to.equal(true); + assert.equal(result.id, admin.id); + assert.equal(result.ghost, true); }); }); @@ -389,14 +386,14 @@ describe('User', function () { it('create secret', async function () { twofa = await users.setTwoFactorAuthenticationSecret(admin, auditSource); - expect(twofa.secret).to.be.a('string'); - expect(twofa.qrcode).to.be.a('string'); + assert.equal(typeof twofa.secret, 'string'); + assert.equal(typeof twofa.qrcode, 'string'); }); it('can create secret again', async function () { twofa = await users.setTwoFactorAuthenticationSecret(admin, auditSource); - expect(twofa.secret).to.be.a('string'); - expect(twofa.qrcode).to.be.a('string'); + assert.equal(typeof twofa.secret, 'string'); + assert.equal(typeof twofa.qrcode, 'string'); admin.twoFactorAuthenticationSecret = twofa.secret; // update user object }); @@ -405,41 +402,41 @@ describe('User', function () { await users.enableTwoFactorAuthentication(admin, totpToken, auditSource); const u = await users.get(admin.id); - expect(u.twoFactorAuthenticationEnabled).to.be(true); + assert.equal(u.twoFactorAuthenticationEnabled, true); admin.twoFactorAuthenticationEnabled = true; // update user object }); it('cannot re-create secret', async function () { const [error] = await safe(users.setTwoFactorAuthenticationSecret(admin, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cannot re-enable 2fa', async function () { const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' }); const [error] = await safe(users.enableTwoFactorAuthentication(admin, totpToken, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('verify fails without 2fa', async function () { const [error] = await safe(users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); - expect(error.message).to.be('A totpToken must be provided'); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); + assert.equal(error.message, 'A totpToken must be provided'); }); it('verify succeeds with relaxed 2fa', async function () { const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { skipTotpCheck: true }); - expect(verifiedUser.id).to.be(admin.id); + assert.equal(verifiedUser.id, admin.id); }); it('verify succeeds with relaxed 2fa but incorrect totp (totp is ignored)', async function () { const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { totpToken: 'schlecht', skipTotpCheck: true }); - expect(verifiedUser.id).to.be(admin.id); + assert.equal(verifiedUser.id, admin.id); }); it('verify succeeds with valid 2fa', async function () { const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' }); const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { totpToken }); - expect(verifiedUser.id).to.be(admin.id); + assert.equal(verifiedUser.id, admin.id); }); }); @@ -449,7 +446,7 @@ describe('User', function () { it('verify fails for inactive user', async function () { await users.update(admin, { active: false }, auditSource); const [error] = await safe(users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('verify succeeds for inactive user', async function () { @@ -463,16 +460,16 @@ describe('User', function () { it('fails due to non existing user', async function () { const result = await users.get('randomid'); - expect(result).to.be(null); + assert.equal(result, null); }); it('succeeds', async function () { const result = await users.get(admin.id); - expect(result.id).to.equal(admin.id); - expect(result.email).to.equal(admin.email.toLowerCase()); - expect(result.fallbackEmail).to.equal(admin.fallbackEmail.toLowerCase()); - expect(result.username).to.equal(admin.username.toLowerCase()); - expect(result.displayName).to.equal(admin.displayName); + assert.equal(result.id, admin.id); + assert.equal(result.email, admin.email.toLowerCase()); + assert.equal(result.fallbackEmail, admin.fallbackEmail.toLowerCase()); + assert.equal(result.username, admin.username.toLowerCase()); + assert.equal(result.displayName, admin.displayName); }); }); @@ -481,14 +478,14 @@ describe('User', function () { it('succeeds with no users', async function () { const activated = await users.isActivated(); - expect(activated).to.be(false); + assert.equal(activated, false); }); it('create admin', createOwner); it('succeeds with users', async function () { const activated = await users.isActivated(); - expect(activated).to.be(true); + assert.equal(activated, true); }); }); @@ -498,17 +495,17 @@ describe('User', function () { it('fails due to unknown user', async function () { const unknownUser = Object.assign({}, admin, { id: 'doesnotexist' }); const [error] = await safe(users.setPassword(unknownUser, 'newpassword', auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('fails due to empty password', async function () { const [error] = await safe(users.setPassword(admin, '', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('fails due to invalid password', async function () { const [error] = await safe(users.setPassword(admin, 'foobar', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('succeeds', async function () { @@ -517,7 +514,7 @@ describe('User', function () { it('actually changed the password (unable to login with old pasword)', async function () { const [error] = await safe(users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {})); - expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS); + assert.equal(error.reason, BoxError.INVALID_CREDENTIALS); }); it('actually changed the password (login with new password)', async function () { @@ -530,12 +527,12 @@ describe('User', function () { it('fails due to unknown email', async function () { const [error] = await safe(users.sendPasswordResetByIdentifier('unknown@mail.com', auditSource)); - expect(error.reason).to.eql(BoxError.NOT_FOUND); + assert.deepEqual(error.reason, BoxError.NOT_FOUND); }); it('fails due to unknown username', async function () { const [error] = await safe(users.sendPasswordResetByIdentifier('unknown', auditSource)); - expect(error.reason).to.eql(BoxError.NOT_FOUND); + assert.deepEqual(error.reason, BoxError.NOT_FOUND); }); it('succeeds with email', async function () { @@ -556,24 +553,24 @@ describe('User', function () { it('default language is empty', async function () { const result = await users.get(admin.id); - expect(result.language).to.be(''); + assert.equal(result.language, ''); }); it('cannot set bad language', async function () { const [error] = await safe(users.update(admin, { language: 'ta '}, auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can set language', async function () { await users.update(admin, { language: 'en' }, auditSource); const result = await users.get(admin.id); - expect(result.language).to.be('en'); + assert.equal(result.language, 'en'); }); it('can reset language', async function () { await users.update(admin, { language: '' }, auditSource); const result = await users.get(admin.id); - expect(result.language).to.be(''); + assert.equal(result.language, ''); }); }); @@ -582,24 +579,24 @@ describe('User', function () { it('default avatar is empty', async function () { const result = await users.get(admin.id); - expect(result.avatar).to.be(undefined); // should not be in 'get' + assert.equal(result.avatar, undefined); // should not be in 'get' const result2 = await users.getAvatar(result); - expect(result2).to.be(null); + assert.equal(result2, null); }); it('set avatar', async function () { await users.setAvatar(admin, Buffer.from('ABC')); const avatar = await users.getAvatar(admin); - expect(avatar).to.be.eql(Buffer.from('ABC')); + assert.deepEqual(avatar, Buffer.from('ABC')); }); it('reset avatar', async function () { await users.setAvatar(admin, null); const avatar = await users.getAvatar(admin); - expect(avatar).to.be(null); + assert.equal(avatar, null); }); }); @@ -610,7 +607,7 @@ describe('User', function () { it('get link fails as alreayd been used', async function () { const [error] = await safe(users.getInviteLink(admin, auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('can get link', async function () { @@ -618,25 +615,25 @@ describe('User', function () { invitedUser = await users.get(userId); const inviteLink = await users.getInviteLink(invitedUser, auditSource); - expect(inviteLink).to.be.a('string'); - expect(inviteLink).to.contain(invitedUser.inviteToken); + assert.equal(typeof inviteLink, 'string'); + assert.ok(inviteLink.includes(invitedUser.inviteToken)); }); it('cannot send mail for already active user', async function () { const [error] = await safe(users.sendInviteEmail(admin, 'admin@mail.com', auditSource)); - expect(error.reason).to.be(BoxError.BAD_STATE); + assert.equal(error.reason, BoxError.BAD_STATE); }); it('cannot send mail with empty receipient', async function () { const [error] = await safe(users.sendInviteEmail(invitedUser, '', auditSource)); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('can send mail', async function () { await clearMailQueue(); await users.sendInviteEmail(invitedUser, 'custom@mail.com', auditSource); const emails = await checkMails(1); - expect(emails[0].to).to.equal('custom@mail.com'); + assert.equal(emails[0].to, 'custom@mail.com'); }); }); @@ -646,7 +643,7 @@ describe('User', function () { it('fails for unknown user', async function () { const unknownUser = Object.assign({}, admin, { id: 'doesnotexist' }); const [error] = await safe(users.del(unknownUser, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can remove valid user', async function () { @@ -665,7 +662,7 @@ describe('User', function () { ]; for (const name of names) { - expect(users.parseDisplayName(name.in)).to.eql(name.out); + assert.deepEqual(users.parseDisplayName(name.in), name.out); } }); }); diff --git a/src/test/validator-test.js b/src/test/validator-test.js index c798ab4b2..ef6927e10 100644 --- a/src/test/validator-test.js +++ b/src/test/validator-test.js @@ -1,6 +1,6 @@ -/* global it, describe */ +import { describe, it } from 'node:test'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import validator from '../validator.js'; describe('Validator', function () { @@ -14,7 +14,7 @@ describe('Validator', function () { ]; for (const goodEmail of goodEmails) { - it(`isEmail returns false ${goodEmail}`, () => expect(validator.isEmail(goodEmail)).to.be(true)); + it(`isEmail returns false ${goodEmail}`, () => assert.equal(validator.isEmail(goodEmail), true)); } const badEmails = [ @@ -26,20 +26,20 @@ describe('Validator', function () { ]; for (const badEmail of badEmails) { - it(`isEmail returns false ${badEmail}`, () => expect(validator.isEmail(badEmail)).to.be(false)); + it(`isEmail returns false ${badEmail}`, () => assert.equal(validator.isEmail(badEmail), false)); } describe('isIsoDate', function () { it('returns true for valid ISO string', function () { - expect(validator.isIsoDate('2024-01-15T10:30:00.000Z')).to.be(true); + assert.equal(validator.isIsoDate('2024-01-15T10:30:00.000Z'), true); }); it('returns false for invalid string', function () { - expect(validator.isIsoDate('not-a-date')).to.be(false); + assert.equal(validator.isIsoDate('not-a-date'), false); }); it('returns false for empty string', function () { - expect(validator.isIsoDate('')).to.be(false); + assert.equal(validator.isIsoDate(''), false); }); }); }); diff --git a/src/test/volumes-test.js b/src/test/volumes-test.js index db315e027..c1b528471 100644 --- a/src/test/volumes-test.js +++ b/src/test/volumes-test.js @@ -1,16 +1,13 @@ +import { describe, it, before, after } from 'node:test'; /* jslint node:true */ import BoxError from '../boxerror.js'; import common from './common.js'; -import expect from 'expect.js'; +import assert from 'node:assert/strict'; import paths from '../paths.js'; import safe from 'safetydance'; import volumes from '../volumes.js'; -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ describe('Volumes', function () { const { setup, cleanup, auditSource } = common; @@ -21,53 +18,53 @@ describe('Volumes', function () { it('cannot add bad name', async function () { const [error] = await safe(volumes.add({ name: 'music/is', hostPath: '/tmp/music', mountType: 'filesystem', mountOptions: {} }, auditSource)); if (!error) throw new Error('Expecting bad field error'); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); it('cannot add bad path', async function () { const [error] = await safe(volumes.add({ name: 'music', hostPath: '/tmp/music', mountType: 'filesystem', mountOptions: {} }, auditSource)); if (!error) throw new Error('Expecting bad field error'); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); let volume; it('can add volume', async function () { const id = await volumes.add({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music' } }, auditSource); - expect(id).to.be.a('string'); + assert.equal(typeof id, 'string'); volume = { id, name: 'music', hostPath: '/mnt/cloudron-test-music' }; }); it('cannot add duplicate path', async function () { const [error] = await safe(volumes.add({ name: 'music-dup', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music' } }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('cannot add duplicate name', async function () { const [error] = await safe(volumes.add({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music2' } }, auditSource)); - expect(error.reason).to.be(BoxError.ALREADY_EXISTS); + assert.equal(error.reason, BoxError.ALREADY_EXISTS); }); it('can get volume', async function () { const result = await volumes.get(volume.id); - expect(result.hostPath).to.be('/mnt/cloudron-test-music'); + assert.equal(result.hostPath, '/mnt/cloudron-test-music'); }); it('cannot get random volume', async function () { const result = await volumes.get('randomvolume'); - expect(result).to.be(null); + assert.equal(result, null); }); it('can list volumes', async function () { const result = await volumes.list(); - expect(result).to.be.an(Array); - expect(result.length).to.be(1); - expect(result[0].id).to.be(volume.id); - expect(result[0].hostPath).to.be('/mnt/cloudron-test-music'); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].id, volume.id); + assert.equal(result[0].hostPath, '/mnt/cloudron-test-music'); }); it('cannot del random volume', async function () { const [error] = await safe(volumes.del({ id: 'randomvolume' }, auditSource)); - expect(error.reason).to.be(BoxError.NOT_FOUND); + assert.equal(error.reason, BoxError.NOT_FOUND); }); it('can del volume', async function () { @@ -92,7 +89,7 @@ describe('Volumes', function () { for (const p of badPaths) { it(`validateHostPath - ${p}`, function () { const error = volumes._validateHostPath(p); - expect(error.reason).to.be(BoxError.BAD_FIELD); + assert.equal(error.reason, BoxError.BAD_FIELD); }); } });