diff --git a/README.md b/README.md index b33bd0c..9136fcc 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ The following parameters can be set in config files or in env variables: - `esConfig.ES_INDEX_JOB`: the index name for job - `esConfig.ES_INDEX_JOB_CANDIDATE`: the index name for job candidate - `esConfig.ES_INDEX_RESOURCE_BOOKING`: the index name for resource booking -- `esConfig.ES_INDEX_WORK_PERIOD`: the index name for work period - `auth0.AUTH0_URL`: Auth0 URL, used to get TC M2M token - `auth0.AUTH0_AUDIENCE`: Auth0 audience, used to get TC M2M token diff --git a/config/default.js b/config/default.js index 5476e65..1ea7851 100644 --- a/config/default.js +++ b/config/default.js @@ -54,8 +54,7 @@ module.exports = { ES_INDEX_JOB: process.env.ES_INDEX_JOB || 'job', ES_INDEX_JOB_CANDIDATE: process.env.ES_INDEX_JOB_CANDIDATE || 'job_candidate', - ES_INDEX_RESOURCE_BOOKING: process.env.ES_INDEX_RESOURCE_BOOKING || 'resource_booking', - ES_INDEX_WORK_PERIOD: process.env.ES_INDEX_WORK_PERIOD || 'work_period' + ES_INDEX_RESOURCE_BOOKING: process.env.ES_INDEX_RESOURCE_BOOKING || 'resource_booking' }, auth0: { diff --git a/package-lock.json b/package-lock.json index 6a4fb26..8db26cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -216,6 +216,12 @@ } } }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -251,6 +257,15 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -350,6 +365,12 @@ "@types/node": "*" } }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -407,6 +428,43 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", @@ -639,6 +697,111 @@ "type-is": "~1.6.17" } }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -699,6 +862,38 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, "caching-transform": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", @@ -772,12 +967,24 @@ "readdirp": "~3.2.0" } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz", @@ -821,6 +1028,23 @@ } } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -925,6 +1149,49 @@ "json5": "^1.0.1" } }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, "connection-parse": { "version": "0.0.7", "resolved": "https://registry.npm.taobao.org/connection-parse/download/connection-parse-0.0.7.tgz", @@ -1062,6 +1329,12 @@ "which": "^1.2.9" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1105,6 +1378,12 @@ "mimic-response": "^2.0.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz", @@ -1120,6 +1399,12 @@ "strip-bom": "^3.0.0" } }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1191,6 +1476,15 @@ "esutils": "^2.0.2" } }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, "dtrace-provider": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", @@ -1200,6 +1494,12 @@ "nan": "^2.14.0" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1302,6 +1602,12 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", @@ -2109,12 +2415,57 @@ "is-glob": "^4.0.1" } }, + "global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "requires": { + "ini": "1.3.7" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", @@ -2189,6 +2540,12 @@ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, "hasha": { "version": "3.0.0", "resolved": "https://registry.npm.taobao.org/hasha/download/hasha-3.0.0.tgz", @@ -2225,6 +2582,12 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -2305,6 +2668,18 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz", @@ -2325,6 +2700,12 @@ "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, "inquirer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", @@ -2429,6 +2810,15 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", @@ -2456,12 +2846,40 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -2502,6 +2920,12 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", @@ -2649,6 +3073,12 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2774,6 +3204,15 @@ "safe-buffer": "^5.0.1" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, "kuler": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", @@ -2782,6 +3221,15 @@ "colornames": "^1.1.1" } }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -2959,6 +3407,12 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -3441,6 +3895,59 @@ "semver": "^5.7.0" } }, + "nodemon": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", + "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==", + "dev": true, + "requires": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.3", + "update-notifier": "^4.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3459,6 +3966,12 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -3688,6 +4201,12 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -3742,6 +4261,26 @@ "release-zalgo": "^1.0.0" } }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz?cache=0&sync_timestamp=1598129684464&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-4.0.0.tgz", @@ -3917,6 +4456,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -3974,6 +4519,12 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -3988,6 +4539,15 @@ "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -4039,6 +4599,18 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", @@ -4099,6 +4671,24 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npm.taobao.org/release-zalgo/download/release-zalgo-1.0.0.tgz", @@ -4197,6 +4787,15 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz", @@ -4271,6 +4870,23 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -5003,6 +5619,12 @@ "request": "^2.88.0" } }, + "term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -5047,6 +5669,12 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5069,6 +5697,15 @@ "express": "^4.16.3" } }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -5129,6 +5766,12 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -5138,17 +5781,116 @@ "mime-types": "~2.1.24" } }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "dev": true, + "requires": { + "debug": "^2.2.0" + } + }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz", "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -5173,6 +5915,15 @@ "querystring": "0.2.0" } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", @@ -5237,6 +5988,55 @@ "string-width": "^1.0.2 || 2" } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "winston": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", @@ -5351,6 +6151,12 @@ "lodash": "^4.17.11" } }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", diff --git a/package.json b/package.json index 73f7cc9..f857c4e 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "src/app.js", "scripts": { "start": "node src/app.js", + "dev": "nodemon src/app.js", "lint": "standard", "lint:fix": "standard --fix", "create-index": "node src/scripts/createIndex.js", @@ -22,6 +23,7 @@ "mocha": "^7.1.2", "mocha-prepare": "^0.1.0", "nock": "^12.0.3", + "nodemon": "^2.0.7", "nyc": "^14.1.1", "should": "^13.2.3", "sinon": "^10.0.1", @@ -58,4 +60,4 @@ "test/e2e/*.js" ] } -} +} \ No newline at end of file diff --git a/src/scripts/createIndex.js b/src/scripts/createIndex.js index dc0d213..1d6d6b1 100644 --- a/src/scripts/createIndex.js +++ b/src/scripts/createIndex.js @@ -87,37 +87,35 @@ async function createIndex () { customerRate: { type: 'float' }, rateType: { type: 'keyword' }, billingAccountId: { type: 'integer' }, - createdAt: { type: 'date' }, - createdBy: { type: 'keyword' }, - updatedAt: { type: 'date' }, - updatedBy: { type: 'keyword' } - } - } - } - }, - { - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - body: { - mappings: { - properties: { - resourceBookingId: { type: 'keyword' }, - userHandle: { type: 'keyword' }, - projectId: { type: 'integer' }, - userId: { type: 'keyword' }, - startDate: { type: 'date', format: 'yyyy-MM-dd' }, - endDate: { type: 'date', format: 'yyyy-MM-dd' }, - daysWorked: { type: 'integer' }, - memberRate: { type: 'float' }, - customerRate: { type: 'float' }, - paymentStatus: { type: 'keyword' }, - payments: { + workPeriods: { type: 'nested', properties: { - workPeriodId: { type: 'keyword' }, - challengeId: { type: 'keyword' }, - amount: { type: 'float' }, - status: { type: 'keyword' }, - billingAccountId: { type: 'integer' }, + id: { type: 'keyword' }, + resourceBookingId: { type: 'keyword' }, + userHandle: { type: 'keyword' }, + projectId: { type: 'integer' }, + userId: { type: 'keyword' }, + startDate: { type: 'date', format: 'yyyy-MM-dd' }, + endDate: { type: 'date', format: 'yyyy-MM-dd' }, + daysWorked: { type: 'integer' }, + memberRate: { type: 'float' }, + customerRate: { type: 'float' }, + paymentStatus: { type: 'keyword' }, + payments: { + type: 'nested', + properties: { + id: { type: 'keyword' }, + workPeriodId: { type: 'keyword' }, + challengeId: { type: 'keyword' }, + amount: { type: 'float' }, + status: { type: 'keyword' }, + billingAccountId: { type: 'integer' }, + createdAt: { type: 'date' }, + createdBy: { type: 'keyword' }, + updatedAt: { type: 'date' }, + updatedBy: { type: 'keyword' } + } + }, createdAt: { type: 'date' }, createdBy: { type: 'keyword' }, updatedAt: { type: 'date' }, @@ -131,7 +129,8 @@ async function createIndex () { } } } - }] + } + ] for (const index of indices) { await esClient.indices.create(index) diff --git a/src/scripts/deleteIndex.js b/src/scripts/deleteIndex.js index 69594b4..9c3a1bb 100644 --- a/src/scripts/deleteIndex.js +++ b/src/scripts/deleteIndex.js @@ -11,8 +11,7 @@ async function deleteIndex () { const esClient = helper.getESClient() const indices = [config.get('esConfig.ES_INDEX_JOB'), config.get('esConfig.ES_INDEX_JOB_CANDIDATE'), - config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), - config.get('esConfig.ES_INDEX_WORK_PERIOD')] + config.get('esConfig.ES_INDEX_RESOURCE_BOOKING')] for (const index of indices) { await esClient.indices.delete({ index diff --git a/src/scripts/view-data.js b/src/scripts/view-data.js index 9c3d0ce..1db36d5 100644 --- a/src/scripts/view-data.js +++ b/src/scripts/view-data.js @@ -11,8 +11,7 @@ const esClient = helper.getESClient() const modelIndexMapping = { Job: 'ES_INDEX_JOB', JobCandidate: 'ES_INDEX_JOB_CANDIDATE', - ResourceBooking: 'ES_INDEX_RESOURCE_BOOKING', - WorkPeriod: 'ES_INDEX_WORK_PERIOD' + ResourceBooking: 'ES_INDEX_RESOURCE_BOOKING' } async function showESData () { diff --git a/src/services/JobCandidateProcessorService.js b/src/services/JobCandidateProcessorService.js index 051af9a..48d8660 100644 --- a/src/services/JobCandidateProcessorService.js +++ b/src/services/JobCandidateProcessorService.js @@ -25,8 +25,8 @@ async function updateCandidateStatus ({ type, payload, previousData }) { localLogger.debug({ context: 'updateCandidateStatus', message: `jobCandidate is already in status: ${payload.status}` }) return } - //if (!['rejected', 'shortlist',].includes(payload.status)) { - if (!['client rejected - screening', 'client rejected - interview','interview','selected'].includes(payload.status)) { + // if (!['rejected', 'shortlist',].includes(payload.status)) { + if (!['client rejected - screening', 'client rejected - interview', 'interview', 'selected'].includes(payload.status)) { localLogger.debug({ context: 'updateCandidateStatus', message: `not interested status: ${payload.status}` }) return } diff --git a/src/services/WorkPeriodPaymentProcessorService.js b/src/services/WorkPeriodPaymentProcessorService.js index d336379..7f30b6e 100644 --- a/src/services/WorkPeriodPaymentProcessorService.js +++ b/src/services/WorkPeriodPaymentProcessorService.js @@ -18,19 +18,39 @@ const esClient = helper.getESClient() */ async function processCreate (message, transactionId) { const data = message.payload - const workPeriod = await esClient.getExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.workPeriodId + // find related resourceBooking + const result = await esClient.search({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + body: { + query: { + nested: { + path: 'workPeriods', + query: { + match: { 'workPeriods.id': data.workPeriodId } + } + } + } + } }) - const payments = _.isArray(workPeriod.body.payments) ? workPeriod.body.payments : [] + if (!result.body.hits.total.value) { + throw new Error(`id: ${data.workPeriodId} "WorkPeriod" not found`) + } + const resourceBooking = result.body.hits.hits[0]._source + // find related workPeriod record + const workPeriod = _.find(resourceBooking.workPeriods, ['id', data.workPeriodId]) + // Get workPeriod's existing payments + const payments = _.isArray(workPeriod.payments) ? workPeriod.payments : [] + // Append new payment payments.push(data) - - return esClient.updateExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.workPeriodId, + // Assign new payments array to workPeriod + workPeriod.payments = payments + // Update ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: resourceBooking.id, transactionId, body: { - doc: _.assign(workPeriod.body, { payments }) + doc: { workPeriods: resourceBooking.workPeriods } }, refresh: constants.esRefreshOption }) @@ -65,64 +85,103 @@ processCreate.schema = { */ async function processUpdate (message, transactionId) { const data = message.payload - let workPeriod = await esClient.search({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), + // find workPeriodPayment in it's parent ResourceBooking + let result = await esClient.search({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), body: { query: { nested: { - path: 'payments', + path: 'workPeriods.payments', query: { - match: { 'payments.id': data.id } + match: { 'workPeriods.payments.id': data.id } } } } } }) - if (!workPeriod.body.hits.total.value) { - throw new Error(`id: ${data.id} "WorkPeriodPayments" not found`) + if (!result.body.hits.total.value) { + throw new Error(`id: ${data.id} "WorkPeriodPayment" not found`) } + const resourceBooking = _.cloneDeep(result.body.hits.hits[0]._source) + let workPeriod = null + let payment = null + let paymentIndex = null + // find workPeriod and workPeriodPayment records + _.forEach(resourceBooking.workPeriods, wp => { + _.forEach(wp.payments, (p, pi) => { + if (p.id === data.id) { + payment = p + paymentIndex = pi + return false + } + }) + if (payment) { + workPeriod = wp + return false + } + }) let payments // if WorkPeriodPayment's workPeriodId changed then it must be deleted from the old WorkPeriod // and added to the new WorkPeriod - if (workPeriod.body.hits.hits[0]._source.id !== data.workPeriodId) { - payments = _.filter(workPeriod.body.hits.hits[0]._source.payments, (payment) => payment.id !== data.id) + if (payment.workPeriodId !== data.workPeriodId) { + // remove payment from payments + payments = _.filter(workPeriod.payments, p => p.id !== data.id) + // assign payments to workPeriod record + workPeriod.payments = payments + // Update old ResourceBooking's workPeriods property await esClient.updateExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: workPeriod.body.hits.hits[0]._source.id, + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: resourceBooking.id, transactionId, body: { - doc: _.assign(workPeriod.body.hits.hits[0]._source, { payments }) - } + doc: { workPeriods: resourceBooking.workPeriods } + }, + refresh: constants.esRefreshOption }) - workPeriod = await esClient.getExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.workPeriodId + // find workPeriodPayment's new parent WorkPeriod + result = await esClient.search({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + body: { + query: { + nested: { + path: 'workPeriods', + query: { + match: { 'workPeriods.id': data.workPeriodId } + } + } + } + } }) - payments = _.isArray(workPeriod.body.payments) ? workPeriod.body.payments : [] - payments.push(data) - return esClient.updateExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.workPeriodId, + const newResourceBooking = result.body.hits.hits[0]._source + // find WorkPeriod record in ResourceBooking + const newWorkPeriod = _.find(newResourceBooking.workPeriods, ['id', data.workPeriodId]) + // Get WorkPeriod's existing payments + const newPayments = _.isArray(newWorkPeriod.payments) ? newWorkPeriod.payments : [] + // Append new payment + newPayments.push(data) + // Assign new payments array to workPeriod + newWorkPeriod.payments = newPayments + // Update new ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: newResourceBooking.id, transactionId, body: { - doc: _.assign(workPeriod.body, { payments }) - } + doc: { workPeriods: newResourceBooking.workPeriods } + }, + refresh: constants.esRefreshOption }) + return } - - payments = _.map(workPeriod.body.hits.hits[0]._source.payments, (payment) => { - if (payment.id === data.id) { - return _.assign(payment, data) - } - return payment - }) - - return esClient.updateExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.workPeriodId, + // update payment record + workPeriod.payments[paymentIndex] = data + // Update ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: resourceBooking.id, transactionId, body: { - doc: _.assign(workPeriod.body.hits.hits[0]._source, { payments }) + doc: { workPeriods: resourceBooking.workPeriods } }, refresh: constants.esRefreshOption }) diff --git a/src/services/WorkPeriodProcessorService.js b/src/services/WorkPeriodProcessorService.js index 568c746..59b8d4b 100644 --- a/src/services/WorkPeriodProcessorService.js +++ b/src/services/WorkPeriodProcessorService.js @@ -7,7 +7,7 @@ const logger = require('../common/logger') const helper = require('../common/helper') const constants = require('../common/constants') const config = require('config') - +const _ = require('lodash') const esClient = helper.getESClient() /** @@ -17,11 +17,23 @@ const esClient = helper.getESClient() */ async function processCreate (message, transactionId) { const workPeriod = message.payload - await esClient.createExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: workPeriod.id, + // Find related resourceBooking + const resourceBooking = await esClient.getExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: workPeriod.resourceBookingId + }) + // Get ResourceBooking's existing workPeriods + const workPeriods = _.isArray(resourceBooking.body.workPeriods) ? resourceBooking.body.workPeriods : [] + // Append new workPeriod + workPeriods.push(workPeriod) + // Update ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: workPeriod.resourceBookingId, transactionId, - body: workPeriod, + body: { + doc: { workPeriods } + }, refresh: constants.esRefreshOption }) } @@ -59,12 +71,78 @@ processCreate.schema = { */ async function processUpdate (message, transactionId) { const data = message.payload + // find workPeriod in it's parent ResourceBooking + let resourceBooking = await esClient.search({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + body: { + query: { + nested: { + path: 'workPeriods', + query: { + match: { 'workPeriods.id': data.id } + } + } + } + } + }) + if (!resourceBooking.body.hits.total.value) { + throw new Error(`id: ${data.id} "WorkPeriod" not found`) + } + let workPeriods + // if WorkPeriod's resourceBookingId changed then it must be deleted from the old ResourceBooking + // and added to the new ResourceBooking + if (resourceBooking.body.hits.hits[0]._source.id !== data.resourceBookingId) { + // find old workPeriod record, so we can keep it's existing nested payments field + let oldWorkPeriod = _.find(resourceBooking.body.hits.hits[0]._source.workPeriods, ['id', data.id]) + // remove workPeriod from it's old parent + workPeriods = _.filter(resourceBooking.body.hits.hits[0]._source.workPeriods, (workPeriod) => workPeriod.id !== data.id) + // Update old ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: resourceBooking.body.hits.hits[0]._source.id, + transactionId, + body: { + doc: { workPeriods } + }, + refresh: constants.esRefreshOption + }) + // find workPeriod's new parent ResourceBooking + resourceBooking = await esClient.getExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: data.resourceBookingId + }) + // Get ResourceBooking's existing workPeriods + workPeriods = _.isArray(resourceBooking.body.workPeriods) ? resourceBooking.body.workPeriods : [] + // Update workPeriod record + const newData = _.assign(oldWorkPeriod, data) + // Append updated workPeriod to workPeriods + workPeriods.push(newData) + // Update new ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: data.resourceBookingId, + transactionId, + body: { + doc: { workPeriods } + }, + refresh: constants.esRefreshOption + }) + return + } + // Update workPeriod record + workPeriods = _.map(resourceBooking.body.hits.hits[0]._source.workPeriods, (workPeriod) => { + if (workPeriod.id === data.id) { + return _.assign(workPeriod, data) + } + return workPeriod + }) + // Update ResourceBooking's workPeriods property await esClient.updateExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id: data.id, + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: data.resourceBookingId, transactionId, body: { - doc: data + doc: { workPeriods } }, refresh: constants.esRefreshOption }) @@ -78,11 +156,34 @@ processUpdate.schema = processCreate.schema * @param {String} transactionId */ async function processDelete (message, transactionId) { - const id = message.payload.id - await esClient.deleteExtra({ - index: config.get('esConfig.ES_INDEX_WORK_PERIOD'), - id, + const data = message.payload + // Find related ResourceBooking + const resourceBooking = await esClient.search({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + body: { + query: { + nested: { + path: 'workPeriods', + query: { + match: { 'workPeriods.id': data.id } + } + } + } + } + }) + if (!resourceBooking.body.hits.total.value) { + throw new Error(`id: ${data.id} "WorkPeriod" not found`) + } + // Remove workPeriod from workPeriods + const workPeriods = _.filter(resourceBooking.body.hits.hits[0]._source.workPeriods, (workPeriod) => workPeriod.id !== data.id) + // Update ResourceBooking's workPeriods property + await esClient.updateExtra({ + index: config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'), + id: resourceBooking.body.hits.hits[0]._source.id, transactionId, + body: { + doc: { workPeriods } + }, refresh: constants.esRefreshOption }) } diff --git a/test/common/testData.js b/test/common/testData.js index 7e18dde..e583618 100644 --- a/test/common/testData.js +++ b/test/common/testData.js @@ -17,6 +17,15 @@ const messages = { update: { topic: 'taas.resourcebooking.update', message: require('../messages/taas.resourcebooking.update.event.json') }, delete: { topic: 'taas.resourcebooking.delete', message: require('../messages/taas.resourcebooking.delete.event.json') } }, + WorkPeriod: { + create: { topic: 'taas.workperiod.create', message: require('../messages/taas.workperiod.create.event.json') }, + update: { topic: 'taas.workperiod.update', message: require('../messages/taas.workperiod.update.event.json') }, + delete: { topic: 'taas.workperiod.delete', message: require('../messages/taas.workperiod.delete.event.json') } + }, + WorkPeriodPayment: { + create: { topic: 'taas.workperiodpayment.create', message: require('../messages/taas.workperiodpayment.create.event.json') }, + update: { topic: 'taas.workperiodpayment.update', message: require('../messages/taas.workperiodpayment.update.event.json') } + }, messageInvalid: '{ "topic": "taas.job.create", }' } diff --git a/test/e2e/test.js b/test/e2e/test.js index 1e09ccc..020b060 100644 --- a/test/e2e/test.js +++ b/test/e2e/test.js @@ -10,6 +10,7 @@ const should = require('should') const logger = require('../../src/common/logger') const testData = require('../common/testData') const testHelper = require('../common/testHelper') +const _ = require('lodash') describe('Taas ES Processor E2E Test', () => { let infoLogs = [] @@ -54,102 +55,233 @@ describe('Taas ES Processor E2E Test', () => { errorLogs = [] await testHelper.clearES() }) + describe('General Logic Tests', () => { + it('Should setup healthcheck with check on kafka connection', async () => { + const healthcheckEndpoint = `http://localhost:${config.PORT}/health` + const result = await request.get(healthcheckEndpoint) + should.equal(result.status, 200) + should.deepEqual(result.body, { checksRun: 1 }) + }) - it('Should setup healthcheck with check on kafka connection', async () => { - const healthcheckEndpoint = `http://localhost:${config.PORT}/health` - const result = await request.get(healthcheckEndpoint) - should.equal(result.status, 200) - should.deepEqual(result.body, { checksRun: 1 }) - }) + it('Should handle invalid json message', async () => { + await testHelper.sendMessage(testData.messages.messageInvalid, config.topics.TAAS_JOB_CREATE_TOPIC) + await waitForMessageHandled() + errorLogs[0].should.match(/Invalid message JSON/) + }) - it('Should handle invalid json message', async () => { - await testHelper.sendMessage(testData.messages.messageInvalid, config.topics.TAAS_JOB_CREATE_TOPIC) - await waitForMessageHandled() - errorLogs[0].should.match(/Invalid message JSON/) + it('Should handle incorrect topic field message', async () => { + await testHelper.sendMessage(testData.messages.Job.create.message, config.topics.TAAS_JOB_UPDATE_TOPIC) + await waitForMessageHandled() + should.equal(errorLogs[0], `The message topic ${testData.messages.Job.create.topic} doesn't match the Kafka topic ${config.topics.TAAS_JOB_UPDATE_TOPIC}.`) + }) }) + describe('Job, JobCandidate, ResourceBooking tests', () => { + for (const [index, model] of [ + [config.esConfig.ES_INDEX_JOB, 'Job'], + [config.esConfig.ES_INDEX_JOB_CANDIDATE, 'JobCandidate'], + [config.esConfig.ES_INDEX_RESOURCE_BOOKING, 'ResourceBooking'] + ]) { + const modelInSpaceCase = stringcase.spacecase(model) - it('Should handle incorrect topic field message', async () => { - await testHelper.sendMessage(testData.messages.Job.create.message, config.topics.TAAS_JOB_UPDATE_TOPIC) - await waitForMessageHandled() - should.equal(errorLogs[0], `The message topic ${testData.messages.Job.create.topic} doesn't match the Kafka topic ${config.topics.TAAS_JOB_UPDATE_TOPIC}.`) - }) + it(`Should handle ${modelInSpaceCase} creation message`, async () => { + await testHelper.sendMessage(testData.messages[model].create.message) + await waitForMessageHandled() + const doc = await testHelper.esClient.get({ + index, + id: testData.messages[model].create.message.payload.id + }) + should.deepEqual(doc.body._source, testData.messages[model].create.message.payload, ['id']) + }) + + it(`Should handle ${modelInSpaceCase} updating message`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + await testHelper.sendMessage(testData.messages[model].update.message) + await waitForMessageHandled() + const doc = await testHelper.esClient.get({ + index, + id: testData.messages[model].update.message.payload.id + }) + should.deepEqual(doc.body._source, testData.messages[model].update.message.payload) + }) + + it(`Should handle ${modelInSpaceCase} deletion message`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + await testHelper.sendMessage(testData.messages[model].delete.message) + await waitForMessageHandled() + const doc = await testHelper.esClient.get({ + index, + id: testData.messages[model].delete.message.payload.id + }).catch(err => { + if (err.statusCode === 404) { + return + } + throw err + }) + should.not.exist(doc) + }) + + it(`Failure - creation message - ${modelInSpaceCase} already exists`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + await testHelper.sendMessage(testData.messages[model].create.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].create.message.payload.id} "${index}" already exists`) + }) + + it(`Failure - updating message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].update.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].update.message.payload.id} "${index}" not found`) + }) - for (const [index, model] of [ - [config.esConfig.ES_INDEX_JOB, 'Job'], - [config.esConfig.ES_INDEX_JOB_CANDIDATE, 'JobCandidate'], - [config.esConfig.ES_INDEX_RESOURCE_BOOKING, 'ResourceBooking'] - ]) { + it(`Failure - deletion message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].delete.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].delete.message.payload.id} "${index}" not found`) + }) + } + }) + describe('Nested WorkPeriod tests', () => { + const index = config.esConfig.ES_INDEX_RESOURCE_BOOKING + const model = 'WorkPeriod' + const parentModel = 'ResourceBooking' + const nestedName = 'workPeriods' const modelInSpaceCase = stringcase.spacecase(model) it(`Should handle ${modelInSpaceCase} creation message`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[parentModel].create.message.payload.id, + body: testData.messages[parentModel].create.message.payload, + refresh: 'true' + }) await testHelper.sendMessage(testData.messages[model].create.message) await waitForMessageHandled() const doc = await testHelper.esClient.get({ index, - id: testData.messages[model].create.message.payload.id + id: testData.messages[parentModel].create.message.payload.id }) - should.deepEqual(doc.body._source, testData.messages[model].create.message.payload, ['id']) + should.deepEqual(doc.body._source, + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] })) }) it(`Should handle ${modelInSpaceCase} updating message`, async () => { await testHelper.esClient.create({ index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, + id: testData.messages[parentModel].create.message.payload.id, + body: _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] }), refresh: 'true' }) await testHelper.sendMessage(testData.messages[model].update.message) await waitForMessageHandled() const doc = await testHelper.esClient.get({ index, - id: testData.messages[model].update.message.payload.id + id: testData.messages[parentModel].create.message.payload.id }) - should.deepEqual(doc.body._source, testData.messages[model].update.message.payload) + should.deepEqual(doc.body._source, + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].update.message.payload] })) }) it(`Should handle ${modelInSpaceCase} deletion message`, async () => { await testHelper.esClient.create({ index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, + id: testData.messages[parentModel].create.message.payload.id, + body: _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] }), refresh: 'true' }) await testHelper.sendMessage(testData.messages[model].delete.message) await waitForMessageHandled() const doc = await testHelper.esClient.get({ index, - id: testData.messages[model].delete.message.payload.id - }).catch(err => { - if (err.statusCode === 404) { - return - } - throw err - }) - should.not.exist(doc) + id: testData.messages[parentModel].create.message.payload.id + }) + should.deepEqual(doc.body._source, + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [] })) + }) + + it(`Failure - creation message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].create.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[parentModel].create.message.payload.id} "${index}" not found`) + }) + + it(`Failure - updating message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].update.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].update.message.payload.id} "${model}" not found`) + }) + + it(`Failure - deletion message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].delete.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].delete.message.payload.id} "${model}" not found`) }) + }) + describe('Nested WorkPeriodPayment tests', () => { + const index = config.esConfig.ES_INDEX_RESOURCE_BOOKING + const model = 'WorkPeriodPayment' + const parentModel = 'WorkPeriod' + const rootModel = 'ResourceBooking' + const nestedName = 'payments' + const parentNestedName = 'workPeriods' + const modelInSpaceCase = stringcase.spacecase(model) - it(`Failure - creation message - ${modelInSpaceCase} already exists`, async () => { + it(`Should handle ${modelInSpaceCase} creation message`, async () => { await testHelper.esClient.create({ index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, + id: testData.messages[rootModel].create.message.payload.id, + body: _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [testData.messages[parentModel].create.message.payload] }), refresh: 'true' }) await testHelper.sendMessage(testData.messages[model].create.message) await waitForMessageHandled() - should.equal(errorLogs[0], `id: ${testData.messages[model].create.message.payload.id} "${index}" already exists`) + const doc = await testHelper.esClient.get({ + index, + id: testData.messages[rootModel].create.message.payload.id + }) + should.deepEqual(doc.body._source, _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] })] })) }) - it(`Failure - updating message - ${modelInSpaceCase} not found`, async () => { + it(`Should handle ${modelInSpaceCase} updating message`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[rootModel].create.message.payload.id, + body: _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] })] }), + refresh: 'true' + }) await testHelper.sendMessage(testData.messages[model].update.message) await waitForMessageHandled() - should.equal(errorLogs[0], `id: ${testData.messages[model].update.message.payload.id} "${index}" not found`) + const doc = await testHelper.esClient.get({ + index, + id: testData.messages[rootModel].create.message.payload.id + }) + should.deepEqual(doc.body._source, _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].update.message.payload] })] })) }) - it(`Failure - deletion message - ${modelInSpaceCase} not found`, async () => { - await testHelper.sendMessage(testData.messages[model].delete.message) + it(`Failure - creation message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].create.message) await waitForMessageHandled() - should.equal(errorLogs[0], `id: ${testData.messages[model].delete.message.payload.id} "${index}" not found`) + should.equal(errorLogs[0], `id: ${testData.messages[parentModel].create.message.payload.id} "${parentModel}" not found`) }) - } + + it(`Failure - updating message - ${modelInSpaceCase} not found`, async () => { + await testHelper.sendMessage(testData.messages[model].update.message) + await waitForMessageHandled() + should.equal(errorLogs[0], `id: ${testData.messages[model].update.message.payload.id} "${model}" not found`) + }) + }) }) diff --git a/test/messages/taas.job.create.event.json b/test/messages/taas.job.create.event.json index e2b12bb..ebc5d15 100644 --- a/test/messages/taas.job.create.event.json +++ b/test/messages/taas.job.create.event.json @@ -1 +1,29 @@ -{"topic":"taas.job.create","originator":"taas-api","timestamp":"2020-11-05T19:00:17.563Z","mime-type":"application/json","payload":{"title":"Job Title","projectId":21,"externalId":"1212","description":"Dummy Description","startDate":"2020-09-27T04:17:23.131Z","duration":17,"numPositions":13,"resourceType":"Dummy Resource Type","rateType":"hourly","skills":["56fdc405-eccc-4189-9e83-c78abf844f50","f91ae184-aba2-4485-a8cb-9336988c05ab","edfc7b4f-636f-44bd-96fc-949ffc58e38b","4ca63bb6-f515-4ab0-a6bc-c2d8531e084f","ee03c041-d53b-4c08-b7d9-80d7461da3e4"],"id":"ffbc24f7-301e-48d3-bf01-c056916056a2","createdAt":"2020-11-05T19:00:16.268Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","status":"sourcing","isApplicationPageActive":false}} \ No newline at end of file +{ + "topic": "taas.job.create", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:17.563Z", + "mime-type": "application/json", + "payload": { + "title": "Job Title", + "projectId": 21, + "externalId": "1212", + "description": "Dummy Description", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 17, + "numPositions": 13, + "resourceType": "Dummy Resource Type", + "rateType": "hourly", + "skills": [ + "56fdc405-eccc-4189-9e83-c78abf844f50", + "f91ae184-aba2-4485-a8cb-9336988c05ab", + "edfc7b4f-636f-44bd-96fc-949ffc58e38b", + "4ca63bb6-f515-4ab0-a6bc-c2d8531e084f", + "ee03c041-d53b-4c08-b7d9-80d7461da3e4" + ], + "id": "ffbc24f7-301e-48d3-bf01-c056916056a2", + "createdAt": "2020-11-05T19:00:16.268Z", + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "sourcing", + "isApplicationPageActive": false + } +} \ No newline at end of file diff --git a/test/messages/taas.job.delete.event.json b/test/messages/taas.job.delete.event.json index 00ddbe9..9ad9844 100644 --- a/test/messages/taas.job.delete.event.json +++ b/test/messages/taas.job.delete.event.json @@ -1 +1,9 @@ -{"topic":"taas.job.delete","originator":"taas-api","timestamp":"2020-11-05T19:00:19.035Z","mime-type":"application/json","payload":{"id":"ffbc24f7-301e-48d3-bf01-c056916056a2"}} \ No newline at end of file +{ + "topic": "taas.job.delete", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:19.035Z", + "mime-type": "application/json", + "payload": { + "id": "ffbc24f7-301e-48d3-bf01-c056916056a2" + } +} \ No newline at end of file diff --git a/test/messages/taas.job.update.event.json b/test/messages/taas.job.update.event.json index fced890..3be8597 100644 --- a/test/messages/taas.job.update.event.json +++ b/test/messages/taas.job.update.event.json @@ -1 +1,28 @@ -{"topic":"taas.job.update","originator":"taas-api","timestamp":"2020-11-05T19:00:19.015Z","mime-type":"application/json","payload":{"id":"ffbc24f7-301e-48d3-bf01-c056916056a2","title":"Job Title Updated","projectId":21,"externalId":"1212","description":"Dummy Description","startDate":"2020-09-27T04:17:23.131Z","duration":19,"numPositions":13,"resourceType":"Dummy Resource Type","rateType":"hourly","skills":["3fa85f64-5717-4562-b3fc-2c963f66afa6","cc41ddc4-cacc-4570-9bdb-1229c12b9784"],"status":"sourcing","updatedAt":"2020-11-05T19:00:17.612Z","updatedBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","createdAt":"2020-11-05T19:00:16.268Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","isApplicationPageActive":false}} \ No newline at end of file +{ + "topic": "taas.job.update", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:19.015Z", + "mime-type": "application/json", + "payload": { + "id": "ffbc24f7-301e-48d3-bf01-c056916056a2", + "title": "Job Title Updated", + "projectId": 21, + "externalId": "1212", + "description": "Dummy Description", + "startDate": "2020-09-27T04:17:23.131Z", + "duration": 19, + "numPositions": 13, + "resourceType": "Dummy Resource Type", + "rateType": "hourly", + "skills": [ + "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "cc41ddc4-cacc-4570-9bdb-1229c12b9784" + ], + "status": "sourcing", + "updatedAt": "2020-11-05T19:00:17.612Z", + "updatedBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "createdAt": "2020-11-05T19:00:16.268Z", + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "isApplicationPageActive": false + } +} \ No newline at end of file diff --git a/test/messages/taas.jobcandidate.create.event.json b/test/messages/taas.jobcandidate.create.event.json index 18cabc3..822dc80 100644 --- a/test/messages/taas.jobcandidate.create.event.json +++ b/test/messages/taas.jobcandidate.create.event.json @@ -1 +1,14 @@ -{"topic":"taas.jobcandidate.create","originator":"taas-api","timestamp":"2020-11-05T19:00:21.597Z","mime-type":"application/json","payload":{"jobId":"ffbc24f7-301e-48d3-bf01-c056916056a2","userId":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","id":"0cb99adb-8bcd-4952-9203-9867dd45ef6f","createdAt":"2020-11-05T19:00:19.052Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","status":"open"}} \ No newline at end of file +{ + "topic": "taas.jobcandidate.create", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:21.597Z", + "mime-type": "application/json", + "payload": { + "jobId": "ffbc24f7-301e-48d3-bf01-c056916056a2", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "id": "0cb99adb-8bcd-4952-9203-9867dd45ef6f", + "createdAt": "2020-11-05T19:00:19.052Z", + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "open" + } +} \ No newline at end of file diff --git a/test/messages/taas.jobcandidate.delete.event.json b/test/messages/taas.jobcandidate.delete.event.json index 714cce6..0aa13d5 100644 --- a/test/messages/taas.jobcandidate.delete.event.json +++ b/test/messages/taas.jobcandidate.delete.event.json @@ -1 +1,9 @@ -{"topic":"taas.jobcandidate.delete","originator":"taas-api","timestamp":"2020-11-05T19:00:23.021Z","mime-type":"application/json","payload":{"id":"0cb99adb-8bcd-4952-9203-9867dd45ef6f"}} \ No newline at end of file +{ + "topic": "taas.jobcandidate.delete", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:23.021Z", + "mime-type": "application/json", + "payload": { + "id": "0cb99adb-8bcd-4952-9203-9867dd45ef6f" + } +} \ No newline at end of file diff --git a/test/messages/taas.jobcandidate.update.event.json b/test/messages/taas.jobcandidate.update.event.json index 79530f9..1254087 100644 --- a/test/messages/taas.jobcandidate.update.event.json +++ b/test/messages/taas.jobcandidate.update.event.json @@ -1 +1,16 @@ -{"topic":"taas.jobcandidate.update","originator":"taas-api","timestamp":"2020-11-05T19:00:23.003Z","mime-type":"application/json","payload":{"id":"0cb99adb-8bcd-4952-9203-9867dd45ef6f","jobId":"ffbc24f7-301e-48d3-bf01-c056916056a2","userId":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","status":"selected","updatedAt":"2020-11-05T19:00:21.625Z","updatedBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","createdAt":"2020-11-05T19:00:16.268Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a"}} \ No newline at end of file +{ + "topic": "taas.jobcandidate.update", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:23.003Z", + "mime-type": "application/json", + "payload": { + "id": "0cb99adb-8bcd-4952-9203-9867dd45ef6f", + "jobId": "ffbc24f7-301e-48d3-bf01-c056916056a2", + "userId": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "status": "selected", + "updatedAt": "2020-11-05T19:00:21.625Z", + "updatedBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", + "createdAt": "2020-11-05T19:00:16.268Z", + "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a" + } +} \ No newline at end of file diff --git a/test/messages/taas.resourcebooking.create.event.json b/test/messages/taas.resourcebooking.create.event.json index 2f3de0a..2d7fd00 100644 --- a/test/messages/taas.resourcebooking.create.event.json +++ b/test/messages/taas.resourcebooking.create.event.json @@ -15,7 +15,7 @@ "id": "60d97713-8621-476e-b006-7cb9589c7777", "createdAt": "2020-11-05T19:00:23.036Z", "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", - "status": "assigned", + "status": "placed", "billingAccountId": 80000071 } -} +} \ No newline at end of file diff --git a/test/messages/taas.resourcebooking.delete.event.json b/test/messages/taas.resourcebooking.delete.event.json index 46a5e6f..644037e 100644 --- a/test/messages/taas.resourcebooking.delete.event.json +++ b/test/messages/taas.resourcebooking.delete.event.json @@ -1 +1,9 @@ -{"topic":"taas.resourcebooking.delete","originator":"taas-api","timestamp":"2020-11-05T19:00:26.433Z","mime-type":"application/json","payload":{"id":"60d97713-8621-476e-b006-7cb9589c7777"}} \ No newline at end of file +{ + "topic": "taas.resourcebooking.delete", + "originator": "taas-api", + "timestamp": "2020-11-05T19:00:26.433Z", + "mime-type": "application/json", + "payload": { + "id": "60d97713-8621-476e-b006-7cb9589c7777" + } +} \ No newline at end of file diff --git a/test/messages/taas.resourcebooking.update.event.json b/test/messages/taas.resourcebooking.update.event.json index 2b96229..036b6c6 100644 --- a/test/messages/taas.resourcebooking.update.event.json +++ b/test/messages/taas.resourcebooking.update.event.json @@ -13,11 +13,11 @@ "memberRate": 13.23, "customerRate": 13, "rateType": "hourly", - "status": "assigned", + "status": "placed", "billingAccountId": 80000071, "updatedAt": "2020-11-05T19:00:25.062Z", "updatedBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a", "createdAt": "2020-11-05T19:00:16.268Z", "createdBy": "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a" } -} +} \ No newline at end of file diff --git a/test/messages/taas.workperiod.create.event.json b/test/messages/taas.workperiod.create.event.json index 3c2d286..eb26743 100644 --- a/test/messages/taas.workperiod.create.event.json +++ b/test/messages/taas.workperiod.create.event.json @@ -4,7 +4,7 @@ "timestamp": "2021-03-30T20:24:17.555Z", "mime-type": "application/json", "payload": { - "resourceBookingId": "6cf2edf6-4b2c-40ef-96db-e1ddb771fdd3", + "resourceBookingId": "60d97713-8621-476e-b006-7cb9589c7777", "startDate": "2021-03-14", "endDate": "2021-03-20", "daysWorked": 3, @@ -14,10 +14,9 @@ "projectId": 111, "userHandle": "pshah_manager", "id": "926040c4-1709-4de2-b2b6-52adf6e5e72d", - "billingAccountId": 80000071 "createdBy": "00000000-0000-0000-0000-000000000000", "updatedAt": "2021-03-30T20:24:17.541Z", "createdAt": "2021-03-30T20:24:17.541Z", "updatedBy": null } -} +} \ No newline at end of file diff --git a/test/messages/taas.workperiod.update.event.json b/test/messages/taas.workperiod.update.event.json index 0e8ca71..e8798dd 100644 --- a/test/messages/taas.workperiod.update.event.json +++ b/test/messages/taas.workperiod.update.event.json @@ -4,18 +4,19 @@ "timestamp": "2021-03-30T20:13:53.179Z", "mime-type": "application/json", "payload": { - "id": "926040c4-1709-4de2-b2b6-52adf6e5e72d", - "resourceBookingId": "79317ff6-5b30-45c2-ace8-b97282b042a8", - "startDate": "2021-03-14", - "endDate": "2021-03-20", - "daysWorked": 3, + "resourceBookingId": "60d97713-8621-476e-b006-7cb9589c7777", + "startDate": "2021-03-21", + "endDate": "2021-03-28", + "daysWorked": 4, "memberRate": 13.13, "customerRate": 13.13, - "paymentStatus": "pending", + "paymentStatus": "cancelled", "projectId": 111, "userHandle": "pshah_manager", + "id": "926040c4-1709-4de2-b2b6-52adf6e5e72d", "createdBy": "00000000-0000-0000-0000-000000000000", - "createdAt": "2021-03-30T20:13:34.670Z", - "updatedAt": "2021-03-30T20:13:45.354Z" + "updatedAt": "2021-03-30T20:24:17.541Z", + "createdAt": "2021-03-30T20:24:17.541Z", + "updatedBy": "00000000-0000-0000-0000-000000000000" } } \ No newline at end of file diff --git a/test/messages/taas.workperiodpayment.create.event.json b/test/messages/taas.workperiodpayment.create.event.json index 25ab9cc..1ecbc84 100644 --- a/test/messages/taas.workperiodpayment.create.event.json +++ b/test/messages/taas.workperiodpayment.create.event.json @@ -1 +1,18 @@ -{"topic":"taas.workperiodpayment.create","originator":"taas-api","timestamp":"2021-04-09T20:10:33.770Z","mime-type":"application/json","payload":{"challengeId":"00000000-0000-0000-0000-000000000000","workPeriodId":"140b7407-540d-40c3-ad23-905d932aa9c8","amount":600,"status":"completed","id":"09c80ee6-21be-45a4-9c3c-7ec4c75ece79","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedAt":"2021-04-09T20:10:33.755Z","createdAt":"2021-04-09T20:10:33.755Z","updatedBy":null}} \ No newline at end of file +{ + "topic": "taas.workperiodpayment.create", + "originator": "taas-api", + "timestamp": "2021-04-09T20:10:33.770Z", + "mime-type": "application/json", + "payload": { + "challengeId": "00000000-0000-0000-0000-000000000000", + "workPeriodId": "926040c4-1709-4de2-b2b6-52adf6e5e72d", + "amount": 600, + "status": "completed", + "id": "09c80ee6-21be-45a4-9c3c-7ec4c75ece79", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedAt": "2021-04-09T20:10:33.755Z", + "createdAt": "2021-04-09T20:10:33.755Z", + "updatedBy": null + } +} \ No newline at end of file diff --git a/test/messages/taas.workperiodpayment.update.event.json b/test/messages/taas.workperiodpayment.update.event.json index 66e5bce..ea1e859 100644 --- a/test/messages/taas.workperiodpayment.update.event.json +++ b/test/messages/taas.workperiodpayment.update.event.json @@ -1 +1,18 @@ -{"topic":"taas.workperiodpayment.update","originator":"taas-api","timestamp":"2021-04-09T20:12:26.994Z","mime-type":"application/json","payload":{"id":"09c80ee6-21be-45a4-9c3c-7ec4c75ece79","workPeriodId":"140b7407-540d-40c3-ad23-905d932aa9c8","challengeId":"00000000-0000-0000-0000-000000000000","amount":1600,"status":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-04-09T20:10:33.755Z","updatedAt":"2021-04-09T20:12:26.966Z"}} \ No newline at end of file +{ + "topic": "taas.workperiodpayment.update", + "originator": "taas-api", + "timestamp": "2021-04-09T20:12:26.994Z", + "mime-type": "application/json", + "payload": { + "id": "09c80ee6-21be-45a4-9c3c-7ec4c75ece79", + "workPeriodId": "926040c4-1709-4de2-b2b6-52adf6e5e72d", + "challengeId": "00000000-0000-0000-0000-000000000000", + "amount": 1600, + "status": "completed", + "billingAccountId": 80000071, + "createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "updatedBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c", + "createdAt": "2021-04-09T20:10:33.755Z", + "updatedAt": "2021-04-09T20:12:26.966Z" + } +} \ No newline at end of file diff --git a/test/unit/prepare.js b/test/unit/prepare.js index 320b0a8..f7966ed 100644 --- a/test/unit/prepare.js +++ b/test/unit/prepare.js @@ -32,7 +32,7 @@ prepare(function (done) { .reply((uri, body) => { const id = idFromUri(uri) if (testData.esStorage.content[id]) { - testData.esStorage.content[id] = body.doc + _.assign(testData.esStorage.content[id], body.doc) return [200] } else { return [404] @@ -59,6 +59,31 @@ prepare(function (done) { return [404] } }) + .post(uri => uri.includes('_search')) + .query(true) + .reply(uri => { + if (Object.keys(testData.esStorage.content).length > 0) { + return [200, { + hits: { + total: { + value: 1 + }, + hits: [{ + _source: testData.esStorage.content[Object.keys(testData.esStorage.content)[0]] + }] + } + } ] + } else { + return [200, { + hits: { + total: { + value: 0 + }, + hits: [] + } + } ] + } + }) done() }, function (done) { nock.cleanAll() diff --git a/test/unit/test.js b/test/unit/test.js index 6f9ca67..d2d3f66 100644 --- a/test/unit/test.js +++ b/test/unit/test.js @@ -15,7 +15,9 @@ const constants = require('../../src/common/constants') const services = { JobProcessorService: require('../../src/services/JobProcessorService'), JobCandidateProcessorService: require('../../src/services/JobCandidateProcessorService'), - ResourceBookingProcessorService: require('../../src/services/ResourceBookingProcessorService') + ResourceBookingProcessorService: require('../../src/services/ResourceBookingProcessorService'), + WorkPeriodProcessorService: require('../../src/services/WorkPeriodProcessorService'), + WorkPeriodPaymentProcessorService: require('../../src/services/WorkPeriodPaymentProcessorService') } // random transaction id here @@ -48,58 +50,133 @@ describe('General Logic Tests', () => { sandbox.restore() }) + describe('Job, JobCandidate, ResourceBooking tests', () => { + for (const [index, model] of [ + [config.esConfig.ES_INDEX_JOB, 'Job'], + [config.esConfig.ES_INDEX_JOB_CANDIDATE, 'JobCandidate'], + [config.esConfig.ES_INDEX_RESOURCE_BOOKING, 'ResourceBooking'] + ]) { + const modelInSpaceCase = stringcase.spacecase(model) + it(`processCreate - ${modelInSpaceCase} success`, async () => { + await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) + should.deepEqual( + testData.esStorage.content[testData.messages[model].create.message.payload.id], + testData.messages[model].create.message.payload + ) + }) + + it(`processUpdate - ${modelInSpaceCase} success`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) + should.deepEqual( + testData.esStorage.content[testData.messages[model].create.message.payload.id], + testData.messages[model].update.message.payload + ) + }) + + it(`processDelete - ${modelInSpaceCase} success`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + await services[`${model}ProcessorService`].processDelete(testData.messages[model].delete.message, transactionId) + should.not.exist(testData.esStorage.content[testData.messages[model].create.message.payload.id]) + }) - for (const [index, model] of [ - [config.esConfig.ES_INDEX_JOB, 'Job'], - [config.esConfig.ES_INDEX_JOB_CANDIDATE, 'JobCandidate'], - [config.esConfig.ES_INDEX_RESOURCE_BOOKING, 'ResourceBooking'] - ]) { + it(`Failure - processCreate - ${modelInSpaceCase} already exists`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[model].create.message.payload.id, + body: testData.messages[model].create.message.payload, + refresh: 'true' + }) + try { + await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) + throw new Error() + } catch (err) { + should.equal(err.message, `id: ${testData.messages[model].create.message.payload.id} "${index}" already exists`) + } + }) + + it(`Failure - processUpdate - ${modelInSpaceCase} not found`, async () => { + try { + await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) + throw new Error() + } catch (err) { + should.equal(err.message, `id: ${testData.messages[model].update.message.payload.id} "${index}" not found`) + } + }) + + it(`Failure - processDelete - ${modelInSpaceCase} not found`, async () => { + try { + await services[`${model}ProcessorService`].processDelete(testData.messages[model].delete.message, transactionId) + throw new Error() + } catch (err) { + should.equal(err.message, `id: ${testData.messages[model].delete.message.payload.id} "${index}" not found`) + } + }) + } + }) + describe('Nested WorkPeriod tests', () => { + const index = config.esConfig.ES_INDEX_RESOURCE_BOOKING + const model = 'WorkPeriod' + const parentModel = 'ResourceBooking' + const nestedName = 'workPeriods' const modelInSpaceCase = stringcase.spacecase(model) - it('processCreate - success', async () => { + it(`processCreate - ${modelInSpaceCase} success`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[parentModel].create.message.payload.id, + body: testData.messages[parentModel].create.message.payload, + refresh: 'true' + }) await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) should.deepEqual( - testData.esStorage.content[testData.messages[model].create.message.payload.id], - testData.messages[model].create.message.payload + testData.esStorage.content[testData.messages[parentModel].create.message.payload.id], + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] }) ) }) - it('processUpdate - success', async () => { + it(`processUpdate - ${modelInSpaceCase} success`, async () => { await testHelper.esClient.create({ index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, + id: testData.messages[parentModel].create.message.payload.id, + body: _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] }), refresh: 'true' }) await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) should.deepEqual( - testData.esStorage.content[testData.messages[model].create.message.payload.id], - testData.messages[model].update.message.payload + testData.esStorage.content[testData.messages[parentModel].create.message.payload.id], + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].update.message.payload] }) ) }) - it('processDelete - success', async () => { + it(`processDelete - ${modelInSpaceCase} success`, async () => { await testHelper.esClient.create({ index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, + id: testData.messages[parentModel].create.message.payload.id, + body: _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] }), refresh: 'true' }) await services[`${model}ProcessorService`].processDelete(testData.messages[model].delete.message, transactionId) - should.not.exist(testData.esStorage.content[testData.messages[model].create.message.payload.id]) + should.deepEqual( + testData.esStorage.content[testData.messages[parentModel].create.message.payload.id], + _.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [] }) + ) }) - - it(`Failure - processCreate - ${modelInSpaceCase} already exists`, async () => { - await testHelper.esClient.create({ - index, - id: testData.messages[model].create.message.payload.id, - body: testData.messages[model].create.message.payload, - refresh: 'true' - }) + it(`Failure - processCreate - ${modelInSpaceCase} not found`, async () => { try { await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) throw new Error() } catch (err) { - should.equal(err.message, `id: ${testData.messages[model].create.message.payload.id} "${index}" already exists`) + should.equal(err.message, `id: ${testData.messages[parentModel].create.message.payload.id} "${index}" not found`) } }) @@ -108,7 +185,7 @@ describe('General Logic Tests', () => { await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) throw new Error() } catch (err) { - should.equal(err.message, `id: ${testData.messages[model].update.message.payload.id} "${index}" not found`) + should.equal(err.message, `id: ${testData.messages[model].update.message.payload.id} "${model}" not found`) } }) @@ -117,10 +194,64 @@ describe('General Logic Tests', () => { await services[`${model}ProcessorService`].processDelete(testData.messages[model].delete.message, transactionId) throw new Error() } catch (err) { - should.equal(err.message, `id: ${testData.messages[model].delete.message.payload.id} "${index}" not found`) + should.equal(err.message, `id: ${testData.messages[model].delete.message.payload.id} "${model}" not found`) } }) - } + }) + describe('Nested WorkPeriodPayment tests', () => { + const index = config.esConfig.ES_INDEX_RESOURCE_BOOKING + const model = 'WorkPeriodPayment' + const parentModel = 'WorkPeriod' + const rootModel = 'ResourceBooking' + const nestedName = 'payments' + const parentNestedName = 'workPeriods' + const modelInSpaceCase = stringcase.spacecase(model) + it(`processCreate - ${modelInSpaceCase} success`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[rootModel].create.message.payload.id, + body: _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [testData.messages[parentModel].create.message.payload] }), + refresh: 'true' + }) + await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) + should.deepEqual( + testData.esStorage.content[testData.messages[rootModel].create.message.payload.id], + _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] })] }) + ) + }) + + it(`processUpdate - ${modelInSpaceCase} success`, async () => { + await testHelper.esClient.create({ + index, + id: testData.messages[rootModel].create.message.payload.id, + body: _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].create.message.payload] })] }), + refresh: 'true' + }) + await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) + should.deepEqual( + testData.esStorage.content[testData.messages[rootModel].create.message.payload.id], + _.assign(testData.messages[rootModel].create.message.payload, { [parentNestedName]: [_.assign(testData.messages[parentModel].create.message.payload, { [nestedName]: [testData.messages[model].update.message.payload] })] }) + ) + }) + + it(`Failure - processCreate - ${modelInSpaceCase} not found`, async () => { + try { + await services[`${model}ProcessorService`].processCreate(testData.messages[model].create.message, transactionId) + throw new Error() + } catch (err) { + should.equal(err.message, `id: ${testData.messages[parentModel].create.message.payload.id} "${parentModel}" not found`) + } + }) + + it(`Failure - processUpdate - ${modelInSpaceCase} not found`, async () => { + try { + await services[`${model}ProcessorService`].processUpdate(testData.messages[model].update.message, transactionId) + throw new Error() + } catch (err) { + should.equal(err.message, `id: ${testData.messages[model].update.message.payload.id} "${model}" not found`) + } + }) + }) }) describe('Zapier Logic Tests', () => { @@ -158,10 +289,10 @@ describe('Zapier Logic Tests', () => { }) describe('Job Candidate Update', () => { - it('should post to Zapier if status is changed to "rejected"', async () => { + it('should post to Zapier if status is changed to "client rejected - screening"', async () => { const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'open', externalId: '123' }) const updateMessage = _.assign({}, testData.messages.JobCandidate.update.message, { - payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'rejected', externalId: '123' }) + payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'client rejected - screening', externalId: '123' }) }) await testHelper.esClient.create({ @@ -181,10 +312,10 @@ describe('Zapier Logic Tests', () => { helper.postMessageViaWebhook.callCount.should.equal(1) }) - it('should post to Zapier if status is changed to "shortlist"', async () => { + it('should post to Zapier if status is changed to "interview"', async () => { const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'open', externalId: '123' }) const updateMessage = _.assign({}, testData.messages.JobCandidate.update.message, { - payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'shortlist', externalId: '123' }) + payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'interview', externalId: '123' }) }) await testHelper.esClient.create({ @@ -204,10 +335,10 @@ describe('Zapier Logic Tests', () => { helper.postMessageViaWebhook.callCount.should.equal(1) }) - it('should not post to Zapier if status was already "rejected"', async () => { - const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'rejected', externalId: '123' }) + it('should not post to Zapier if status was already "client rejected - screening"', async () => { + const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'client rejected - screening', externalId: '123' }) const updateMessage = _.assign({}, testData.messages.JobCandidate.update.message, { - payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'rejected', externalId: '123' }) + payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'client rejected - screening', externalId: '123' }) }) await testHelper.esClient.create({ @@ -227,10 +358,10 @@ describe('Zapier Logic Tests', () => { helper.postMessageViaWebhook.callCount.should.equal(0) }) - it('should not post to Zapier if status was already "shortlist"', async () => { - const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'shortlist', externalId: '123' }) + it('should not post to Zapier if status was already "interview"', async () => { + const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'interview', externalId: '123' }) const updateMessage = _.assign({}, testData.messages.JobCandidate.update.message, { - payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'shortlist', externalId: '123' }) + payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'interview', externalId: '123' }) }) await testHelper.esClient.create({ @@ -250,10 +381,10 @@ describe('Zapier Logic Tests', () => { helper.postMessageViaWebhook.callCount.should.equal(0) }) - it('should not post to Zapier if status is changed to "interview" (not "rejected" or "shortlist")', async () => { + it('should not post to Zapier if status is changed to "placed" (not "rejected" or "shortlist")', async () => { const previousData = _.assign({}, testData.messages.JobCandidate.create.message.payload, { status: 'open', externalId: '123' }) const updateMessage = _.assign({}, testData.messages.JobCandidate.update.message, { - payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'interview', externalId: '123' }) + payload: _.assign({}, testData.messages.JobCandidate.update.message.payload, { status: 'placed', externalId: '123' }) }) await testHelper.esClient.create({