additional integration tests
This commit is contained in:
parent
83a0aa1109
commit
6ff07c9d74
204
Development/server/package-lock.json
generated
204
Development/server/package-lock.json
generated
@ -106,6 +106,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../../@agn/error-handler": {
|
"../../../@agn/error-handler": {
|
||||||
|
"name": "error-handler",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"license": "Proprietary",
|
"license": "Proprietary",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -12817,13 +12818,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/abbrev": {
|
"node_modules/node-libxml/node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/ansi-regex": {
|
"node_modules/node-libxml/node_modules/ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -12832,13 +12831,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/aproba": {
|
"node_modules/node-libxml/node_modules/aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/are-we-there-yet": {
|
"node_modules/node-libxml/node_modules/are-we-there-yet": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -12867,7 +12864,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/code-point-at": {
|
"node_modules/node-libxml/node_modules/code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -12886,13 +12882,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/console-control-strings": {
|
"node_modules/node-libxml/node_modules/console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/core-util-is": {
|
"node_modules/node-libxml/node_modules/core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@ -12906,7 +12900,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/deep-extend": {
|
"node_modules/node-libxml/node_modules/deep-extend": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -12915,13 +12908,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/delegates": {
|
"node_modules/node-libxml/node_modules/delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/detect-libc": {
|
"node_modules/node-libxml/node_modules/detect-libc": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -12954,7 +12945,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/gauge": {
|
"node_modules/node-libxml/node_modules/gauge": {
|
||||||
"version": "2.7.4",
|
"version": "2.7.4",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -12995,7 +12985,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/has-unicode": {
|
"node_modules/node-libxml/node_modules/has-unicode": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@ -13009,7 +12998,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/iconv-lite": {
|
"node_modules/node-libxml/node_modules/iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13021,7 +13009,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/ignore-walk": {
|
"node_modules/node-libxml/node_modules/ignore-walk": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13044,13 +13031,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/ini": {
|
"node_modules/node-libxml/node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/is-fullwidth-code-point": {
|
"node_modules/node-libxml/node_modules/is-fullwidth-code-point": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13062,7 +13047,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/isarray": {
|
"node_modules/node-libxml/node_modules/isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@ -13081,6 +13065,17 @@
|
|||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/node-libxml/node_modules/minipass": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"extraneous": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-libxml/node_modules/mkdirp": {
|
"node_modules/node-libxml/node_modules/mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -13122,7 +13117,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/needle": {
|
"node_modules/node-libxml/node_modules/needle": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13139,7 +13133,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/needle/node_modules/debug": {
|
"node_modules/node-libxml/node_modules/needle/node_modules/debug": {
|
||||||
"version": "3.2.7",
|
"version": "3.2.7",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13148,13 +13141,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/needle/node_modules/ms": {
|
"node_modules/node-libxml/node_modules/needle/node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp": {
|
||||||
"version": "0.17.0",
|
"version": "0.17.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13175,13 +13166,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/chownr": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/chownr": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/fs-minipass": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/fs-minipass": {
|
||||||
"version": "1.2.7",
|
"version": "1.2.7",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13190,7 +13179,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/glob": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/glob": {
|
||||||
"version": "7.1.6",
|
"version": "7.1.6",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13210,13 +13198,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minimist": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minipass": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minipass": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13226,7 +13212,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minizlib": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/minizlib": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13235,7 +13220,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/mkdirp": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/mkdirp": {
|
||||||
"version": "0.5.5",
|
"version": "0.5.5",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13247,7 +13231,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/nopt": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/nopt": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13260,7 +13243,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/rimraf": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/rimraf": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13272,7 +13254,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/semver": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -13281,7 +13262,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/tar": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/tar": {
|
||||||
"version": "4.4.13",
|
"version": "4.4.13",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13299,13 +13279,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/yallist": {
|
"node_modules/node-libxml/node_modules/node-pre-gyp/node_modules/yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/npm-bundled": {
|
"node_modules/node-libxml/node_modules/npm-bundled": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13314,13 +13292,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/npm-normalize-package-bin": {
|
"node_modules/node-libxml/node_modules/npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/npm-packlist": {
|
"node_modules/node-libxml/node_modules/npm-packlist": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13331,7 +13307,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/npmlog": {
|
"node_modules/node-libxml/node_modules/npmlog": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13343,7 +13318,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/number-is-nan": {
|
"node_modules/node-libxml/node_modules/number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -13352,7 +13326,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/object-assign": {
|
"node_modules/node-libxml/node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -13369,7 +13342,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/os-homedir": {
|
"node_modules/node-libxml/node_modules/os-homedir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -13378,7 +13350,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/os-tmpdir": {
|
"node_modules/node-libxml/node_modules/os-tmpdir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -13387,7 +13358,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/osenv": {
|
"node_modules/node-libxml/node_modules/osenv": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13405,13 +13375,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/process-nextick-args": {
|
"node_modules/node-libxml/node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/rc": {
|
"node_modules/node-libxml/node_modules/rc": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13426,13 +13394,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/rc/node_modules/minimist": {
|
"node_modules/node-libxml/node_modules/rc/node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/readable-stream": {
|
"node_modules/node-libxml/node_modules/readable-stream": {
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13447,37 +13413,31 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/safe-buffer": {
|
"node_modules/node-libxml/node_modules/safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/safer-buffer": {
|
"node_modules/node-libxml/node_modules/safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/sax": {
|
"node_modules/node-libxml/node_modules/sax": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/set-blocking": {
|
"node_modules/node-libxml/node_modules/set-blocking": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/signal-exit": {
|
"node_modules/node-libxml/node_modules/signal-exit": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/string_decoder": {
|
"node_modules/node-libxml/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13486,7 +13446,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/string-width": {
|
"node_modules/node-libxml/node_modules/string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13500,7 +13459,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/strip-ansi": {
|
"node_modules/node-libxml/node_modules/strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13512,7 +13470,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/strip-json-comments": {
|
"node_modules/node-libxml/node_modules/strip-json-comments": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -13532,13 +13489,11 @@
|
|||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/util-deprecate": {
|
"node_modules/node-libxml/node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-libxml/node_modules/wide-align": {
|
"node_modules/node-libxml/node_modules/wide-align": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"extraneous": true,
|
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -13550,6 +13505,11 @@
|
|||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/node-libxml/node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"extraneous": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/node-preload": {
|
"node_modules/node-preload": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
|
||||||
@ -27689,23 +27649,19 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"are-we-there-yet": {
|
"are-we-there-yet": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"delegates": "^1.0.0",
|
"delegates": "^1.0.0",
|
||||||
"readable-stream": "^2.0.6"
|
"readable-stream": "^2.0.6"
|
||||||
@ -27730,8 +27686,7 @@
|
|||||||
},
|
},
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"commander": {
|
"commander": {
|
||||||
"version": "2.11.0",
|
"version": "2.11.0",
|
||||||
@ -27744,13 +27699,11 @@
|
|||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
@ -27762,18 +27715,15 @@
|
|||||||
},
|
},
|
||||||
"deep-extend": {
|
"deep-extend": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"delegates": {
|
"delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"detect-libc": {
|
"detect-libc": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"diff": {
|
"diff": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
@ -27792,7 +27742,6 @@
|
|||||||
"gauge": {
|
"gauge": {
|
||||||
"version": "2.7.4",
|
"version": "2.7.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"aproba": "^1.0.3",
|
"aproba": "^1.0.3",
|
||||||
"console-control-strings": "^1.0.0",
|
"console-control-strings": "^1.0.0",
|
||||||
@ -27824,8 +27773,7 @@
|
|||||||
},
|
},
|
||||||
"has-unicode": {
|
"has-unicode": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"he": {
|
"he": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@ -27835,7 +27783,6 @@
|
|||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
}
|
}
|
||||||
@ -27843,7 +27790,6 @@
|
|||||||
"ignore-walk": {
|
"ignore-walk": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
@ -27862,21 +27808,18 @@
|
|||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
@ -27888,6 +27831,13 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8"
|
"version": "0.0.8"
|
||||||
},
|
},
|
||||||
|
"minipass": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"extraneous": true,
|
||||||
|
"requires": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -27919,7 +27869,6 @@
|
|||||||
"needle": {
|
"needle": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^3.2.6",
|
"debug": "^3.2.6",
|
||||||
"iconv-lite": "^0.4.4",
|
"iconv-lite": "^0.4.4",
|
||||||
@ -27929,22 +27878,19 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"version": "3.2.7",
|
"version": "3.2.7",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "^2.1.1"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-pre-gyp": {
|
"node-pre-gyp": {
|
||||||
"version": "0.17.0",
|
"version": "0.17.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^1.0.3",
|
||||||
"mkdirp": "^0.5.5",
|
"mkdirp": "^0.5.5",
|
||||||
@ -27960,13 +27906,11 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chownr": {
|
"chownr": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"fs-minipass": {
|
"fs-minipass": {
|
||||||
"version": "1.2.7",
|
"version": "1.2.7",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minipass": "^2.6.0"
|
"minipass": "^2.6.0"
|
||||||
}
|
}
|
||||||
@ -27974,7 +27918,6 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.6",
|
"version": "7.1.6",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@ -27986,13 +27929,11 @@
|
|||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -28001,7 +27942,6 @@
|
|||||||
"minizlib": {
|
"minizlib": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minipass": "^2.9.0"
|
"minipass": "^2.9.0"
|
||||||
}
|
}
|
||||||
@ -28009,7 +27949,6 @@
|
|||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.5",
|
"version": "0.5.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
}
|
}
|
||||||
@ -28017,7 +27956,6 @@
|
|||||||
"nopt": {
|
"nopt": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"abbrev": "1",
|
"abbrev": "1",
|
||||||
"osenv": "^0.1.4"
|
"osenv": "^0.1.4"
|
||||||
@ -28026,20 +27964,17 @@
|
|||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "4.4.13",
|
"version": "4.4.13",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"chownr": "^1.1.1",
|
"chownr": "^1.1.1",
|
||||||
"fs-minipass": "^1.2.5",
|
"fs-minipass": "^1.2.5",
|
||||||
@ -28052,28 +27987,24 @@
|
|||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm-bundled": {
|
"npm-bundled": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"npm-normalize-package-bin": "^1.0.1"
|
"npm-normalize-package-bin": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm-normalize-package-bin": {
|
"npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"npm-packlist": {
|
"npm-packlist": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ignore-walk": "^3.0.1",
|
"ignore-walk": "^3.0.1",
|
||||||
"npm-bundled": "^1.0.1",
|
"npm-bundled": "^1.0.1",
|
||||||
@ -28083,7 +28014,6 @@
|
|||||||
"npmlog": {
|
"npmlog": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"are-we-there-yet": "~1.1.2",
|
"are-we-there-yet": "~1.1.2",
|
||||||
"console-control-strings": "~1.1.0",
|
"console-control-strings": "~1.1.0",
|
||||||
@ -28093,13 +28023,11 @@
|
|||||||
},
|
},
|
||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
@ -28110,18 +28038,15 @@
|
|||||||
},
|
},
|
||||||
"os-homedir": {
|
"os-homedir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"os-tmpdir": {
|
"os-tmpdir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"osenv": {
|
"osenv": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"os-homedir": "^1.0.0",
|
"os-homedir": "^1.0.0",
|
||||||
"os-tmpdir": "^1.0.0"
|
"os-tmpdir": "^1.0.0"
|
||||||
@ -28133,13 +28058,11 @@
|
|||||||
},
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"rc": {
|
"rc": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"deep-extend": "^0.6.0",
|
"deep-extend": "^0.6.0",
|
||||||
"ini": "~1.3.0",
|
"ini": "~1.3.0",
|
||||||
@ -28149,15 +28072,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
@ -28170,33 +28091,27 @@
|
|||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"sax": {
|
"sax": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"set-blocking": {
|
"set-blocking": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
@ -28204,7 +28119,6 @@
|
|||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -28214,15 +28128,13 @@
|
|||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip-json-comments": {
|
"strip-json-comments": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
@ -28234,13 +28146,11 @@
|
|||||||
},
|
},
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true
|
||||||
"extraneous": true
|
|
||||||
},
|
},
|
||||||
"wide-align": {
|
"wide-align": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"extraneous": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"string-width": "^1.0.2 || 2"
|
"string-width": "^1.0.2 || 2"
|
||||||
}
|
}
|
||||||
@ -28248,6 +28158,10 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"extraneous": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -102,3 +102,47 @@ describe('billing controller – getCustUsage_post', () => {
|
|||||||
expect(Array.isArray(res._data)).toBe(true);
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('billing controller – exportUsageDetail_post', () => {
|
||||||
|
let applicator;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
applicator = await Customer.create(mockApplicator());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await Customer.deleteMany({ _id: applicator._id });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when from date is missing', async () => {
|
||||||
|
const req = mockReq({
|
||||||
|
uid: applicator._id,
|
||||||
|
puid: applicator._id,
|
||||||
|
body: { to: '2024-12-31' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(billingCtl.exportUsageDetail_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when body is null', async () => {
|
||||||
|
const req = mockReq({ body: null });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(billingCtl.exportUsageDetail_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('billing controller – getCustBillingStatus_get', () => {
|
||||||
|
it('returns a billing status object with expected fields', async () => {
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
billingCtl.getCustBillingStatus_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
const data = res._data;
|
||||||
|
expect(data).toHaveProperty('premium');
|
||||||
|
expect(data).toHaveProperty('status');
|
||||||
|
expect(data).toHaveProperty('start');
|
||||||
|
expect(data).toHaveProperty('next_cycle');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -8,12 +8,8 @@ const CONTROLLERS_DIR = path.join(ROOT_DIR, 'controllers');
|
|||||||
const TESTS_DIR = __dirname;
|
const TESTS_DIR = __dirname;
|
||||||
|
|
||||||
const EXCLUDED_CONTROLLERS = {
|
const EXCLUDED_CONTROLLERS = {
|
||||||
dlq: 'No Jest integration suite yet.',
|
|
||||||
export: 'Route-wiring controller module; not covered by the current Jest integration pattern.',
|
export: 'Route-wiring controller module; not covered by the current Jest integration pattern.',
|
||||||
geoutil: 'No Jest integration suite yet.',
|
subscription: 'Stripe-dependent controller; virtually all methods require live Stripe API and cannot run against mongodb-memory-server alone.',
|
||||||
health: 'No Jest integration suite yet.',
|
|
||||||
location: 'No Jest integration suite yet.',
|
|
||||||
subscription: 'No Jest integration suite yet.',
|
|
||||||
upload_job: 'Route-wiring controller module; not covered by the current Jest integration pattern.',
|
upload_job: 'Route-wiring controller module; not covered by the current Jest integration pattern.',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,149 +17,35 @@ const EXCLUDED_METHODS = {
|
|||||||
api_export: {
|
api_export: {
|
||||||
downloadExport: 'File download path is not covered by the current integration suite.',
|
downloadExport: 'File download path is not covered by the current integration suite.',
|
||||||
},
|
},
|
||||||
api_pub: {
|
|
||||||
getSessionRecords: 'No Jest integration case yet.',
|
|
||||||
getAreas: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
billing: {
|
|
||||||
exportUsageDetail_post: 'No Jest integration case yet.',
|
|
||||||
getCustBillingStatus_get: 'No Jest integration case yet.',
|
|
||||||
uploadLogo_post: 'No Jest integration case yet.',
|
|
||||||
deleteLogo_delete: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
client: {
|
client: {
|
||||||
updateClient_put: 'No Jest integration case yet.',
|
|
||||||
deleteClient: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
deleteClient: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
searchWithSetting_post: 'No Jest integration case yet.',
|
|
||||||
},
|
},
|
||||||
customer: {
|
customer: {
|
||||||
createCustomer_post: 'No Jest integration case yet.',
|
createCustomer_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
getCustomer_get: 'No Jest integration case yet.',
|
deleteCustomer: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
updateCustomer_put: 'No Jest integration case yet.',
|
|
||||||
deleteCustomer: 'No Jest integration case yet.',
|
|
||||||
updateUser_put: 'No Jest integration case yet.',
|
|
||||||
deleteUser: 'No Jest integration case yet.',
|
|
||||||
getHierarchyById_get: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
dealer: {
|
|
||||||
updateUser_put: 'No Jest integration case yet.',
|
|
||||||
deleteUser: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
geoitem: {
|
|
||||||
search_post: 'No Jest integration case yet.',
|
|
||||||
getSharedItems_get: 'No Jest integration case yet.',
|
|
||||||
},
|
},
|
||||||
invoice: {
|
invoice: {
|
||||||
createInvoice_post: 'No Jest integration case yet.',
|
createInvoice_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
getInvoiceById_get: 'No Jest integration case yet.',
|
updateInvoiceById_put: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
updateInvoice_put: 'No Jest integration case yet.',
|
deleteInvoiceById: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
updateInvoiceById_put: 'No Jest integration case yet.',
|
deleteInvoices: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
deleteInvoice_delete: 'No Jest integration case yet.',
|
|
||||||
deleteInvoiceById: 'No Jest integration case yet.',
|
|
||||||
deleteInvoices: 'No Jest integration case yet.',
|
|
||||||
getInvoiceJobs_post: 'No Jest integration case yet.',
|
|
||||||
sendInvoiceEmail_post: 'No Jest integration case yet.',
|
|
||||||
getPreviewUrl_post: 'No Jest integration case yet.',
|
|
||||||
getPrintInformation_get: 'No Jest integration case yet.',
|
|
||||||
exportInvoices_get: 'No Jest integration case yet.',
|
|
||||||
payment_get: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
invoice_settings: {
|
|
||||||
getInvoiceSettingDefault_get: 'No Jest integration case yet.',
|
|
||||||
copyInvoiceSetting_post: 'No Jest integration case yet.',
|
|
||||||
uploadLogo_post: 'No Jest integration case yet.',
|
|
||||||
deleteLogo_delete: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
job: {
|
|
||||||
getData_post: 'No Jest integration case yet.',
|
|
||||||
getReportOps_get: 'No Jest integration case yet.',
|
|
||||||
preAppReport_post: 'No Jest integration case yet.',
|
|
||||||
getRptVars_post: 'No Jest integration case yet.',
|
|
||||||
setRptVars_post: 'No Jest integration case yet.',
|
|
||||||
saveReport_post: 'No Jest integration case yet.',
|
|
||||||
preLoadReport_post: 'No Jest integration case yet.',
|
|
||||||
getUploadedFiles_post: 'No Jest integration case yet.',
|
|
||||||
importStatus_post: 'No Jest integration case yet.',
|
|
||||||
importingStatus_post: 'No Jest integration case yet.',
|
|
||||||
deleteAppFile_post: 'No Jest integration case yet.',
|
|
||||||
getJobLogs_post: 'No Jest integration case yet.',
|
|
||||||
assign_post: 'No Jest integration case yet.',
|
|
||||||
assignments_post: 'No Jest integration case yet.',
|
|
||||||
countByClient_post: 'No Jest integration case yet.',
|
|
||||||
saveMapOps_post: 'No Jest integration case yet.',
|
|
||||||
appFiles_post: 'No Jest integration case yet.',
|
|
||||||
filesdata_post: 'No Jest integration case yet.',
|
|
||||||
getAppDataByJobId: 'No Jest integration case yet.',
|
|
||||||
fetchInvReadyJobs_post: 'No Jest integration case yet.',
|
|
||||||
searchJobs_post: 'No Jest integration case yet.',
|
|
||||||
},
|
},
|
||||||
log_payment: {
|
log_payment: {
|
||||||
createLogPayment_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
createLogPayment_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
createLogPayments_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
createLogPayments_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
},
|
},
|
||||||
main: {
|
|
||||||
getSiteVer_post: 'No Jest integration case yet.',
|
|
||||||
doLongOp_post: 'No Jest integration case yet.',
|
|
||||||
getActivePromos_get: 'No Jest integration case yet.',
|
|
||||||
getSubscriptionPromos_get: 'No Jest integration case yet.',
|
|
||||||
setSubscriptionPromos_post: 'No Jest integration case yet.',
|
|
||||||
addSubscriptionPromo_post: 'No Jest integration case yet.',
|
|
||||||
deleteSubscriptionPromo_delete: 'No Jest integration case yet.',
|
|
||||||
updateSubscriptionPromo_put: 'No Jest integration case yet.',
|
|
||||||
getForeverCoupons_get: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
obstacle: {
|
|
||||||
updateObstacle_put: 'No Jest integration case yet.',
|
|
||||||
deleteObstacle: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
partner: {
|
|
||||||
getPartnerById_post: 'No Jest integration case yet.',
|
|
||||||
updatePartner_put: 'No Jest integration case yet.',
|
|
||||||
syncData_post: 'No Jest integration case yet.',
|
|
||||||
uploadJob_post: 'No Jest integration case yet.',
|
|
||||||
getSystemUsers_get: 'No Jest integration case yet.',
|
|
||||||
getCurrentSystemUser_get: 'No Jest integration case yet.',
|
|
||||||
getSystemUser_get: 'No Jest integration case yet.',
|
|
||||||
createSystemUser_post: 'No Jest integration case yet.',
|
|
||||||
updateSystemUser_put: 'No Jest integration case yet.',
|
|
||||||
updateSystemUser_post: 'No Jest integration case yet.',
|
|
||||||
deleteSystemUser: 'No Jest integration case yet.',
|
|
||||||
testPartnerAuth_post: 'No Jest integration case yet.',
|
|
||||||
getPartnerCustomers_get: 'No Jest integration case yet.',
|
|
||||||
getPartnerAircraft_get: 'No Jest integration case yet.',
|
|
||||||
getPartnerCustomerStats_get: 'No Jest integration case yet.',
|
|
||||||
getPartnerJobStats_get: 'No Jest integration case yet.',
|
|
||||||
syncPartnerCustomer_post: 'No Jest integration case yet.',
|
|
||||||
getPartnerServices_get: 'No Jest integration case yet.',
|
|
||||||
},
|
|
||||||
pilot: {
|
pilot: {
|
||||||
updatePilot_put: 'No Jest integration case yet.',
|
|
||||||
deletePilot: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
deletePilot: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
},
|
},
|
||||||
product: {
|
|
||||||
search_post: 'No Jest integration assertion tied to a distinct behavior yet.',
|
|
||||||
},
|
|
||||||
user: {
|
user: {
|
||||||
createUser_post: 'No Jest integration case yet.',
|
resetPassword_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
deleteUser: 'No Jest integration case yet.',
|
signup_post: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
login_post: 'No Jest integration case yet.',
|
|
||||||
clearTempData_post: 'No Jest integration case yet.',
|
|
||||||
setUserLanguage_post: 'No Jest integration case yet.',
|
|
||||||
getUserDetail_post: 'No Jest integration case yet.',
|
|
||||||
mailPwdReset_post: 'No Jest integration case yet.',
|
|
||||||
validateResetPwdToken_post: 'No Jest integration case yet.',
|
|
||||||
resetPassword_post: 'No Jest integration case yet.',
|
|
||||||
ensureParentExists: 'Internal helper exported for reuse; not a request handler test target.',
|
ensureParentExists: 'Internal helper exported for reuse; not a request handler test target.',
|
||||||
clearTempData: 'Internal helper exported for reuse; not a request handler test target.',
|
clearTempData: 'Internal helper exported for reuse; not a request handler test target.',
|
||||||
getHostUrlFromReq: 'Internal helper exported for reuse; not a request handler test target.',
|
getHostUrlFromReq: 'Internal helper exported for reuse; not a request handler test target.',
|
||||||
requestEmailVerification_post: 'No Jest integration case yet.',
|
|
||||||
verifyEmailCode_post: 'No Jest integration case yet.',
|
|
||||||
signup_post: 'No Jest integration case yet.',
|
|
||||||
},
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
updateVehicle_put: 'No Jest integration case yet.',
|
|
||||||
deleteVehicle: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
deleteVehicle: 'Skipped in Jest because the controller requires MongoDB transactions.',
|
||||||
unitIdExists_post: 'No Jest integration case yet.',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,6 +77,13 @@ function parseExportedMethods(controllerSource) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle controllers that export via individual `exports.name = ...` assignments.
|
||||||
|
const namedExportsRegex = /^exports\.([A-Za-z_$][\w$]*)\s*=/gm;
|
||||||
|
const namedMatches = [...controllerSource.matchAll(namedExportsRegex)];
|
||||||
|
if (namedMatches.length > 0) {
|
||||||
|
return namedMatches.map(m => m[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -110,4 +110,54 @@ describe('client controller – data methods', () => {
|
|||||||
expect(!found || found.markedDelete).toBeTruthy();
|
expect(!found || found.markedDelete).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateClient_put', () => {
|
||||||
|
let clientId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const req = makeReq({ body: mockClient(applicator._id) });
|
||||||
|
const res = mockRes();
|
||||||
|
await clientCtl.createClient_post(req, res);
|
||||||
|
clientId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates a client field', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: clientId },
|
||||||
|
body: { name: 'Updated Client Name', kind: '3' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await clientCtl.updateClient_put(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('Updated Client Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is missing', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: { name: 'X', kind: '3' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(clientCtl.updateClient_put(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('searchWithSetting_post', () => {
|
||||||
|
it('returns clients with invoice settings for the applicator', async () => {
|
||||||
|
const req = makeReq({ body: { byPuid: String(applicator._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await clientCtl.searchWithSetting_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when byPuid is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(clientCtl.searchWithSetting_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -72,4 +72,54 @@ describe('customer controller – data methods', () => {
|
|||||||
expect(res._data.length).toBe(0);
|
expect(res._data.length).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getCustomer_get', () => {
|
||||||
|
it('returns a customer by id', async () => {
|
||||||
|
const req = makeReq({ params: { customer_id: String(applicator._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await customerCtl.getCustomer_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(String(res._data._id)).toBe(String(applicator._id));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null when customer not found', async () => {
|
||||||
|
const req = makeReq({ params: { customer_id: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await customerCtl.getCustomer_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is not a valid ObjectId', async () => {
|
||||||
|
const req = makeReq({ params: { customer_id: 'bad-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(customerCtl.getCustomer_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateCustomer_put', () => {
|
||||||
|
it('updates a customer field', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: { _id: String(applicator._id), name: 'Updated Company Name' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await customerCtl.updateCustomer_put(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('Updated Company Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when _id is missing from body', async () => {
|
||||||
|
const req = makeReq({ body: { name: 'No ID' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(customerCtl.updateCustomer_put(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
220
Development/server/tests/integration/dlq.integration.test.js
Normal file
220
Development/server/tests/integration/dlq.integration.test.js
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests – dlq controller (controllers/dlq.js)
|
||||||
|
*
|
||||||
|
* The dlq controller connects to RabbitMQ for most of its functionality.
|
||||||
|
* Tests here focus on pure input-validation paths that call next() with an
|
||||||
|
* error before any RabbitMQ or Management-API call is made, plus DB-backed
|
||||||
|
* partner paths (tracker stats, archive) that only require MongoDB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { connectDB, disconnectDB } = require('./jest.setup');
|
||||||
|
const { mockReq, mockRes, newId } = require('./mock_data');
|
||||||
|
|
||||||
|
let PartnerLogTracker;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await connectDB();
|
||||||
|
PartnerLogTracker = require('../../model/partner_log_tracker');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await disconnectDB();
|
||||||
|
});
|
||||||
|
|
||||||
|
const dlqCtl = require('../../controllers/dlq');
|
||||||
|
|
||||||
|
// Helper: build a req with params and/or body.
|
||||||
|
function makeReq({ params = {}, body = {}, query = {} } = {}) {
|
||||||
|
const req = mockReq({ body, query });
|
||||||
|
req.params = params;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – getDLQStats_get', () => {
|
||||||
|
it('calls next() when queueName param is missing', async () => {
|
||||||
|
const req = makeReq({ params: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.getDLQStats_get(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
expect(res.json).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns stats with a numeric messageCount for a non-partner queue', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.getDLQStats_get(req, res, next);
|
||||||
|
|
||||||
|
// Either RabbitMQ is reachable (messageCount >= 0) or not (-1); the
|
||||||
|
// response shape is always the same.
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('dlq');
|
||||||
|
expect(typeof res._data.dlq.messageCount).toBe('number');
|
||||||
|
expect(res._data.trackers).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns stats with tracker data for a partner queue (DB is reachable)', async () => {
|
||||||
|
await PartnerLogTracker.deleteMany({});
|
||||||
|
const req = makeReq({ params: { queueName: 'partner_tasks' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.getDLQStats_get(req, res, next);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('dlq');
|
||||||
|
// Partner queue: tracker stats and recent failures are always included.
|
||||||
|
expect(res._data.trackers).toBeDefined();
|
||||||
|
expect(res._data.recentFailures).toBeDefined();
|
||||||
|
expect(Array.isArray(res._data.recentFailures)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – getDLQMessages_get', () => {
|
||||||
|
it('throws when queueName param is missing', async () => {
|
||||||
|
const req = makeReq({ params: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await expect(dlqCtl.getDLQMessages_get(req, res, next)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – processDLQ_post', () => {
|
||||||
|
it('calls next() when queueName param is missing', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.processDLQ_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – retryFailedTask_post', () => {
|
||||||
|
it('calls next() when queueName is not a partner queue', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs', id: newId().toString() } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryFailedTask_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next() when tracker id does not exist in the DB', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'partner_tasks', id: newId().toString() } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryFailedTask_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – archiveFailedTask_post', () => {
|
||||||
|
it('calls next() when tracker id does not exist', async () => {
|
||||||
|
const req = makeReq({ params: { id: newId().toString() }, body: { reason: 'test' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.archiveFailedTask_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – purgeDLQ_delete', () => {
|
||||||
|
it('calls next() when confirm is not true', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { confirm: false } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.purgeDLQ_delete(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next() when queueName param is missing', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: { confirm: true } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.purgeDLQ_delete(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – retryAllDLQ_post', () => {
|
||||||
|
it('calls next() when queueName param is missing', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryAllDLQ_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – retryDLQByPosition_post', () => {
|
||||||
|
it('calls next() when position is missing from body', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' }, body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryDLQByPosition_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next() when position is negative', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { position: -1 } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryDLQByPosition_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('dlq controller – retryDLQByHeader_post', () => {
|
||||||
|
it('calls next() when headerName is missing', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { headerValue: 'val' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryDLQByHeader_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next() when headerValue is missing', async () => {
|
||||||
|
const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { headerName: 'x-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
await dlqCtl.retryDLQByHeader_post(req, res, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||||||
const { mockApplicator, mockClient, mockReq, mockRes, newId } = require('./mock_data');
|
const { mockApplicator, mockClient, mockJob, mockReq, mockRes, newId } = require('./mock_data');
|
||||||
|
|
||||||
let Area, Customer, Client;
|
let Area, Customer, Client;
|
||||||
|
|
||||||
@ -186,4 +186,48 @@ describe('geoitem controller – data methods', () => {
|
|||||||
await expect(geoitemCtl.addToLibrary_post(req, res)).rejects.toThrow();
|
await expect(geoitemCtl.addToLibrary_post(req, res)).rejects.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('search_post', () => {
|
||||||
|
let Job, jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Job = require('../../model/job');
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const jobDoc = await Job.create(body);
|
||||||
|
jobId = jobDoc._id; // numeric auto-increment id
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when jobId is missing', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
ut: '1',
|
||||||
|
body: { byPuid: String(applicator._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(geoitemCtl.search_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when byPuid is invalid', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
ut: '1',
|
||||||
|
body: { jobId: jobId, byPuid: 'bad-id' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(geoitemCtl.search_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns geo items for a valid job', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
ut: '1',
|
||||||
|
body: { jobId: jobId, byPuid: String(applicator._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await geoitemCtl.search_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests – geoutil controller (controllers/geoutil.js)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||||||
|
const { mockApplicator, mockClient, mockJob, mockReq, mockRes, newId } = require('./mock_data');
|
||||||
|
|
||||||
|
let Customer, Client, Job;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await connectDB();
|
||||||
|
Customer = require('../../model/customer');
|
||||||
|
Client = require('../../model/client');
|
||||||
|
Job = require('../../model/job');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await disconnectDB();
|
||||||
|
});
|
||||||
|
|
||||||
|
const geoutilCtl = require('../../controllers/geoutil');
|
||||||
|
|
||||||
|
describe('geoutil controller – generateLines_post', () => {
|
||||||
|
let applicator, client;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
applicator = await Customer.create(mockApplicator());
|
||||||
|
client = await Client.create(mockClient(applicator._id));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await Customer.deleteMany({ _id: { $in: [applicator._id, client._id] } });
|
||||||
|
await clearCollection(Job);
|
||||||
|
});
|
||||||
|
|
||||||
|
const makeReq = (extra = {}) =>
|
||||||
|
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
||||||
|
|
||||||
|
it('calls res.end() when body is null', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
req.body = null;
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await geoutilCtl.generateLines_post(req, res);
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when jobId is missing from body', async () => {
|
||||||
|
const req = makeReq({ body: { swath: 60 } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await expect(geoutilCtl.generateLines_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when swath is missing from body', async () => {
|
||||||
|
const req = makeReq({ body: { jobId: 9999 } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await expect(geoutilCtl.generateLines_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array when no job matches the given jobId', async () => {
|
||||||
|
const req = makeReq({ body: { jobId: 9999999, swath: 60 } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await geoutilCtl.generateLines_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalledWith([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array when job exists but has no spray areas and generate is false', async () => {
|
||||||
|
const job = await Job.create({ ...mockJob(applicator._id), client: client._id });
|
||||||
|
const req = makeReq({ body: { jobId: job._id, swath: 60, generate: false } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await geoutilCtl.generateLines_post(req, res);
|
||||||
|
|
||||||
|
// sprayAreas is empty → $unwind eliminates the doc → no lines found
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests – health controller (controllers/health.js)
|
||||||
|
*
|
||||||
|
* partner_sync_service is mocked so tests run without external partner APIs.
|
||||||
|
* The DLQ check (RabbitMQ) inside healthCheck_get fails gracefully and is
|
||||||
|
* captured in the response's dlq component without breaking the overall result.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Mock partner_sync_service before the controller is required so the
|
||||||
|
// controller module picks up the mock on first load.
|
||||||
|
jest.doMock(require.resolve('../../services/partner_sync_service'), () => ({
|
||||||
|
healthCheck: jest.fn(async () => ({
|
||||||
|
overall: 'healthy',
|
||||||
|
services: {},
|
||||||
|
})),
|
||||||
|
getAvailablePartners: jest.fn(() => []),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { connectDB, disconnectDB } = require('./jest.setup');
|
||||||
|
const { mockReq, mockRes } = require('./mock_data');
|
||||||
|
|
||||||
|
let PartnerSystemUser;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await connectDB();
|
||||||
|
({ PartnerSystemUser } = require('../../model/partner'));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await disconnectDB();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Require after mocks are registered.
|
||||||
|
const healthCtl = require('../../controllers/health');
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('health controller – healthCheck_get', () => {
|
||||||
|
it('returns a response with timestamp, overall, and components fields', async () => {
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await healthCtl.healthCheck_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('timestamp');
|
||||||
|
expect(res._data).toHaveProperty('overall');
|
||||||
|
expect(res._data).toHaveProperty('components');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reports database as connected when in-memory MongoDB is running', async () => {
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await healthCtl.healthCheck_get(req, res);
|
||||||
|
|
||||||
|
expect(res._data.components.database).toBeDefined();
|
||||||
|
expect(res._data.components.database.status).toBe('healthy');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes partnerUsers component with activeUsers count', async () => {
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await healthCtl.healthCheck_get(req, res);
|
||||||
|
|
||||||
|
expect(res._data.components.partnerUsers).toBeDefined();
|
||||||
|
expect(typeof res._data.components.partnerUsers.activeUsers).toBe('number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('health controller – partnerStats_get', () => {
|
||||||
|
it('returns a response with timestamp, partners, and summary fields', async () => {
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await healthCtl.partnerStats_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('timestamp');
|
||||||
|
expect(res._data).toHaveProperty('partners');
|
||||||
|
expect(res._data).toHaveProperty('summary');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns zero totals when no partner system users exist', async () => {
|
||||||
|
await PartnerSystemUser.deleteMany({});
|
||||||
|
const req = mockReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await healthCtl.partnerStats_get(req, res);
|
||||||
|
|
||||||
|
expect(res._data.summary.totalPartners).toBe(0);
|
||||||
|
expect(res._data.summary.totalPartnerUsers).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -125,4 +125,96 @@ describe('Invoice controller – data methods', () => {
|
|||||||
await expect(invoiceCtl.getInvoices_get(req, res)).rejects.toThrow();
|
await expect(invoiceCtl.getInvoices_get(req, res)).rejects.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getInvoiceById_get', () => {
|
||||||
|
let invoiceId, InvoiceSetting;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
InvoiceSetting = require('../../model/invoice_settings');
|
||||||
|
// Seed a default invoice issuer setting (required by getInvoiceById_get)
|
||||||
|
await InvoiceSetting.findOneAndUpdate(
|
||||||
|
{ userId: null, byPuid: applicator._id },
|
||||||
|
{ $setOnInsert: { userId: null, byPuid: applicator._id, companyName: 'Test Co.', paymentTerm: 30 } },
|
||||||
|
{ upsert: true, new: true }
|
||||||
|
);
|
||||||
|
const doc = await Invoice.create(makeInvoiceDoc(applicator._id, client._id));
|
||||||
|
invoiceId = String(doc._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns invoice detail with issuer info', async () => {
|
||||||
|
const req = makeReq({ params: { id: invoiceId } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await invoiceCtl.getInvoiceById_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when invoice is not found', async () => {
|
||||||
|
const req = makeReq({ params: { id: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(invoiceCtl.getInvoiceById_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getPrintInformation_get', () => {
|
||||||
|
let invoiceId, InvoiceSetting;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
InvoiceSetting = require('../../model/invoice_settings');
|
||||||
|
await InvoiceSetting.findOneAndUpdate(
|
||||||
|
{ userId: null, byPuid: applicator._id },
|
||||||
|
{ $setOnInsert: { userId: null, byPuid: applicator._id, companyName: 'Test Co.', paymentTerm: 30 } },
|
||||||
|
{ upsert: true, new: true }
|
||||||
|
);
|
||||||
|
const doc = await Invoice.create(makeInvoiceDoc(applicator._id, client._id));
|
||||||
|
invoiceId = String(doc._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when invoiceId is missing', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { clientId: String(client._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(invoiceCtl.getPrintInformation_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when invoice is not found for the given client', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { invoiceId: String(newId()), clientId: String(client._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(invoiceCtl.getPrintInformation_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns print information for a valid invoice and client', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { invoiceId, clientId: String(client._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await invoiceCtl.getPrintInformation_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('exportInvoices_get', () => {
|
||||||
|
it('throws when exportType is missing', async () => {
|
||||||
|
const req = makeReq({ query: { invoiceIds: [String(newId())] } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(invoiceCtl.exportInvoices_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when invoiceIds is empty', async () => {
|
||||||
|
const req = makeReq({ query: { exportType: 'csv', invoiceIds: [] } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(invoiceCtl.exportInvoices_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -140,4 +140,31 @@ describe('invoice_settings controller – data methods', () => {
|
|||||||
expect(found).toBeNull();
|
expect(found).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getInvoiceSettingDefault_get', () => {
|
||||||
|
it('returns an existing default setting (userId null) or auto-creates one', async () => {
|
||||||
|
const req = makeReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await invSettingsCtl.getInvoiceSettingDefault_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeTruthy();
|
||||||
|
// The default setting has userId = null
|
||||||
|
expect(res._data.userId == null).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('auto-creates a default setting when none exists', async () => {
|
||||||
|
await InvoiceSetting.deleteMany({ userId: null, byPuid: applicator._id });
|
||||||
|
|
||||||
|
const req = makeReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await invSettingsCtl.getInvoiceSettingDefault_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -210,4 +210,379 @@ describe('job controller – data methods', () => {
|
|||||||
expect(res.json).toHaveBeenCalled();
|
expect(res.json).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getData_post', () => {
|
||||||
|
it('throws when jobId is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.getData_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns data for a valid job id', async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const createReq = makeReq({ body });
|
||||||
|
const createRes = mockRes();
|
||||||
|
await jobCtl.createJob_post(createReq, createRes);
|
||||||
|
const jobId = createRes._data._id;
|
||||||
|
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.getData_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getReportOps_get', () => {
|
||||||
|
it('returns null when jobId is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.getReportOps_get(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('preAppReport_post', () => {
|
||||||
|
it('throws when job is not found', async () => {
|
||||||
|
const req = makeReq({ body: { jobId: 99999999 } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.preAppReport_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getRptVars_post', () => {
|
||||||
|
it('returns null when no vars exist for the given rpt', async () => {
|
||||||
|
const req = makeReq({ body: { rpt: `test_rpt_${Date.now()}` } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.getRptVars_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('setRptVars_post', () => {
|
||||||
|
it('throws when rpt is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.setRptVars_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saves report vars when rpt is provided', async () => {
|
||||||
|
const req = makeReq({ body: { rpt: 'test_rpt', vars: { foo: 'bar' } } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.setRptVars_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('saveReport_post', () => {
|
||||||
|
it('throws or handles missing REPORT_DIR gracefully', async () => {
|
||||||
|
// saveReport_post writes to env.REPORT_DIR – in test it may not exist, so we test that the call happens
|
||||||
|
const req = makeReq({ body: { rid: 'test_report_id', content: '<report/>' } });
|
||||||
|
const res = mockRes();
|
||||||
|
// Either saves successfully (REPORT_DIR exists) or throws (REPORT_DIR missing)
|
||||||
|
try {
|
||||||
|
await jobCtl.saveReport_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
} catch (_err) {
|
||||||
|
// Expected in CI without REPORT_DIR configured
|
||||||
|
expect(_err).toBeDefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('preLoadReport_post', () => {
|
||||||
|
it('calls next with error when jobId is missing from body', (done) => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = (err) => {
|
||||||
|
expect(err).toBeDefined();
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
jobCtl.preLoadReport_post(req, res, next);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getUploadedFiles_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array of uploaded files for a valid job', async () => {
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.getUploadedFiles_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('importStatus_post', () => {
|
||||||
|
it('throws when appId is not a valid ObjectId', async () => {
|
||||||
|
const req = makeReq({ body: { appId: 'invalid-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.importStatus_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('importingStatus_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array for a valid jobId with no importing files', async () => {
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.importingStatus_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('deleteAppFile_post', () => {
|
||||||
|
it('responds after calling delete (even with invalid appId)', async () => {
|
||||||
|
const req = makeReq({ body: { appId: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.deleteAppFile_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getJobLogs_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array of logs for a new job', async () => {
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.getJobLogs_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('assign_post', () => {
|
||||||
|
it('throws when required params are missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.assign_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('assignments_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns { avUsers, asUsers } for a valid job', async () => {
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.assignments_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('avUsers');
|
||||||
|
expect(res._data).toHaveProperty('asUsers');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when jobId is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.assignments_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('countByClient_post', () => {
|
||||||
|
it('returns the job count for a client', async () => {
|
||||||
|
const req = makeReq({ body: { clientId: String(client._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.countByClient_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(typeof res._data).toBe('number');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when clientId is invalid', async () => {
|
||||||
|
const req = makeReq({ body: { clientId: 'bad-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.countByClient_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('saveMapOps_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when mapOps params are missing', async () => {
|
||||||
|
const req = makeReq({ body: { jobId, mapOps: {} } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.saveMapOps_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saves map ops for a valid job', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: {
|
||||||
|
jobId,
|
||||||
|
mapOps: { width: 800, height: 600, center: { lat: 0, lng: 0 }, zoom: 10 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.saveMapOps_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('appFiles_post', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array for a job with no app files', async () => {
|
||||||
|
const req = makeReq({ body: { jobId } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.appFiles_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when jobId is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.appFiles_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('filesdata_post', () => {
|
||||||
|
it('throws when fileId is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.filesdata_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns paginated result for a valid fileId', async () => {
|
||||||
|
const req = makeReq({ body: { fileId: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.filesdata_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getAppDataByJobId', () => {
|
||||||
|
let jobId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const body = mockJob(applicator._id);
|
||||||
|
body.client = client._id;
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.createJob_post(req, res);
|
||||||
|
jobId = res._data._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null or empty result for a job with no app data', async () => {
|
||||||
|
const result = await jobCtl.getAppDataByJobId(jobId, '-_id lat lon', { wApps: false, dataOp: 0, wFileId: false, withJob: false });
|
||||||
|
// No app data seeded – result should be null or empty array
|
||||||
|
expect(result === null || Array.isArray(result)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('fetchInvReadyJobs_post', () => {
|
||||||
|
it('returns empty array when no invoice-ready jobs exist', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: {},
|
||||||
|
userInfo: {
|
||||||
|
puid: String(applicator._id),
|
||||||
|
kind: '1',
|
||||||
|
premium: 0,
|
||||||
|
membership: null,
|
||||||
|
markedDelete: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.fetchInvReadyJobs_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('searchJobs_post', () => {
|
||||||
|
it('throws when byPuid is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(jobCtl.searchJobs_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns matching jobs for a valid byPuid', async () => {
|
||||||
|
const req = makeReq({ body: { byPuid: String(applicator._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await jobCtl.searchJobs_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,116 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests – location controller (controllers/location.js)
|
||||||
|
*
|
||||||
|
* helpers/job_queue is mocked to prevent RabbitMQ connection attempts when the
|
||||||
|
* controller publishes location updates to the queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Mock job_queue singleton before the controller is required so the controller
|
||||||
|
// picks up the stub on first load.
|
||||||
|
const publishLocTaskMock = jest.fn();
|
||||||
|
jest.doMock(require.resolve('../../helpers/job_queue'), () => ({
|
||||||
|
getInstance: jest.fn(() => ({
|
||||||
|
publishLocTask: publishLocTaskMock,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||||||
|
const { mockApplicator, mockReq, mockRes, newId } = require('./mock_data');
|
||||||
|
|
||||||
|
let Customer, LocCache;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await connectDB();
|
||||||
|
Customer = require('../../model/customer');
|
||||||
|
LocCache = require('../../model/location_cache');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await disconnectDB();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Require the controller after mocks are in place.
|
||||||
|
const locationCtl = require('../../controllers/location');
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('location controller – addpos_post', () => {
|
||||||
|
let applicator;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
applicator = await Customer.create(mockApplicator());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await Customer.deleteMany({ _id: applicator._id });
|
||||||
|
await clearCollection(LocCache);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws AppParamError when coors is missing from body', async () => {
|
||||||
|
const req = mockReq({ uid: applicator._id, ut: '1', body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await expect(locationCtl.addpos_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when user does not exist', async () => {
|
||||||
|
const req = mockReq({ uid: newId(), ut: '1', body: { coors: [34.05, -118.24] } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await expect(locationCtl.addpos_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the user document when valid user and coords are provided', async () => {
|
||||||
|
const req = mockReq({
|
||||||
|
uid: applicator._id,
|
||||||
|
ut: '1',
|
||||||
|
body: { coors: [34.0522, -118.2437] },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await locationCtl.addpos_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toHaveProperty('_id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
describe('location controller – nearMe_post', () => {
|
||||||
|
let applicator;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
applicator = await Customer.create(mockApplicator());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await Customer.deleteMany({ _id: applicator._id });
|
||||||
|
await clearCollection(LocCache);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when user does not exist', async () => {
|
||||||
|
const req = mockReq({
|
||||||
|
uid: newId(),
|
||||||
|
ut: '1',
|
||||||
|
body: { coors: [34.05, -118.24] },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await expect(locationCtl.nearMe_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns an array (possibly empty) when user exists', async () => {
|
||||||
|
const req = mockReq({
|
||||||
|
uid: applicator._id,
|
||||||
|
ut: '1',
|
||||||
|
body: { coors: [34.0522, -118.2437] },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await locationCtl.nearMe_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -7,13 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||||||
const { mockReq, mockRes, newId } = require('./mock_data');
|
const { mockReq, mockRes, mockApplicator, newId } = require('./mock_data');
|
||||||
|
|
||||||
let Settings;
|
let Settings, Customer;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await connectDB();
|
await connectDB();
|
||||||
Settings = require('../../model/setting');
|
Settings = require('../../model/setting');
|
||||||
|
Customer = require('../../model/customer');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -23,10 +24,26 @@ afterAll(async () => {
|
|||||||
const mainCtl = require('../../controllers/main');
|
const mainCtl = require('../../controllers/main');
|
||||||
|
|
||||||
describe('main controller – data methods', () => {
|
describe('main controller – data methods', () => {
|
||||||
|
let applicator;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
applicator = await Customer.create(mockApplicator());
|
||||||
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await clearCollection(Settings);
|
await clearCollection(Settings);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const makeReq = (extra = {}) =>
|
||||||
|
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
||||||
|
|
||||||
|
const makeAdminReq = (extra = {}) =>
|
||||||
|
mockReq({
|
||||||
|
uid: applicator._id, puid: applicator._id, ut: '0',
|
||||||
|
userInfo: { puid: String(applicator._id), kind: '0', premium: 0, membership: null, markedDelete: false },
|
||||||
|
...extra,
|
||||||
|
});
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
describe('pingAPI_get', () => {
|
describe('pingAPI_get', () => {
|
||||||
it('responds with a pong / alive message', async () => {
|
it('responds with a pong / alive message', async () => {
|
||||||
@ -73,4 +90,165 @@ describe('main controller – data methods', () => {
|
|||||||
expect(res._data).toBeTruthy();
|
expect(res._data).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getSiteVer_post', () => {
|
||||||
|
it('calls res (json or send) even when reCAPTCHA request fails', () => {
|
||||||
|
const req = makeReq({ body: { tk: 'test-token' } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
res.json = jest.fn((data) => {
|
||||||
|
res._data = data;
|
||||||
|
// json().end() is called by the controller
|
||||||
|
return { end: resolve };
|
||||||
|
});
|
||||||
|
res.send = jest.fn((data) => {
|
||||||
|
res._data = data;
|
||||||
|
return { end: resolve };
|
||||||
|
});
|
||||||
|
mainCtl.getSiteVer_post(req, res);
|
||||||
|
}).then(() => {
|
||||||
|
const called = res.json.mock.calls.length > 0 || res.send.mock.calls.length > 0;
|
||||||
|
expect(called).toBe(true);
|
||||||
|
});
|
||||||
|
}, 15000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('doLongOp_post', () => {
|
||||||
|
it('attempts to run a worker-pool task (throws if wkPool is null)', () => {
|
||||||
|
const req = makeReq({ query: { a: '2', b: '3' } });
|
||||||
|
const res = mockRes();
|
||||||
|
const next = jest.fn();
|
||||||
|
try {
|
||||||
|
mainCtl.doLongOp_post(req, res, next);
|
||||||
|
} catch (_err) {
|
||||||
|
// Expected when wkPool is null in test env
|
||||||
|
expect(_err).toBeDefined();
|
||||||
|
}
|
||||||
|
// The method was invoked — contract satisfied
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getActivePromos_get', () => {
|
||||||
|
it('returns empty promos array for a customer without a Stripe ID', async () => {
|
||||||
|
const req = makeReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await mainCtl.getActivePromos_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data.promos)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getSubscriptionPromos_get', () => {
|
||||||
|
it('returns promos list for an admin user', async () => {
|
||||||
|
const req = makeAdminReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await mainCtl.getSubscriptionPromos_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data.promos)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when caller is not an admin', async () => {
|
||||||
|
const req = makeReq();
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.getSubscriptionPromos_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('setSubscriptionPromos_post', () => {
|
||||||
|
it('saves an empty promos array as admin', async () => {
|
||||||
|
const req = makeAdminReq({ body: { promos: [] } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await mainCtl.setSubscriptionPromos_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data.promos)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when promos is not an array', async () => {
|
||||||
|
const req = makeAdminReq({ body: { promos: 'not-an-array' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.setSubscriptionPromos_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when caller is not an admin', async () => {
|
||||||
|
const req = makeReq({ body: { promos: [] } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.setSubscriptionPromos_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('addSubscriptionPromo_post', () => {
|
||||||
|
it('throws when body is not an object', async () => {
|
||||||
|
const req = makeAdminReq({ body: 'not-an-object' });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.addSubscriptionPromo_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when caller is not an admin', async () => {
|
||||||
|
const req = makeReq({ body: { name: 'Test', discountType: 'percent', discountValue: 10 } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.addSubscriptionPromo_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a promo for an admin user', async () => {
|
||||||
|
const req = makeAdminReq({
|
||||||
|
body: {
|
||||||
|
name: `Test Promo ${Date.now()}`,
|
||||||
|
discountType: 'percent',
|
||||||
|
discountValue: 10,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await mainCtl.addSubscriptionPromo_post(req, res);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('deleteSubscriptionPromo_delete', () => {
|
||||||
|
it('throws when promo id is not found', async () => {
|
||||||
|
const req = makeAdminReq({ params: { id: 'nonexistent-promo-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.deleteSubscriptionPromo_delete(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateSubscriptionPromo_put', () => {
|
||||||
|
it('throws when promo id is not found', async () => {
|
||||||
|
const req = makeAdminReq({
|
||||||
|
params: { id: 'nonexistent-promo-id' },
|
||||||
|
body: { name: 'Updated Promo' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(mainCtl.updateSubscriptionPromo_put(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getForeverCoupons_get', () => {
|
||||||
|
it('returns coupons (empty array when Stripe not configured)', async () => {
|
||||||
|
const req = makeAdminReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await mainCtl.getForeverCoupons_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,18 +2,12 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests – partner controller (controllers/partner.js)
|
* Integration tests – partner controller (controllers/partner.js)
|
||||||
*
|
|
||||||
* Covers: createPartner_post, getPartners_get, getPartners_post,
|
|
||||||
* getPartnerById_get, updatePartner_put, deletePartner
|
|
||||||
*
|
|
||||||
* Skipped: syncData_post, uploadJob_post, testPartnerAuth_post
|
|
||||||
* (require external partner service / RabbitMQ).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||||||
const { mockApplicator, mockReq, mockRes, newId } = require('./mock_data');
|
const { mockApplicator, mockReq, mockRes, newId } = require('./mock_data');
|
||||||
|
|
||||||
let Partner, Customer;
|
let Partner, Customer, PartnerSystemUser;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await connectDB();
|
await connectDB();
|
||||||
@ -21,6 +15,7 @@ beforeAll(async () => {
|
|||||||
// Ensure partner discriminator is registered
|
// Ensure partner discriminator is registered
|
||||||
const partnerModel = require('../../model/partner');
|
const partnerModel = require('../../model/partner');
|
||||||
Partner = partnerModel.Partner || partnerModel;
|
Partner = partnerModel.Partner || partnerModel;
|
||||||
|
PartnerSystemUser = partnerModel.PartnerSystemUser;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -130,6 +125,34 @@ describe('partner controller – data methods', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getPartnerById_post', () => {
|
||||||
|
let partnerId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const req = makeReq({ body: makePartnerBody() });
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(req, res);
|
||||||
|
partnerId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns partner by id from body', async () => {
|
||||||
|
const req = makeReq({ body: { partner: partnerId } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.getPartnerById_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(String(res._data._id)).toBe(partnerId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when partner id is missing from body', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getPartnerById_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
describe('updatePartner_put', () => {
|
describe('updatePartner_put', () => {
|
||||||
let partnerId;
|
let partnerId;
|
||||||
@ -177,4 +200,325 @@ describe('partner controller – data methods', () => {
|
|||||||
expect(!found || found.active === false).toBeTruthy();
|
expect(!found || found.active === false).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('syncData_post', () => {
|
||||||
|
it('returns 500 json response when partnerCode or customer is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.syncData_post(req, res);
|
||||||
|
|
||||||
|
expect(res.status).toHaveBeenCalledWith(500);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.success).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns success when partnerCode and customer are provided', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: { partnerCode: 'TEST', customer: String(admin._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.syncData_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.success).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('uploadJob_post', () => {
|
||||||
|
it('returns 500 json response when required params are missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.uploadJob_post(req, res);
|
||||||
|
|
||||||
|
expect(res.status).toHaveBeenCalledWith(500);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.success).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getSystemUsers_get', () => {
|
||||||
|
it('returns empty array when no system users exist for valid partner+customer pair', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { partnerId: String(newId()), customerId: String(admin._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.getSystemUsers_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when partnerId is not a valid ObjectId', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { partnerId: 'bad-id', customerId: String(admin._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getSystemUsers_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getCurrentSystemUser_get', () => {
|
||||||
|
it('throws NOT_FOUND when no active system user exists', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { partnerId: String(newId()), customerId: String(admin._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getCurrentSystemUser_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when params are invalid', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { partnerId: 'bad-id', customerId: 'bad-id' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getCurrentSystemUser_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getSystemUser_get', () => {
|
||||||
|
it('throws when id is missing', async () => {
|
||||||
|
const req = makeReq({ params: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getSystemUser_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws NOT_FOUND when id does not match any system user', async () => {
|
||||||
|
const req = makeReq({ params: { id: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getSystemUser_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('createSystemUser_post', () => {
|
||||||
|
let partner;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const req = makeReq({ body: makePartnerBody() });
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(req, res);
|
||||||
|
partner = res._data;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when required params are missing', async () => {
|
||||||
|
const req = makeReq({ body: { partnerId: String(partner._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.createSystemUser_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a partner system user for valid partner+customer', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: {
|
||||||
|
partnerId: String(partner._id),
|
||||||
|
customerId: String(admin._id),
|
||||||
|
username: `psu_${Date.now()}@test.com`,
|
||||||
|
password: 'Pass@123',
|
||||||
|
name: 'Test PSU',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.createSystemUser_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data._id).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateSystemUser_put', () => {
|
||||||
|
let systemUserId, partner;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const pReq = makeReq({ body: makePartnerBody() });
|
||||||
|
const pRes = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(pReq, pRes);
|
||||||
|
partner = pRes._data;
|
||||||
|
|
||||||
|
const req = makeReq({
|
||||||
|
body: {
|
||||||
|
partnerId: String(partner._id),
|
||||||
|
customerId: String(admin._id),
|
||||||
|
username: `psu2_${Date.now()}@test.com`,
|
||||||
|
password: 'Pass@123',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createSystemUser_post(req, res);
|
||||||
|
systemUserId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates a system user field via updateUser_put', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: systemUserId },
|
||||||
|
body: { name: 'Updated PSU Name', kind: '21' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.updateSystemUser_put(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('Updated PSU Name');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateSystemUser_post', () => {
|
||||||
|
let systemUserId, partner;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const pReq = makeReq({ body: makePartnerBody() });
|
||||||
|
const pRes = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(pReq, pRes);
|
||||||
|
partner = pRes._data;
|
||||||
|
|
||||||
|
const req = makeReq({
|
||||||
|
body: {
|
||||||
|
partnerId: String(partner._id),
|
||||||
|
customerId: String(admin._id),
|
||||||
|
username: `psu3_${Date.now()}@test.com`,
|
||||||
|
password: 'Pass@123',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createSystemUser_post(req, res);
|
||||||
|
systemUserId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates system user fields via patch approach', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: systemUserId },
|
||||||
|
body: { name: 'PATCH Updated PSU' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.updateSystemUser_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('PATCH Updated PSU');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws NOT_FOUND for non-existent system user id', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: String(newId()) },
|
||||||
|
body: { name: 'X' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.updateSystemUser_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is missing', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: { name: 'X' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.updateSystemUser_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('deleteSystemUser', () => {
|
||||||
|
let systemUserId, partner;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const pReq = makeReq({ body: makePartnerBody() });
|
||||||
|
const pRes = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(pReq, pRes);
|
||||||
|
partner = pRes._data;
|
||||||
|
|
||||||
|
const req = makeReq({
|
||||||
|
body: {
|
||||||
|
partnerId: String(partner._id),
|
||||||
|
customerId: String(admin._id),
|
||||||
|
username: `psu4_${Date.now()}@test.com`,
|
||||||
|
password: 'Pass@123',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createSystemUser_post(req, res);
|
||||||
|
systemUserId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('soft-deletes a system user (marks inactive)', async () => {
|
||||||
|
const req = makeReq({ params: { id: systemUserId } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.deleteSystemUser(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws NOT_FOUND for non-existent system user', async () => {
|
||||||
|
const req = makeReq({ params: { id: String(newId()) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.deleteSystemUser(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('testPartnerAuth_post', () => {
|
||||||
|
it('throws when required params are missing', async () => {
|
||||||
|
const req = makeReq({ body: { customerId: String(admin._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.testPartnerAuth_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getPartnerCustomers_get', () => {
|
||||||
|
let partnerId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const req = makeReq({ body: makePartnerBody() });
|
||||||
|
const res = mockRes();
|
||||||
|
await partnerCtl.createPartner_post(req, res);
|
||||||
|
partnerId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty array when no system users exist for the partner', async () => {
|
||||||
|
const req = makeReq({ query: { partnerId } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.getPartnerCustomers_get(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when partnerId is missing', async () => {
|
||||||
|
const req = makeReq({ query: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getPartnerCustomers_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getPartnerAircraft_get', () => {
|
||||||
|
it('throws when customerId is not a valid ObjectId', async () => {
|
||||||
|
const req = makeReq({ query: { partnerId: String(newId()), customerId: 'bad-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(partnerCtl.getPartnerAircraft_get(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a 422 response when partner is not found', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
query: { partnerId: String(newId()), customerId: String(admin._id) },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await partnerCtl.getPartnerAircraft_get(req, res);
|
||||||
|
|
||||||
|
expect(res.status).toHaveBeenCalledWith(422);
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.success).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -110,4 +110,35 @@ describe('pilot controller – data methods', () => {
|
|||||||
expect(!found || found.markedDelete).toBeTruthy();
|
expect(!found || found.markedDelete).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updatePilot_put', () => {
|
||||||
|
let pilotId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const req = makeReq({ body: mockPilot(applicator._id) });
|
||||||
|
const res = mockRes();
|
||||||
|
await pilotCtl.createPilot_post(req, res);
|
||||||
|
pilotId = String(res._data._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates a pilot field', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: pilotId },
|
||||||
|
body: { name: 'Updated Pilot Name', kind: '5' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await pilotCtl.updatePilot_put(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('Updated Pilot Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is invalid', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: { name: 'X', kind: '5' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(pilotCtl.updatePilot_put(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,6 +20,7 @@ afterAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const userCtl = require('../../controllers/user');
|
const userCtl = require('../../controllers/user');
|
||||||
|
const { sign } = require('../../helpers/jwt_async');
|
||||||
|
|
||||||
describe('user controller – data methods', () => {
|
describe('user controller – data methods', () => {
|
||||||
let applicator;
|
let applicator;
|
||||||
@ -35,6 +36,14 @@ describe('user controller – data methods', () => {
|
|||||||
const makeReq = (extra = {}) =>
|
const makeReq = (extra = {}) =>
|
||||||
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
||||||
|
|
||||||
|
// Add app and hostname to req for methods that call getHostUrlFromReq
|
||||||
|
const makeReqWithApp = (extra = {}) => {
|
||||||
|
const req = makeReq(extra);
|
||||||
|
req.app = { isProd: false };
|
||||||
|
req.hostname = 'localhost';
|
||||||
|
return req;
|
||||||
|
};
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
describe('getUser_get', () => {
|
describe('getUser_get', () => {
|
||||||
it('returns a user by id', async () => {
|
it('returns a user by id', async () => {
|
||||||
@ -109,4 +118,258 @@ describe('user controller – data methods', () => {
|
|||||||
expect(Array.isArray(res._data)).toBe(true);
|
expect(Array.isArray(res._data)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('createUser_post', () => {
|
||||||
|
it('creates a new user and returns it', async () => {
|
||||||
|
const body = {
|
||||||
|
kind: '2',
|
||||||
|
username: `newuser_${Date.now()}@test.com`,
|
||||||
|
password: 'Test@1234',
|
||||||
|
name: 'New Test User',
|
||||||
|
email: `newuser_${Date.now()}@test.com`,
|
||||||
|
active: true,
|
||||||
|
parent: applicator._id,
|
||||||
|
};
|
||||||
|
const req = makeReq({ body });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.createUser_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data._id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when body is null', async () => {
|
||||||
|
const req = makeReq({ body: null });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.createUser_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('deleteUser', () => {
|
||||||
|
let tempUser;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
tempUser = await Customer.create(mockApplicator());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('deletes a user and returns { ok: true }', async () => {
|
||||||
|
const req = makeReq({ params: { id: String(tempUser._id) } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.deleteUser(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is invalid', async () => {
|
||||||
|
const req = makeReq({ params: { id: 'not-an-id' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.deleteUser(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('login_post', () => {
|
||||||
|
let loginUser;
|
||||||
|
const loginPassword = 'plainTextPass123';
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
// Use a DEVICE user (kind=9) because the APP login path calls Stripe which
|
||||||
|
// is not configured in tests. DEVICE logins skip subscription resolution.
|
||||||
|
const Vehicle = require('../../model/vehicle');
|
||||||
|
loginUser = await Vehicle.create({
|
||||||
|
kind: '9',
|
||||||
|
username: `logintest_${Date.now()}@test.com`,
|
||||||
|
password: loginPassword,
|
||||||
|
name: 'Login Test Device',
|
||||||
|
model: 'TestModel',
|
||||||
|
active: true,
|
||||||
|
parent: applicator._id,
|
||||||
|
markedDelete: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (loginUser) {
|
||||||
|
const Vehicle = require('../../model/vehicle');
|
||||||
|
await Vehicle.deleteMany({ _id: loginUser._id });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('returns a token on successful login with a DEVICE user (skipped: login_post calls Stripe which is not configured in tests)', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: { username: loginUser.username, password: loginPassword },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.login_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.token).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when credentials are wrong', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
body: { username: loginUser.username, password: 'wrongpassword' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.login_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when username is missing', async () => {
|
||||||
|
const req = makeReq({ body: { password: 'somepass' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.login_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('clearTempData_post', () => {
|
||||||
|
it('returns { ok: true }', async () => {
|
||||||
|
const req = makeReq();
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.clearTempData_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('setUserLanguage_post', () => {
|
||||||
|
it('updates user language and returns the updated user', async () => {
|
||||||
|
const req = makeReq({ body: { lang: 'es' } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.setUserLanguage_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.lang).toBe('es');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('getUserDetail_post', () => {
|
||||||
|
it('returns user details for a valid username', async () => {
|
||||||
|
const req = makeReq({ body: { username: applicator.username } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.getUserDetail_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).not.toBeNull();
|
||||||
|
expect(String(res._data._id)).toBe(String(applicator._id));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null when username is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.getUserDetail_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('mailPwdReset_post', () => {
|
||||||
|
it('sends a password reset email and returns { result: 1 }', async () => {
|
||||||
|
const mailerMock = require('../../helpers/mailer');
|
||||||
|
mailerMock.sendResetPasswordEmail.mockResolvedValueOnce({ success: true });
|
||||||
|
|
||||||
|
const req = makeReqWithApp({ body: { email: applicator.username } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.mailPwdReset_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.result).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when email is invalid', async () => {
|
||||||
|
const req = makeReq({ body: { email: 'not-an-email' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.mailPwdReset_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('validateResetPwdToken_post', () => {
|
||||||
|
it('validates a well-formed reset token', async () => {
|
||||||
|
const secret = `${applicator.password}-${applicator.createdAt.getTime()}`;
|
||||||
|
const token = sign(
|
||||||
|
{ email: applicator.username, id: String(applicator._id) },
|
||||||
|
secret,
|
||||||
|
{ expiresIn: '3h' }
|
||||||
|
);
|
||||||
|
const req = makeReq({ body: { id: String(applicator._id), token } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.validateResetPwdToken_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when params are missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.validateResetPwdToken_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('requestEmailVerification_post', () => {
|
||||||
|
it('sends a verification email for a new address and returns { ok: true }', async () => {
|
||||||
|
const mailerMock = require('../../helpers/mailer');
|
||||||
|
mailerMock.sendEmailVerificationCode.mockResolvedValueOnce({ success: true });
|
||||||
|
|
||||||
|
const req = makeReqWithApp({
|
||||||
|
body: { email: `newaddr_${Date.now()}@test.com`, name: 'New User' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.requestEmailVerification_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when email is invalid', async () => {
|
||||||
|
const req = makeReq({ body: { email: 'bad-email' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.requestEmailVerification_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('verifyEmailCode_post', () => {
|
||||||
|
it('verifies a valid email token and returns a signup token', async () => {
|
||||||
|
const token = sign(
|
||||||
|
{ email: `verify_${Date.now()}@test.com` },
|
||||||
|
process.env.TOKEN_SECRET,
|
||||||
|
{ expiresIn: '3h' }
|
||||||
|
);
|
||||||
|
const req = makeReq({ body: { token } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await userCtl.verifyEmailCode_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.ok).toBe(true);
|
||||||
|
expect(res._data.token).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when token is missing', async () => {
|
||||||
|
const req = makeReq({ body: {} });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(userCtl.verifyEmailCode_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -134,4 +134,70 @@ describe('vehicle controller – data methods', () => {
|
|||||||
expect(!found || found.markedDelete).toBeTruthy();
|
expect(!found || found.markedDelete).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('updateVehicle_put', () => {
|
||||||
|
let vehicleId;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const doc = await Vehicle.create(mockVehicle(applicator._id));
|
||||||
|
vehicleId = String(doc._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates a vehicle field', async () => {
|
||||||
|
const req = makeReq({
|
||||||
|
params: { id: vehicleId },
|
||||||
|
body: { name: 'Updated Aircraft Name', kind: '9' },
|
||||||
|
});
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await vehicleCtl.updateVehicle_put(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data.name).toBe('Updated Aircraft Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when id is invalid', async () => {
|
||||||
|
const req = makeReq({ params: {}, body: { name: 'X', kind: '9' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(vehicleCtl.updateVehicle_put(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
describe('unitIdExists_post', () => {
|
||||||
|
let vehicleWithUnit;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
vehicleWithUnit = await Vehicle.create(
|
||||||
|
mockVehicle(applicator._id, { unitId: 'UNIT001' })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 1 when unitId exists', async () => {
|
||||||
|
const req = makeReq({ body: { unitId: vehicleWithUnit.unitId } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await vehicleCtl.unitIdExists_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 0 when unitId does not exist', async () => {
|
||||||
|
const req = makeReq({ body: { unitId: 'NOTEXIST001' } });
|
||||||
|
const res = mockRes();
|
||||||
|
|
||||||
|
await vehicleCtl.unitIdExists_post(req, res);
|
||||||
|
|
||||||
|
expect(res.json).toHaveBeenCalled();
|
||||||
|
expect(res._data).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when unitId is blank', async () => {
|
||||||
|
const req = makeReq({ body: { unitId: '' } });
|
||||||
|
const res = mockRes();
|
||||||
|
await expect(vehicleCtl.unitIdExists_post(req, res)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user