diff --git a/.eslintrc.js b/.eslintrc.js index 1c21a821..abfc56e0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,7 +4,6 @@ module.exports = { es6: true, node: true }, - parser: "babel-eslint", rules: { // These rules assume eslint recommended, if the rules is accepted from // eslint:recommended settings it is commented out and noted to the right of diff --git a/cypressWebpack/plugins/index.js b/cypressWebpack/plugins/index.js index 612f1cac..e0da6097 100644 --- a/cypressWebpack/plugins/index.js +++ b/cypressWebpack/plugins/index.js @@ -37,6 +37,7 @@ module.exports = (on, config) => { resolve: { fallback: { "fs": false, + "process/browser": require.resolve("process/browser") }, } } diff --git a/package-lock.json b/package-lock.json index 6e8f4069..b7c1fa45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,14 +20,10 @@ "web-worker": "^1.3.0" }, "devDependencies": { - "@babel/core": "^7.25.2", - "@babel/preset-env": "^7.25.4", "@cypress/browserify-preprocessor": "^3.0.2", "@cypress/vite-dev-server": "^5.2.0", "@cypress/webpack-preprocessor": "^6.0.2", - "babel-eslint": "^10.1.0", - "babel-plugin-transform-remove-strict-mode": "^0.0.2", - "chai": "^4.5.0", + "chai": "4.5.0", "concurrently": "^9.0.1", "convert-hrtime": "^5.0.0", "cypress": "^13.14.2", @@ -37,11 +33,11 @@ "node-polyfill-webpack-plugin": "^4.0.0", "nodemon": "^3.1.7", "nyc": "^17.1.0", + "sinon": "^19.0.2", "url-polyfill": "^1.1.12", "wait-on": "^8.0.1", "webpack": "^5.94.0", - "webpack-cli": "^5.1.4", - "wtfnode": "^0.9.3" + "webpack-cli": "^5.1.4" } }, "node_modules/@ampproject/remapping": { @@ -2431,6 +2427,50 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", "dev": true }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/commons/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", + "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "lodash.get": "^4.4.2", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -3078,27 +3118,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "eslint": ">= 4.12.1" - } - }, "node_modules/babel-loader": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", @@ -3162,12 +3181,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-transform-remove-strict-mode": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-strict-mode/-/babel-plugin-transform-remove-strict-mode-0.0.2.tgz", - "integrity": "sha512-iYRG9kH+jXfLaE5wUe/RP5uFd1MTkgTWFuhxJyaQLA6+sMwj31GNTAZCZowLOXGX2KkgH/ej1+3x0D2lKXadKQ==", - "dev": true - }, "node_modules/babelify": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", @@ -5190,15 +5203,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -7480,6 +7484,12 @@ "node": ">=0.8.0" } }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -7639,6 +7649,12 @@ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, "node_modules/lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", @@ -8252,6 +8268,19 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/nise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", + "just-extend": "^6.2.0", + "path-to-regexp": "^8.1.0" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -9150,6 +9179,15 @@ "node": ">= 0.8.0" } }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -10115,6 +10153,54 @@ "node": ">=10" } }, + "node_modules/sinon": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -11459,15 +11545,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/wtfnode": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.9.3.tgz", - "integrity": "sha512-MXjgxJovNVYUkD85JBZTKT5S5ng/e56sNuRZlid7HcGTNrIODa5UPtqE3i0daj7fJ2SGj5Um2VmiphQVyVKK5A==", - "dev": true, - "bin": { - "wtfnode": "proxy.js" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 7d029356..3781e70b 100644 --- a/package.json +++ b/package.json @@ -149,13 +149,9 @@ }, "homepage": "https://github.com/cassproject/cass-npm#readme", "devDependencies": { - "@babel/core": "^7.25.2", - "@babel/preset-env": "^7.25.4", "@cypress/browserify-preprocessor": "^3.0.2", "@cypress/vite-dev-server": "^5.2.0", "@cypress/webpack-preprocessor": "^6.0.2", - "babel-eslint": "^10.1.0", - "babel-plugin-transform-remove-strict-mode": "^0.0.2", "chai": "4.5.0", "concurrently": "^9.0.1", "convert-hrtime": "^5.0.0", @@ -166,10 +162,10 @@ "node-polyfill-webpack-plugin": "^4.0.0", "nodemon": "^3.1.7", "nyc": "^17.1.0", + "sinon": "^19.0.2", "url-polyfill": "^1.1.12", "wait-on": "^8.0.1", "webpack": "^5.94.0", - "webpack-cli": "^5.1.4", - "wtfnode": "^0.9.3" + "webpack-cli": "^5.1.4" } } diff --git a/src/com/eduworks/ec/array/EcArray.js b/src/com/eduworks/ec/array/EcArray.js index 9c36400c..43a2eb59 100644 --- a/src/com/eduworks/ec/array/EcArray.js +++ b/src/com/eduworks/ec/array/EcArray.js @@ -69,21 +69,17 @@ module.exports = class EcArray { * @memberOf EcArray */ static has = function (a, o) { + if (a.includes(o)) + return true; if (EcObject.isObject(o)) - for (let i = 0; i < a.length; i++) { - if (a[i] === o) return true; + for (let b of a) { try { - if (a[i].equals(o)) return true; + if (b.equals != null) + if (b.equals(o)) return true; } catch (e) { // eat quietly } } - else - for (let i = 0; i < a.length; i++) { - if (a[i] === o) { - return true; - } - } return false; }; /** @@ -97,21 +93,18 @@ module.exports = class EcArray { * @memberOf EcArray */ static indexOf = function (a, o) { + let index = a.indexOf(o); + if (index != -1) + return index; if (EcObject.isObject(o)) for (let i = 0; i < a.length; i++) { - if (a[i] === o) return i; try { - if (a[i].equals(o)) return i; + if (a[i].equals != null) + if (a[i].equals(o)) return i; } catch (e) { // eat quietly } } - else - for (let i = 0; i < a.length; i++) { - if (a[i] === o) { - return i; - } - } return -1; }; }; diff --git a/src/com/eduworks/ec/crypto/EcAes.js b/src/com/eduworks/ec/crypto/EcAes.js index d3cc16da..4298b120 100644 --- a/src/com/eduworks/ec/crypto/EcAes.js +++ b/src/com/eduworks/ec/crypto/EcAes.js @@ -1,4 +1,4 @@ -let forge = require("node-forge"); +const forge = require("node-forge"); /** * AES encryption tasks common across all variants of AES. * @class EcAes diff --git a/src/com/eduworks/ec/crypto/EcAesCtr.js b/src/com/eduworks/ec/crypto/EcAesCtr.js index 31f72ed8..defa7c06 100644 --- a/src/com/eduworks/ec/crypto/EcAesCtr.js +++ b/src/com/eduworks/ec/crypto/EcAesCtr.js @@ -1,5 +1,5 @@ -let forge = require("node-forge"); -let EcCrypto = require("./EcCrypto.js"); +const forge = require("node-forge"); +const EcCrypto = require("./EcCrypto.js"); /** * Encrypts data synchronously using AES-256-CTR. Requires secret and iv to be 32 bytes. * Output is encoded in base64 for easier handling. @@ -23,7 +23,7 @@ module.exports = class EcAesCtr { * @deprecated For backup use only. Instead, use await on EcAesCtrAsync. */ static encrypt(plaintext, secret, iv) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcAesCtrAsync." ); @@ -58,7 +58,7 @@ module.exports = class EcAesCtr { * @deprecated For backup use only. Instead, use await on EcAesCtrAsync. */ static decrypt(ciphertext, secret, iv) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcAesCtrAsync." ); diff --git a/src/com/eduworks/ec/crypto/EcAesCtrAsync.js b/src/com/eduworks/ec/crypto/EcAesCtrAsync.js index 4c7f4936..92252b8a 100644 --- a/src/com/eduworks/ec/crypto/EcAesCtrAsync.js +++ b/src/com/eduworks/ec/crypto/EcAesCtrAsync.js @@ -1,5 +1,4 @@ -let base64 = require("base64-arraybuffer"); -let forge = require("node-forge"); +const base64 = require("base64-arraybuffer"); require("../../../../org/cassproject/general/AuditLogger.js"); if (typeof crypto == 'undefined') { @@ -15,24 +14,22 @@ if (typeof crypto == 'undefined') } } -let EcCrypto = require("./EcCrypto.js"); -let EcAesCtrAsyncWorker = require("./EcAesCtrAsyncWorker.js"); -let cassPromisify = require("../promises/helpers.js").cassPromisify; -let cassReturnAsPromise = require("../promises/helpers.js").cassReturnAsPromise; -let realCrypto = require('crypto'); +const EcCrypto = require("./EcCrypto.js"); +const cassPromisify = require("../promises/helpers.js").cassPromisify; +const cassReturnAsPromise = require("../promises/helpers.js").cassReturnAsPromise; +const realCrypto = require('crypto'); let inWorker = false; let fipsForced = false; /** * Async version of EcAesCtr that uses browser extensions (window.crypto) to accomplish cryptography much faster. - * Falls back to EcAesCtrAsyncWorker, if window.crypto is not available. + * Falls back to EcAesCtr, if window.crypto is not available. * @class EcAesCtrAsync */ module.exports = class EcAesCtrAsync { static fipsOn() { if (inWorker || fipsForced) return; - if (typeof process !== 'undefined' && process && process.env && process.env.FIPS) - if (realCrypto.getFips() == 0) + if (typeof process !== 'undefined' && process?.env?.FIPS && realCrypto.getFips() == 0) try { realCrypto.setFips(true); } catch (e) { @@ -51,8 +48,7 @@ module.exports = class EcAesCtrAsync { static fipsOff() { if (inWorker || fipsForced) return; - if (typeof process !== 'undefined' && process && process.env && process.env.FIPS) - if (realCrypto.getFips() == 1) + if (typeof process !== 'undefined' && process?.env?.FIPS && realCrypto.getFips() == 1) try { realCrypto.setFips(false); } catch (e) { @@ -83,12 +79,7 @@ module.exports = class EcAesCtrAsync { * @static */ static encrypt(plaintext, secret, iv, success, failure) { - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { + if (crypto?.subtle == null) { return EcAesCtr.encrypt( plaintext, secret, @@ -148,12 +139,7 @@ module.exports = class EcAesCtrAsync { return cassReturnAsPromise(cacheGet, success, failure); } } - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { + if (crypto?.subtle == null) { return EcAesCtr.decrypt( ciphertext, secret, diff --git a/src/com/eduworks/ec/crypto/EcAesCtrAsyncWorker.js b/src/com/eduworks/ec/crypto/EcAesCtrAsyncWorker.js index a956b175..bb8c7a04 100644 --- a/src/com/eduworks/ec/crypto/EcAesCtrAsyncWorker.js +++ b/src/com/eduworks/ec/crypto/EcAesCtrAsyncWorker.js @@ -1,6 +1,5 @@ let forge = require("node-forge"); let EcCrypto = require("./EcCrypto.js"); -let EcAesCtr = require("./EcAesCtr.js"); let EcRsaOaepAsyncWorker = require("./EcRsaOaepAsyncWorker.js"); let cassPromisify = require("../promises/helpers.js").cassPromisify; let cassReturnAsPromise = require("../promises/helpers.js").cassReturnAsPromise; diff --git a/src/com/eduworks/ec/crypto/EcRsaOaep.js b/src/com/eduworks/ec/crypto/EcRsaOaep.js index d696f44d..0d32f1f8 100644 --- a/src/com/eduworks/ec/crypto/EcRsaOaep.js +++ b/src/com/eduworks/ec/crypto/EcRsaOaep.js @@ -21,7 +21,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static encrypt(pk, plaintext) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); @@ -45,7 +45,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static decrypt(ppk, ciphertext) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); @@ -83,7 +83,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static sign(ppk, text) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); @@ -108,7 +108,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static signSha256 = function(ppk, text) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); @@ -130,7 +130,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static verify(pk, text, signature) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); @@ -162,7 +162,7 @@ module.exports = class EcRsaOaep { * @deprecated For backup use only. Instead, use await on EcRsaOaepAsync. */ static verifySha256 = function(pk, text, signature) { - if (EcCrypto.deprecationNotice == false) + if (!EcCrypto.deprecationNotice) console.trace( "This method is deprecated. Please use await on EcRsaOaepAsync." ); diff --git a/src/com/eduworks/ec/crypto/EcRsaOaepAsync.js b/src/com/eduworks/ec/crypto/EcRsaOaepAsync.js index 352f8a3b..46bc09ab 100644 --- a/src/com/eduworks/ec/crypto/EcRsaOaepAsync.js +++ b/src/com/eduworks/ec/crypto/EcRsaOaepAsync.js @@ -2,7 +2,6 @@ let base64 = require("base64-arraybuffer"); let forge = require("node-forge"); const EcAesCtrAsync = require("./EcAesCtrAsync.js"); require("../../../../org/cassproject/general/AuditLogger.js"); -let crypto = undefined; if (typeof crypto == 'undefined') { if (typeof window !== 'undefined' && window != null && window !== undefined) @@ -43,22 +42,11 @@ module.exports = class EcRsaOaepAsync { static encrypt(pk, plainText, success, failure) { if (EcCrypto.testMode) console.log("encrypt: " + plainText) - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { - return EcRsaOaep.encrypt( - pk, - plainText, - success, - failure - ); + if (crypto?.subtle == null) { + return EcRsaOaep.encrypt(pk, plainText, success, failure); //NOSONAR -- This is a Fallback method. } EcAesCtrAsync.fipsOn(); - let keyUsages = []; - keyUsages.push("encrypt"); + let keyUsages = ["encrypt"]; let algorithm = {}; algorithm.name = "RSA-OAEP"; algorithm.hash = "SHA-1"; @@ -111,18 +99,8 @@ module.exports = class EcRsaOaepAsync { return cassReturnAsPromise(cacheGet, success, failure); } } - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { - return EcRsaOaep.decrypt( - ppk, - cipherText, - success, - failure - ); + if (crypto?.subtle == null) { + return EcRsaOaep.decrypt(ppk, cipherText, success, failure); //NOSONAR -- This is a Fallback method. } EcAesCtrAsync.fipsOn(); let algorithm = {}; @@ -193,21 +171,14 @@ module.exports = class EcRsaOaepAsync { static sign(ppk, text, success, failure) { if (EcCrypto.testMode) console.log("sign (sha1): " + text) - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined || - (typeof process !== 'undefined' && process && process.env && process.env.FIPS) - ) { - return EcRsaOaep.sign(ppk, text, success, failure); + if (crypto?.subtle == null || (typeof process !== 'undefined' && process?.env?.FIPS)) { + return EcRsaOaep.sign(ppk, text, success, failure); //NOSONAR -- This is a Fallback method. } if (text == null) { return cassReturnAsPromise(null, success, failure); } EcAesCtrAsync.fipsOff();// OPENSSL3 signing with this method not allowed. See https://github.com/Lomilar/node-fips-rsassa-pkcs1-15-sha1/tree/main - let keyUsages = []; - keyUsages.push("sign"); + let keyUsages = ["sign"]; let algorithm = {}; algorithm.name = "RSASSA-PKCS1-v1_5"; algorithm.hash = "SHA-1"; @@ -264,13 +235,8 @@ module.exports = class EcRsaOaepAsync { static signSha256 = function (ppk, text, success, failure) { if (EcCrypto.testMode) console.log("sign (sha256): " + text) - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { - return EcRsaOaep.sign(ppk, text, success, failure); + if (crypto?.subtle == null) { + return EcRsaOaep.sign(ppk, text, success, failure); //NOSONAR -- This is a Fallback method. } EcAesCtrAsync.fipsOn(); let keyUsages = []; @@ -321,19 +287,8 @@ module.exports = class EcRsaOaepAsync { static verify(pk, text, signature, success, failure) { if (EcCrypto.testMode) console.log("verify (sha1): " + text) - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { - return EcRsaOaep.verify( - pk, - text, - signature, - success, - failure - ); + if (crypto?.subtle == null) { + return EcRsaOaep.verify(pk, text, signature, success, failure); //NOSONAR -- This is a Fallback method. } EcAesCtrAsync.fipsOn(); let algorithm = {}; @@ -396,19 +351,8 @@ module.exports = class EcRsaOaepAsync { static verifySha256(pk, text, signature, success, failure) { if (EcCrypto.testMode) console.log("verify (sha256): " + text) - if ( - crypto == null || - crypto === undefined || - crypto.subtle == null || - crypto.subtle === undefined - ) { - return EcRsaOaep.verify( - pk, - text, - signature, - success, - failure - ); + if (crypto?.subtle == null) { + return EcRsaOaep.verify(pk, text, signature, success, failure); //NOSONAR -- This is a Fallback method. } EcAesCtrAsync.fipsOn(); let algorithm = {}; diff --git a/src/com/eduworks/ec/crypto/EcRsaOaepAsyncWorker.js b/src/com/eduworks/ec/crypto/EcRsaOaepAsyncWorker.js index ef45cd42..537018a1 100644 --- a/src/com/eduworks/ec/crypto/EcRsaOaepAsyncWorker.js +++ b/src/com/eduworks/ec/crypto/EcRsaOaepAsyncWorker.js @@ -4,12 +4,12 @@ if (global.Worker === undefined || global.Worker == null) let PromiseWorker = require("promise-worker"); const path = require('path'); const url = require('url'); -let EcCrypto = require("./EcCrypto.js"); -let forge = require("node-forge"); -let cassPromisify = require("../promises/helpers.js").cassPromisify; -let cassReturnAsPromise = require("../promises/helpers.js").cassReturnAsPromise; +const EcCrypto = require("./EcCrypto.js"); +const forge = require("node-forge"); +const cassPromisify = require("../promises/helpers.js").cassPromisify; +const cassReturnAsPromise = require("../promises/helpers.js").cassReturnAsPromise; require("../../../../org/cassproject/general/AuditLogger.js"); -let EcRsaOaep = require("./EcRsaOaep.js") +const EcRsaOaep = require("./EcRsaOaep.js") /** * Asynchronous implementation of {{#crossLink @@ -22,13 +22,10 @@ let EcRsaOaep = require("./EcRsaOaep.js") module.exports = class EcRsaOaepAsyncWorker { static rotator = 0; static w = null; - static teardown(){ + static teardown() { if (this.w != null) - for (let i = 0;i < this.w.length;i++) - { - let worker = this.w[i]; + for (let worker of this.w) worker._worker.terminate(); - } this.w = null; } static initWorker() { @@ -57,7 +54,7 @@ module.exports = class EcRsaOaepAsyncWorker { wkr = new Worker(url.pathToFileURL(path.resolve(__dirname, 'forgeAsync.js'))); } catch (e) { global.auditLogger.report(global.auditLogger.LogCategory.SYSTEM, global.auditLogger.Severity.ERROR, "EcRsaOaepAsyncWorker", e); - } + } if (wkr == null) try { wkr = new Worker(path.resolve(__dirname, 'forgeAsync.js')); @@ -70,10 +67,10 @@ module.exports = class EcRsaOaepAsyncWorker { me.w[index] = (new PromiseWorker(wkr)); } } - } catch (e) { - global.auditLogger.report(global.auditLogger.LogCategory.SYSTEM, global.auditLogger.Severity.ERROR, "EcRsaOaepAsyncWorker", e); - // Eat quietly. - } + } catch (e) { + global.auditLogger.report(global.auditLogger.LogCategory.SYSTEM, global.auditLogger.Severity.ERROR, "EcRsaOaepAsyncWorker", e); + // Eat quietly. + } if (wkr != null) this.w[index] = (new PromiseWorker(wkr)); } @@ -93,11 +90,8 @@ module.exports = class EcRsaOaepAsyncWorker { static encrypt(pk, plaintext, success, failure) { this.initWorker(); if (!EcCrypto.testMode) - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.encrypt(pk, plaintext)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.encrypt(pk, plaintext), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; @@ -133,11 +127,8 @@ module.exports = class EcRsaOaepAsyncWorker { } this.initWorker(); if (!EcCrypto.testMode) - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.decrypt(ppk, ciphertext)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.decrypt(ppk, ciphertext), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; @@ -146,15 +137,14 @@ module.exports = class EcRsaOaepAsyncWorker { o["text"] = ciphertext; o["cmd"] = "decryptRsaOaep"; o["origin"] = "cassproject"; - let p = this.w[worker].postMessage(o, 'cassproject'); + let p = this.w[worker].postMessage(o, 'cassproject'); p = p.then(function (decrypted) { return forge.util.decodeUtf8(decrypted); }); if (EcCrypto.caching) p = p.then(function (decrypted) { - return EcCrypto.decryptionCache[ - ppk.toPk().fingerprint() + ciphertext - ] = decrypted; + EcCrypto.decryptionCache[ppk.toPk().fingerprint() + ciphertext] = decrypted; + return decrypted; }); return cassPromisify(p, success, failure); } @@ -174,11 +164,8 @@ module.exports = class EcRsaOaepAsyncWorker { static sign(ppk, text, success, failure) { this.initWorker(); if (!EcCrypto.testMode) - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.sign(ppk, text)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.sign(ppk, text), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; @@ -206,11 +193,8 @@ module.exports = class EcRsaOaepAsyncWorker { static signSha256 = function (ppk, text, success, failure) { this.initWorker(); if (!EcCrypto.testMode) - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.signSha256(ppk, text)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.signSha256(ppk, text), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; @@ -219,7 +203,7 @@ module.exports = class EcRsaOaepAsyncWorker { o["text"] = forge.util.encodeUtf8(text); o["cmd"] = "signSha256RsaOaep"; o["origin"] = "cassproject"; - let p = this.w[worker].postMessage(o,'cassproject'); + let p = this.w[worker].postMessage(o, 'cassproject'); return cassPromisify(p, success, failure); }; /** @@ -238,11 +222,8 @@ module.exports = class EcRsaOaepAsyncWorker { */ static verify(pk, text, signature, success, failure) { this.initWorker(); - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.verify(pk, text, signature)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.verify(pk, text, signature), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; @@ -271,11 +252,8 @@ module.exports = class EcRsaOaepAsyncWorker { */ static verifySha256(pk, text, signature, success, failure) { this.initWorker(); - if (this.w == null || this.w[this.rotator] == null) { - let p = new Promise((resolve, reject) => { - resolve(EcRsaOaepAsync.verify(pk, text, signature)); - }); - return cassPromisify(p, success, failure); + if (this.w?.[this.rotator] == null) { + return cassPromisify(EcRsaOaepAsync.verify(pk, text, signature), success, failure); } let worker = this.rotator++; this.rotator = this.rotator % 8; diff --git a/src/com/eduworks/ec/graph/EcDirectedGraph.js b/src/com/eduworks/ec/graph/EcDirectedGraph.js index 3f1ec31c..56864355 100644 --- a/src/com/eduworks/ec/graph/EcDirectedGraph.js +++ b/src/com/eduworks/ec/graph/EcDirectedGraph.js @@ -27,13 +27,13 @@ module.exports = class EcDirectedGraph extends Graph { return results; } containsVertex(vertex) { - for (let i = 0; i < this.verticies.length; i++) - if (vertex.equals(this.verticies[i])) return true; + for (let vertex2 of this.verticies) + if (vertex.equals(vertex2)) return true; return false; } containsEdge(edge) { - for (let i = 0; i < this.edges.length; i++) - if (edge.equals(this.edges[i].edge)) return true; + for (let edge2 of this.edges) + if (edge.equals(edge2.edge)) return true; return false; } getEdgeCount() { @@ -44,65 +44,63 @@ module.exports = class EcDirectedGraph extends Graph { } getNeighbors(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].source)) - results.push(this.edges[i].destination); - else if (vertex.equals(this.edges[i].destination)) - results.push(this.edges[i].source); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.source)) + results.push(edge2.destination); + else if (vertex.equals(edge2.destination)) + results.push(edge2.source); } EcArray.removeDuplicates(results); return results; } getIncidentEdges(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].source)) - results.push(this.edges[i].edge); - else if (vertex.equals(this.edges[i].destination)) - results.push(this.edges[i].edge); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.source) || vertex.equals(edge2.destination)) + results.push(edge2.edge); } EcArray.removeDuplicates(results); return results; } getIncidentVertices(edge) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (edge.equals(this.edges[i].edge)) { - results.push(this.edges[i].source); - results.push(this.edges[i].destination); + for (let edge2 of this.edges) { + if (edge.equals(edge2.edge)) { + results.push(edge2.source); + results.push(edge2.destination); } } EcArray.removeDuplicates(results); return results; } findEdge(v1, v2) { - for (let i = 0; i < this.edges.length; i++) { + for (let edge2 of this.edges) { if ( - v1.equals(this.edges[i].source) && - v2.equals(this.edges[i].destination) + v1.equals(edge2.source) && + v2.equals(edge2.destination) ) - return this.edges[i].edge; + return edge2.edge; if ( - v1.equals(this.edges[i].destination) && - v2.equals(this.edges[i].source) + v1.equals(edge2.destination) && + v2.equals(edge2.source) ) - return this.edges[i].edge; + return edge2.edge; } return null; } findEdgeSet(v1, v2) { let results = []; - for (let i = 0; i < this.edges.length; i++) { + for (let edge2 of this.edges) { if ( - v1.equals(this.edges[i].source) && - v2.equals(this.edges[i].destination) + v1.equals(edge2.source) && + v2.equals(edge2.destination) ) - results.push(this.edges[i].edge); + results.push(edge2.edge); if ( - v1.equals(this.edges[i].destination) && - v2.equals(this.edges[i].source) + v1.equals(edge2.destination) && + v2.equals(edge2.source) ) - results.push(this.edges[i].edge); + results.push(edge2.edge); } return results; } @@ -111,7 +109,8 @@ module.exports = class EcDirectedGraph extends Graph { return true; } addVertexSafely(vertex) { - if (EcArray.has(this.verticies, vertex)) return false; + if (EcArray.has(this.verticies, vertex)) + return false; this.verticies.push(vertex); return true; } @@ -123,8 +122,7 @@ module.exports = class EcDirectedGraph extends Graph { this.edges[i].source.equals(vertex) || this.edges[i].destination.equals(vertex) ) { - this.edges.splice(i, 1); - i--; + this.edges.splice(i--, 1); //NOSONAR It's fine. } } this.verticies.splice(indexOf, 1); @@ -136,34 +134,25 @@ module.exports = class EcDirectedGraph extends Graph { let success = false; for (let i = 0; i < this.edges.length; i++) { if (this.edges[i].edge.equals(edge)) { - this.edges.splice(i, 1); - i--; + this.edges.splice(i--, 1); //NOSONAR It's fine. success = true; } } return success; } isNeighbor(v1, v2) { - for (let i = 0; i < this.edges.length; i++) { - if ( - v1.equals(this.edges[i].source) && - v2.equals(this.edges[i].destination) - ) - return true; - else if ( - v1.equals(this.edges[i].destination) && - v2.equals(this.edges[i].source) - ) + for (let edge2 of this.edges) { + if ((v1.equals(edge2.source) && v2.equals(edge2.destination)) || (v1.equals(edge2.destination) && v2.equals(edge2.source))) return true; } return false; } isIncident(vertex, edge) { - for (let i = 0; i < this.edges.length; i++) { + for (let edge2 of this.edges) { if ( - (vertex.equals(this.edges[i].source) || - vertex.equals(this.edges[i].destination)) && - edge.equals(this.edges[i].edge) + (vertex.equals(edge2.source) || + vertex.equals(edge2.destination)) && + edge.equals(edge2.edge) ) return true; } @@ -171,10 +160,10 @@ module.exports = class EcDirectedGraph extends Graph { } degree(vertex) { let count = 0; - for (let i = 0; i < this.edges.length; i++) { + for (let edge2 of this.edges) { if ( - vertex.equals(this.edges[i].source) || - vertex.equals(this.edges[i].destination) + vertex.equals(edge2.source) || + vertex.equals(edge2.destination) ) count++; } @@ -186,13 +175,13 @@ module.exports = class EcDirectedGraph extends Graph { getIncidentCount(edge) { return this.getIncidentVertices(edge).length; } - getEdgeType(edge) {} - getDefaultEdgeType() {} + getEdgeType(edge) { } //NOSONAR -- This is a stub method. + getDefaultEdgeType() { } //NOSONAR -- This is a stub method. getEdgesOfType(edge_type) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (this.getEdgeType(this.edges[i].edge) == edge_type) - results.push(this.edges[i].edge); + for (let edge2 of this.edges) { + if (this.getEdgeType(edge2.edge) == edge_type) + results.push(edge2.edge); } return results; } @@ -201,18 +190,18 @@ module.exports = class EcDirectedGraph extends Graph { } getInEdges(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].destination)) - results.push(this.edges[i].edge); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.destination)) + results.push(edge2.edge); } EcArray.removeDuplicates(results); return results; } getOutEdges(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].source)) - results.push(this.edges[i].edge); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.source)) + results.push(edge2.edge); } EcArray.removeDuplicates(results); return results; @@ -224,48 +213,48 @@ module.exports = class EcDirectedGraph extends Graph { return this.getOutEdges(vertex).length; } getSource(directed_edge) { - for (let i = 0; i < this.edges.length; i++) { - if (directed_edge.equals(this.edges[i].edge)) - return this.edges[i].source; + for (let edge2 of this.edges) { + if (directed_edge.equals(edge2.edge)) + return edge2.source; } return null; } getDest(directed_edge) { - for (let i = 0; i < this.edges.length; i++) { - if (directed_edge.equals(this.edges[i].edge)) - return this.edges[i].destination; + for (let edge2 of this.edges) { + if (directed_edge.equals(edge2.edge)) + return edge2.destination; } return null; } getPredecessors(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].destination)) - results.push(this.edges[i].source); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.destination)) + results.push(edge2.source); } EcArray.removeDuplicates(results); return results; } getSuccessors(vertex) { let results = []; - for (let i = 0; i < this.edges.length; i++) { - if (vertex.equals(this.edges[i].source)) - results.push(this.edges[i].destination); + for (let edge2 of this.edges) { + if (vertex.equals(edge2.source)) + results.push(edge2.destination); } EcArray.removeDuplicates(results); return results; } isPredecessor(v1, v2) { - for (let i = 0; i < this.edges.length; i++) { - if (v1.equals(this.edges[i].destination)) - if (v2.equals(this.edges[i].source)) return true; + for (let edge2 of this.edges) { + if (v1.equals(edge2.destination)) + if (v2.equals(edge2.source)) return true; } return false; } isSuccessor(v1, v2) { - for (let i = 0; i < this.edges.length; i++) { - if (v2.equals(this.edges[i].destination)) - if (v1.equals(this.edges[i].source)) return true; + for (let edge2 of this.edges) { + if (v2.equals(edge2.destination)) + if (v1.equals(edge2.source)) return true; } return false; } @@ -276,16 +265,16 @@ module.exports = class EcDirectedGraph extends Graph { return this.getSuccessors(vertex).length; } isSource(vertex, edge) { - for (let i = 0; i < this.edges.length; i++) { - if (edge.equals(this.edges[i].edge)) - if (vertex.equals(this.edges[i].source)) return true; + for (let edge2 of this.edges) { + if (edge.equals(edge2.edge)) + if (vertex.equals(edge2.source)) return true; } return false; } isDest(vertex, edge) { - for (let i = 0; i < this.edges.length; i++) { - if (edge.equals(this.edges[i].edge)) - if (vertex.equals(this.edges[i].destination)) return true; + for (let edge2 of this.edges) { + if (edge.equals(edge2.edge)) + if (vertex.equals(edge2.destination)) return true; } return false; } @@ -319,12 +308,12 @@ module.exports = class EcDirectedGraph extends Graph { return true; } getOpposite(vertex, edge) { - for (let i = 0; i < this.edges.length; i++) { - if (edge.equals(this.edges[i].edge)) - if (vertex.equals(this.edges[i].destination)) - return this.edges[i].source; - else if (vertex.equals(this.edges[i].source)) - return this.edges[i].destination; + for (let edge2 of this.edges) { + if (edge.equals(edge2.edge)) + if (vertex.equals(edge2.destination)) + return edge2.source; + else if (vertex.equals(edge2.source)) + return edge2.destination; } return null; } diff --git a/src/com/eduworks/ec/graph/EcFrameworkGraph.js b/src/com/eduworks/ec/graph/EcFrameworkGraph.js index f139de6b..2d3db0b5 100644 --- a/src/com/eduworks/ec/graph/EcFrameworkGraph.js +++ b/src/com/eduworks/ec/graph/EcFrameworkGraph.js @@ -216,7 +216,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { assertion ); await Promise.all( - await this.getOutEdges(competency).map(async (alignment) => + this.getOutEdges(competency).map(async (alignment) => await this.getCompetency(alignment.target).then(async (t) => await this.processAssertionBooleanOutward( alignment, @@ -229,7 +229,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { ) ).then(async() => await Promise.all( - await this.getInEdges(competency).map(async (alignment) => + this.getInEdges(competency).map(async (alignment) => await this.getCompetency(alignment.source).then(async (s) => await this.processAssertionBooleanInward( alignment, @@ -250,7 +250,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { assertion ); await Promise.all( - await this.getInEdges(competency).map(async (alignment) => + this.getInEdges(competency).map(async (alignment) => await this.getCompetency(alignment.source).then(async (t) => await this.processAssertionBooleanOutward( alignment, @@ -263,7 +263,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { ) ).then(async () => await Promise.all( - await this.getOutEdges(competency).map(async (alignment) => + this.getOutEdges(competency).map(async (alignment) => await this.getCompetency(alignment.target).then(async (s) => await this.processAssertionBooleanInward( alignment, @@ -285,14 +285,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { negative, visited ) { - if (alignment.relationType == Relation.NARROWS) - await this.processAssertionsBooleanPerAssertion( - assertions, - negative, - c, - visited - ); - else if (alignment.relationType == Relation.IS_EQUIVALENT_TO) + if (alignment.relationType == Relation.NARROWS || alignment.relationType == Relation.IS_EQUIVALENT_TO) await this.processAssertionsBooleanPerAssertion( assertions, negative, @@ -307,14 +300,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { negative, visited ) { - if (alignment.relationType == Relation.REQUIRES) - await this.processAssertionsBooleanPerAssertion( - assertions, - negative, - c, - visited - ); - else if (alignment.relationType == Relation.IS_EQUIVALENT_TO) + if (alignment.relationType == Relation.REQUIRES || alignment.relationType == Relation.IS_EQUIVALENT_TO) await this.processAssertionsBooleanPerAssertion( assertions, negative, @@ -338,7 +324,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { getMetaStateCompetency(c) { let result = this.metaVerticies[c.shortId()]; if (result === undefined || result == null) { - if (this.containsVertex(c) == false) return null; + if (!this.containsVertex(c)) return null; if (this.metaVerticies[c.shortId()] == null) this.metaVerticies[c.shortId()] = result = {}; } @@ -347,7 +333,7 @@ module.exports = class EcFrameworkGraph extends EcDirectedGraph { getMetaStateAlignment(a) { let result = this.metaEdges[a.shortId()]; if (result == null) { - if (this.containsEdge(a) == false) return null; + if (!this.containsEdge(a)) return null; if (this.metaEdges[a.shortId()] == null) this.metaEdges[a.shortId()] = result = {}; } diff --git a/src/com/eduworks/ec/graph/Graph.js b/src/com/eduworks/ec/graph/Graph.js index a08b6976..42265dbb 100644 --- a/src/com/eduworks/ec/graph/Graph.js +++ b/src/com/eduworks/ec/graph/Graph.js @@ -50,7 +50,7 @@ module.exports = class Graph extends Hypergraph { * to vertex in this graph * @method getInEdges */ - getInEdges(vertex) {} + getInEdges(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Collection view of the outgoing edges incident to vertex * in this graph. @@ -60,7 +60,7 @@ module.exports = class Graph extends Hypergraph { * to vertex in this graph * @method getOutEdges */ - getOutEdges(vertex) {} + getOutEdges(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Collection view of the predecessors of vertex * in this graph. A predecessor of vertex is defined as a vertex v @@ -73,7 +73,7 @@ module.exports = class Graph extends Hypergraph { * vertex in this graph * @method getPredecessors */ - getPredecessors(vertex) {} + getPredecessors(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Collection view of the successors of vertex * in this graph. A successor of vertex is defined as a vertex v @@ -86,7 +86,7 @@ module.exports = class Graph extends Hypergraph { * vertex in this graph * @method getSuccessors */ - getSuccessors(vertex) {} + getSuccessors(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of incoming edges incident to vertex. * Equivalent to getInEdges(vertex).size(). @@ -95,7 +95,7 @@ module.exports = class Graph extends Hypergraph { * @return the number of incoming edges incident to vertex * @method inDegree */ - inDegree(vertex) {} + inDegree(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of outgoing edges incident to vertex. * Equivalent to getOutEdges(vertex).size(). @@ -104,7 +104,7 @@ module.exports = class Graph extends Hypergraph { * @return the number of outgoing edges incident to vertex * @method outDegree */ - outDegree(vertex) {} + outDegree(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if v1 is a predecessor of v2 in this graph. * Equivalent to v1.getPredecessors().contains(v2). @@ -114,7 +114,7 @@ module.exports = class Graph extends Hypergraph { * @return true if v1 is a predecessor of v2, and false otherwise. * @method isPredecessor */ - isPredecessor(v1, v2) {} + isPredecessor(v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if v1 is a successor of v2 in this graph. * Equivalent to v1.getSuccessors().contains(v2). @@ -124,7 +124,7 @@ module.exports = class Graph extends Hypergraph { * @return true if v1 is a successor of v2, and false otherwise. * @method isSuccessor */ - isSuccessor(v1, v2) {} + isSuccessor(v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of predecessors that vertex has in this graph. * Equivalent to vertex.getPredecessors().size(). @@ -133,7 +133,7 @@ module.exports = class Graph extends Hypergraph { * @return the number of predecessors that vertex has in this graph * @method getPredecessorCount */ - getPredecessorCount(vertex) {} + getPredecessorCount(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of successors that vertex has in this graph. * Equivalent to vertex.getSuccessors().size(). @@ -142,7 +142,7 @@ module.exports = class Graph extends Hypergraph { * @return the number of successors that vertex has in this graph * @method getSuccessorCount */ - getSuccessorCount(vertex) {} + getSuccessorCount(vertex) { } //NOSONAR -- Method is intended to be abstract /** * If directed_edge is a directed edge in this graph, returns the source; * otherwise returns null. @@ -155,7 +155,7 @@ module.exports = class Graph extends Hypergraph { * @return the source of directed_edge if it is a directed edge in this graph, or null otherwise * @method getSource */ - getSource(directed_edge) {} + getSource(directed_edge) { } //NOSONAR -- Method is intended to be abstract /** * If directed_edge is a directed edge in this graph, returns the destination; * otherwise returns null. @@ -169,7 +169,7 @@ module.exports = class Graph extends Hypergraph { * @return the destination of directed_edge if it is a directed edge in this graph, or null otherwise * @method getDest */ - getDest(directed_edge) {} + getDest(directed_edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if vertex is the source of edge. * Equivalent to getSource(edge).equals(vertex). @@ -179,7 +179,7 @@ module.exports = class Graph extends Hypergraph { * @return true iff vertex is the source of edge * @method isSource */ - isSource(vertex, edge) {} + isSource(vertex, edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if vertex is the destination of edge. * Equivalent to getDest(edge).equals(vertex). @@ -188,7 +188,7 @@ module.exports = class Graph extends Hypergraph { * @param edge the edge to be queried * @return true iff vertex is the destination of edge */ - isDest(vertex, edge) {} + isDest(vertex, edge) { } //NOSONAR -- Method is intended to be abstract /** * Adds edge e to this graph such that it connects * vertex v1 to v2. @@ -209,7 +209,7 @@ module.exports = class Graph extends Hypergraph { * @see Hypergraph#addEdge(Object, Collection) * @see #addEdge(Object, Object, Object, EdgeType) */ - addEdge(e, v1, v2) {} + addEdge(e, v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Returns the vertex at the other end of edge from vertex. * (That is, returns the vertex incident to edge which is not vertex.) @@ -219,5 +219,5 @@ module.exports = class Graph extends Hypergraph { * @return the vertex at the other end of edge from vertex * @method getOpposite */ - getOpposite(vertex, edge) {} + getOpposite(vertex, edge) { } //NOSONAR -- Method is intended to be abstract }; diff --git a/src/com/eduworks/ec/graph/Hypergraph.js b/src/com/eduworks/ec/graph/Hypergraph.js index 2baa51d5..e0f0032c 100644 --- a/src/com/eduworks/ec/graph/Hypergraph.js +++ b/src/com/eduworks/ec/graph/Hypergraph.js @@ -48,7 +48,7 @@ module.exports = class Hypergraph { * @return a Array view of all edges in this graph * @method getEdges */ - getEdges() {} + getEdges() { } //NOSONAR -- Method is intended to be abstract /** * Returns a view of all vertices in this graph. In general, this obeys the * Array contract, and therefore makes no guarantees about the @@ -57,7 +57,7 @@ module.exports = class Hypergraph { * @return a Array view of all vertices in this graph * @method getVerticies */ - getVertices() {} + getVertices() { } //NOSONAR -- Method is intended to be abstract /** * Returns true if this graph's vertex collection contains * vertex. Equivalent to @@ -67,7 +67,7 @@ module.exports = class Hypergraph { * @return true iff this graph contains a vertex vertex * @method containsVertex */ - containsVertex(vertex) {} + containsVertex(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if this graph's edge collection contains edge. * Equivalent to getEdges().contains(edge). @@ -76,21 +76,21 @@ module.exports = class Hypergraph { * @return true iff this graph contains an edge edge * @method containsEdge */ - containsEdge(edge) {} + containsEdge(edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of edges in this graph. * * @return the number of edges in this graph * @method getEdgeCount */ - getEdgeCount() {} + getEdgeCount() { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of vertices in this graph. * * @return the number of vertices in this graph * @method getVertexCount */ - getVertexCount() {} + getVertexCount() { } //NOSONAR -- Method is intended to be abstract /** * Returns the collection of vertices which are connected to * vertex via any edges in this graph. If vertex @@ -103,7 +103,7 @@ module.exports = class Hypergraph { * is not present * @method getNeighbors */ - getNeighbors(vertex) {} + getNeighbors(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the collection of edges in this graph which are connected to * vertex. @@ -114,7 +114,7 @@ module.exports = class Hypergraph { * is not present * @method getIncidentEdges */ - getIncidentEdges(vertex) {} + getIncidentEdges(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the collection of vertices in this graph which are connected to * edge. Note that for some graph types there are guarantees @@ -129,7 +129,7 @@ module.exports = class Hypergraph { * not present * @method getIncidentVertices */ - getIncidentVertices(edge) {} + getIncidentVertices(edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns an edge that connects this vertex to v. If this edge * is not uniquely defined (that is, if the graph contains more than one @@ -158,7 +158,7 @@ module.exports = class Hypergraph { * @method findEdge * @see Hypergraph#findEdgeSet(Object, Object) */ - findEdge(v1, v2) {} + findEdge(v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Returns all edges that connects this vertex to v. If this * edge is not uniquely defined (that is, if the graph contains more than @@ -186,7 +186,7 @@ module.exports = class Hypergraph { * @method findEdgeSet * @see Hypergraph#findEdge(Object, Object) */ - findEdgeSet(v1, v2) {} + findEdgeSet(v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Adds vertex to this graph. Fails if vertex is * null or already in the graph. @@ -197,7 +197,7 @@ module.exports = class Hypergraph { * @throws IllegalArgumentException if vertex is null * @method addVertex */ - addVertex(vertex) {} + addVertex(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Adds edge to this graph. Fails under the following * circumstances: @@ -221,7 +221,7 @@ module.exports = class Hypergraph { * legal vertex set for edge * @method addHyperEdge */ - addHyperEdge(edge, vertices) {} + addHyperEdge(edge, vertices) { } //NOSONAR -- Method is intended to be abstract /** * Removes vertex from this graph. As a side effect, removes * any edges e incident to vertex if the removal @@ -242,7 +242,7 @@ module.exports = class Hypergraph { * false otherwise * @method removeVertex */ - removeVertex(vertex) {} + removeVertex(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Removes edge from this graph. Fails if edge is * null, or is otherwise not an element of this graph. @@ -252,7 +252,7 @@ module.exports = class Hypergraph { * false otherwise * @method removeEdge */ - removeEdge(edge) {} + removeEdge(edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if v1 and v2 share an * incident edge. Equivalent to getNeighbors(v1).contains(v2). @@ -263,7 +263,7 @@ module.exports = class Hypergraph { * incident edge * @method isNeighbor */ - isNeighbor(v1, v2) {} + isNeighbor(v1, v2) { } //NOSONAR -- Method is intended to be abstract /** * Returns true if vertex and edge * are incident to each other. Equivalent to @@ -276,7 +276,7 @@ module.exports = class Hypergraph { * are incident to each other * @method isIncident */ - isIncident(vertex, edge) {} + isIncident(vertex, edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of edges incident to vertex. Special * cases of interest: @@ -300,7 +300,7 @@ module.exports = class Hypergraph { * @method degree * @see Hypergraph#getNeighborCount(Object) */ - degree(vertex) {} + degree(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of vertices that are adjacent to vertex * (that is, the number of vertices that are incident to edges in @@ -313,7 +313,7 @@ module.exports = class Hypergraph { * @return the number of neighboring vertices * @method getNeighborCount */ - getNeighborCount(vertex) {} + getNeighborCount(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of vertices that are incident to edge. * For hyperedges, this can be any nonnegative integer; for edges this must @@ -326,7 +326,7 @@ module.exports = class Hypergraph { * @return the number of vertices that are incident to edge. * @method getIncidentCount */ - getIncidentCount(edge) {} + getIncidentCount(edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns the edge type of edge in this graph. * @@ -335,14 +335,14 @@ module.exports = class Hypergraph { * null if edge has no defined type * @method getEdgeType */ - getEdgeType(edge) {} + getEdgeType(edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns the default edge type for this graph. * * @return the default edge type for this graph * @method getDefaultEdgeType */ - getDefaultEdgeType() {} + getDefaultEdgeType() { } //NOSONAR -- Method is intended to be abstract /** * Returns the collection of edges in this graph which are of type * edge_type. @@ -354,7 +354,7 @@ module.exports = class Hypergraph { * @method getEdgesOfType * @see EdgeType */ - getEdgesOfType(edge_type) {} + getEdgesOfType(edge_type) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of edges of type edge_type in this graph. * @@ -362,7 +362,7 @@ module.exports = class Hypergraph { * @return the number of edges of type edge_type in this graph * @method getEdgeCountOfType */ - getEdgeCountOfType(edge_type) {} + getEdgeCountOfType(edge_type) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Array view of the incoming edges incident to * vertex in this graph. @@ -372,7 +372,7 @@ module.exports = class Hypergraph { * vertex in this graph * @method getInEdges */ - getInEdges(vertex) {} + getInEdges(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Array view of the outgoing edges incident to * vertex in this graph. @@ -382,7 +382,7 @@ module.exports = class Hypergraph { * vertex in this graph * @method getOutEdges */ - getOutEdges(vertex) {} + getOutEdges(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of incoming edges incident to vertex. * Equivalent to getInEdges(vertex).size(). @@ -391,7 +391,7 @@ module.exports = class Hypergraph { * @return the number of incoming edges incident to vertex * @method inDegree */ - inDegree(vertex) {} + inDegree(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns the number of outgoing edges incident to vertex. * Equivalent to getOutEdges(vertex).size(). @@ -400,7 +400,7 @@ module.exports = class Hypergraph { * @return the number of outgoing edges incident to vertex * @method outDegree */ - outDegree(vertex) {} + outDegree(vertex) { } //NOSONAR -- Method is intended to be abstract /** * If directed_edge is a directed edge in this graph, returns * the source; otherwise returns null. The source of a directed @@ -413,7 +413,7 @@ module.exports = class Hypergraph { * in this graph, or null otherwise * @method getSource */ - getSource(directed_edge) {} + getSource(directed_edge) { } //NOSONAR -- Method is intended to be abstract /** * If directed_edge is a directed edge in this graph, returns * the destination; otherwise returns null. The destination of @@ -427,7 +427,7 @@ module.exports = class Hypergraph { * edge in this graph, or null otherwise * @method getDest */ - getDest(directed_edge) {} + getDest(directed_edge) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Array view of the predecessors of * vertex in this graph. A predecessor of vertex @@ -441,7 +441,7 @@ module.exports = class Hypergraph { * vertex in this graph * @method getPredecessors */ - getPredecessors(vertex) {} + getPredecessors(vertex) { } //NOSONAR -- Method is intended to be abstract /** * Returns a Array view of the successors of * vertex in this graph. A successor of vertex is @@ -455,5 +455,5 @@ module.exports = class Hypergraph { * vertex in this graph * @method getSuccessors */ - getSuccessors(vertex) {} + getSuccessors(vertex) { } //NOSONAR -- Method is intended to be abstract }; diff --git a/src/com/eduworks/ec/promises/helpers.js b/src/com/eduworks/ec/promises/helpers.js index 7a612dfd..2cb48f4e 100644 --- a/src/com/eduworks/ec/promises/helpers.js +++ b/src/com/eduworks/ec/promises/helpers.js @@ -12,7 +12,6 @@ module.exports = { cassReturnAsPromise: function (o, success, failure, error) { let p = new Promise((resolve, reject) => { if (o === undefined || o == null) { - // console.trace(error); reject(new Error(error)); } else resolve(o); diff --git a/src/com/eduworks/ec/remote/EcRemote.js b/src/com/eduworks/ec/remote/EcRemote.js index 270c15e3..f6c43df6 100644 --- a/src/com/eduworks/ec/remote/EcRemote.js +++ b/src/com/eduworks/ec/remote/EcRemote.js @@ -15,20 +15,20 @@ if (isNode) let undici = eval("require('undici');"); if (undici != null) { - var {setGlobalDispatcher,Agent,fetch} = undici; + var {setGlobalDispatcher,Agent,fetch} = undici; //NOSONAR - Intentional use of var to allow for global scope. setGlobalDispatcher(new Agent({ allowH2: process.env.HTTP2 != null ? process.env.HTTP2.trim() == 'true' : true })) } } if (typeof window !== 'undefined' && window.fetch != null) - var fetch = window.fetch; + var fetch = window.fetch; //NOSONAR - Intentional use of var to allow for global scope. if (isNode) { try{ - var dns = require('node:dns'); - if (dns && dns.setDefaultResultOrder) + var dns = require('node:dns'); //NOSONAR - Intentional use of var to allow for global scope. + if (dns?.setDefaultResultOrder) { //Support for Node 18 using Docker containers with a network that doesn't support ipv6 loopback. dns.setDefaultResultOrder('ipv4first'); @@ -154,7 +154,7 @@ module.exports = class EcRemote { if (DEBUG) console.log("POST " + server + "" + (service || "") + " " + headers + fd); let url = server; - if (!url.endsWith("/") && service != null && !("" == service)) { + if (!url.endsWith("/") && service != null && "" != service) { url += "/"; } if (service != null) { @@ -362,13 +362,11 @@ module.exports = class EcRemote { } static upgradeHttpToHttps(url) { if (typeof window !== "undefined") - if (window != null) { - if (window.location != null) { - if (url.indexOf(window.location.protocol) == -1) { - if (window.location.protocol.startsWith("https")) { - if (!url.startsWith("https:")) { - url = url.replace("http:", "https:"); - } + if (window?.location != null) { + if (url.indexOf(window.location.protocol) == -1) { + if (window.location.protocol.startsWith("https")) { + if (!url.startsWith("https:")) { + url = url.replace("http:", "https:"); } } } diff --git a/src/com/eduworks/ec/task/EcAsyncTask.js b/src/com/eduworks/ec/task/EcAsyncTask.js index 3c184806..04bfdb90 100644 --- a/src/com/eduworks/ec/task/EcAsyncTask.js +++ b/src/com/eduworks/ec/task/EcAsyncTask.js @@ -53,7 +53,7 @@ module.exports = class EcAsyncTask { return this.start; } doTask(_arguments) { - let ret = undefined; + let ret; if (!this.isStarted) { this.start = new Date(); this.isStarted = true; @@ -91,35 +91,35 @@ module.exports = class EcAsyncTask { } invoke0 = function() { let that = this; - let ret = this.job.call(this, function() { + let ret = this.job.call(this, function() { //NOSONAR -- Not taking that chance. that.setComplete(); }); return ret; }; invoke1 = function(arg1) { let that = this; - let ret = this.job.call(this, arg1, function() { + let ret = this.job.call(this, arg1, function () { //NOSONAR -- Not taking that chance. that.setComplete(); }); return ret; }; invoke2 = function(arg1, arg2) { let that = this; - let ret = this.job.call(this, arg1, arg2, function() { + let ret = this.job.call(this, arg1, arg2, function () { //NOSONAR -- Not taking that chance. that.setComplete(); }); return ret; }; invoke3 = function(arg1, arg2, arg3) { let that = this; - let ret = this.job.call(this, arg1, arg2, arg3, function() { + let ret = this.job.call(this, arg1, arg2, arg3, function () { //NOSONAR -- Not taking that chance. that.setComplete(); }); return ret; }; invoke4 = function(arg1, arg2, arg3, arg4) { let that = this; - let ret = this.job.call(this, arg1, arg2, arg3, arg4, function() { + let ret = this.job.call(this, arg1, arg2, arg3, arg4, function() { //NOSONAR -- Not taking that chance. that.setComplete(); }); return ret; diff --git a/src/com/eduworks/ec/task/EcAsyncTaskManager.js b/src/com/eduworks/ec/task/EcAsyncTaskManager.js index e42ef1a0..41e72cc4 100644 --- a/src/com/eduworks/ec/task/EcAsyncTaskManager.js +++ b/src/com/eduworks/ec/task/EcAsyncTaskManager.js @@ -18,8 +18,7 @@ module.exports = class EcAsyncTaskManager { addTasks(tasks) { let retMap = {}; if (tasks != undefined) { - for (let i = 0; i < tasks.length; i++) { - let task = tasks[i]; + for (let task of tasks) { let key = this.addTask(task); retMap[key] = task; } @@ -62,9 +61,9 @@ module.exports = class EcAsyncTaskManager { assignNewTask(task) { let min = 10000; let theGuy = null; - for (let i = 0; i < this.workerList.length; i++) { - if (this.workerList[i].getAssignedCount() < min) { - theGuy = this.workerList[i]; + for (let worker of this.workerList) { + if (worker.getAssignedCount() < min) { + theGuy = worker; min = theGuy.getAssignedCount(); } } diff --git a/src/com/eduworks/ec/task/EcAsyncTaskWorker.js b/src/com/eduworks/ec/task/EcAsyncTaskWorker.js index 3a8b66cf..eb0d390e 100644 --- a/src/com/eduworks/ec/task/EcAsyncTaskWorker.js +++ b/src/com/eduworks/ec/task/EcAsyncTaskWorker.js @@ -52,9 +52,7 @@ module.exports = class EcAsyncTaskWorker { that.invoke(); } if ( - that.currentTask != undefined && - that.currentTask != null && - that.currentTask.getIsComplete() + that.currentTask?.getIsComplete() ) { that.currentTask = that.assignedList.shift(); } diff --git a/src/com/eduworks/ec/task/Task.js b/src/com/eduworks/ec/task/Task.js index 655a50bd..32c77a96 100644 --- a/src/com/eduworks/ec/task/Task.js +++ b/src/com/eduworks/ec/task/Task.js @@ -7,7 +7,7 @@ */ let Task = null; module.exports = Task = class Task { - static constructor() { + static() { Task.updateFrame(); } static desiredFps = 2; diff --git a/src/org/cass/competency/EcAlignment.js b/src/org/cass/competency/EcAlignment.js index b9197681..2182cbd6 100644 --- a/src/org/cass/competency/EcAlignment.js +++ b/src/org/cass/competency/EcAlignment.js @@ -1,5 +1,6 @@ const EcRepository = require("../../cassproject/ebac/repository/EcRepository.js"); const Relation = require("../../cassproject/schema/cass/competency/Relation.js"); +const EcRemoteLinkedData = require("../../cassproject/schema/general/EcRemoteLinkedData.js"); /** * Implementation of an alignment object with methods for interacting with CASS * services on a server. diff --git a/src/org/cass/competency/EcCompetency.js b/src/org/cass/competency/EcCompetency.js index 0bf79a4d..f3c38c59 100644 --- a/src/org/cass/competency/EcCompetency.js +++ b/src/org/cass/competency/EcCompetency.js @@ -1,5 +1,8 @@ const EcRepository = require("../../cassproject/ebac/repository/EcRepository.js"); const Competency = require("../../cassproject/schema/cass/competency/Competency.js"); +const EcAlignment = require("./EcAlignment.js"); +const EcLevel = require("./EcLevel.js"); +const EcRollupRule = require("./EcRollupRule.js"); require("../../cassproject/general/AuditLogger.js"); /** * Implementation of a Competency object with methods for interacting with CASS diff --git a/src/org/cass/competency/EcFramework.js b/src/org/cass/competency/EcFramework.js index 71fa5878..8fd8e131 100644 --- a/src/org/cass/competency/EcFramework.js +++ b/src/org/cass/competency/EcFramework.js @@ -104,20 +104,14 @@ module.exports = class EcFramework extends Framework { addCompetency(id) { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.competency == null) this.competency = []; - for (let i = 0; i < this.competency.length; i++) - if ( - EcRemoteLinkedData.trimVersionFromUrl( - this.competency[i] - ) == id - ) + for (let compId of this.competency) + if (EcRemoteLinkedData.trimVersionFromUrl(compId) == id) return; this.competency.push(id); } /** * Removes a competency ID from the framework's list, also removes any * levels and relations associated with that competency - *

- * TODO: remove rollup rules? should we add flag to remove these extras * * @param {String} id * ID of the competency to remove @@ -132,10 +126,7 @@ module.exports = class EcFramework extends Framework { let shortId = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.competency == null) this.competency = []; for (let i = 0; i < this.competency.length; i++) - if ( - this.competency[i].equals(shortId) || - this.competency[i].equals(id) - ) + if (this.competency[i] == shortId || this.competency[i] == id) this.competency.splice(i, 1); if ( (this.relation == null || this.relation.length == 0) && @@ -294,10 +285,8 @@ module.exports = class EcFramework extends Framework { addRelation(id) { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.relation == null) this.relation = []; - for (let i = 0; i < this.relation.length; i++) - if ( - EcRemoteLinkedData.trimVersionFromUrl(this.relation[i]) == id - ) + for (let relationId of this.relation) + if (EcRemoteLinkedData.trimVersionFromUrl(relationId) == id) return; this.relation.push(id); } @@ -312,12 +301,8 @@ module.exports = class EcFramework extends Framework { removeRelation(id) { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.relation == null) this.relation = []; - for (let i = 0; i < this.relation.length; i++) - if ( - EcRemoteLinkedData.trimVersionFromUrl(this.relation[i]).equals( - id - ) - ) + for (let i = 0;i < this.relation.length;i++) + if (EcRemoteLinkedData.trimVersionFromUrl(this.relation[i]) == id) this.relation.splice(i, 1); } /** @@ -331,8 +316,8 @@ module.exports = class EcFramework extends Framework { addLevel(id) { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.level == null) this.level = []; - for (let i = 0; i < this.level.length; i++) - if (EcRemoteLinkedData.trimVersionFromUrl(this.level[i]).equals(id)) + for (let levelId of this.level) + if (EcRemoteLinkedData.trimVersionFromUrl(levelId) == id) return; this.level.push(id); } @@ -348,7 +333,7 @@ module.exports = class EcFramework extends Framework { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.level == null) this.level = []; for (let i = 0; i < this.level.length; i++) - if (EcRemoteLinkedData.trimVersionFromUrl(this.level[i]).equals(id)) + if (EcRemoteLinkedData.trimVersionFromUrl(this.level[i]) == id) this.level.splice(i, 1); } /** @@ -362,12 +347,8 @@ module.exports = class EcFramework extends Framework { addRollupRule(id) { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.rollupRule == null) this.rollupRule = []; - for (let i = 0; i < this.rollupRule.length; i++) - if ( - EcRemoteLinkedData.trimVersionFromUrl( - this.rollupRule[i] - ).equals(id) - ) + for (let rollupRuleId of this.rollupRule) + if (EcRemoteLinkedData.trimVersionFromUrl(rollupRuleId) == id) return; this.rollupRule.push(id); } @@ -383,11 +364,7 @@ module.exports = class EcFramework extends Framework { id = EcRemoteLinkedData.trimVersionFromUrl(id); if (this.rollupRule == null) this.rollupRule = []; for (let i = 0; i < this.rollupRule.length; i++) - if ( - EcRemoteLinkedData.trimVersionFromUrl( - this.rollupRule[i] - ).equals(id) - ) + if (EcRemoteLinkedData.trimVersionFromUrl(this.rollupRule[i]) == id) this.rollupRule.splice(i, 1); } /** diff --git a/src/org/cass/competency/EcLevel.js b/src/org/cass/competency/EcLevel.js index 7c9f56d5..beaab9c8 100644 --- a/src/org/cass/competency/EcLevel.js +++ b/src/org/cass/competency/EcLevel.js @@ -1,5 +1,7 @@ const EcRepository = require("../../cassproject/ebac/repository/EcRepository.js"); const Level = require("../../cassproject/schema/cass/competency/Level.js"); +const EcRemoteLinkedData = require("../../cassproject/schema/general/EcRemoteLinkedData.js"); +const EcAlignment = require("./EcAlignment.js"); /** * Implementation of a Level object with methods for interacting with CASS * services on a server. @@ -121,7 +123,6 @@ module.exports = class EcLevel extends Level { targetLevel, alignmentType, identity, - serverUrl, success, failure, repo, eim @@ -131,11 +132,11 @@ module.exports = class EcLevel extends Level { a.target = targetLevel.id; a.relationType = alignmentType; a.addOwner(identity.toPk()); - if (repo == null || repo.selectedServer.indexOf(serverUrl) != -1) - a.generateId(serverUrl); - else a.generateShortId(serverUrl); + if (repo?.selectedServer != null) + a.generateId(repo.selectedServer); await a.signWith(identity); - return a.save(success, failure, repo, eim); + await a.save(success, failure, repo, eim); + return a; } /** * Method to set the name of this level diff --git a/src/org/cassproject/schema/general/EcRemoteLinkedData.js b/src/org/cassproject/schema/general/EcRemoteLinkedData.js index b08733a0..d49c7fa5 100644 --- a/src/org/cassproject/schema/general/EcRemoteLinkedData.js +++ b/src/org/cassproject/schema/general/EcRemoteLinkedData.js @@ -26,7 +26,7 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { * @param {string} type JSON-LD Type. * @constructor */ - constructor(context, type) { + constructor(context, type) { //NOSONAR - Required for proper documentation super(context, type); } /** @@ -83,24 +83,24 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { static caching = false; static trimVersionFromUrl(id) { if (id == null) return null; - if (EcRemoteLinkedData.caching == true && EcRemoteLinkedData.tvfuCache[id] != null) + if (EcRemoteLinkedData.caching && EcRemoteLinkedData.tvfuCache[id] != null) return EcRemoteLinkedData.tvfuCache[id]; if ( id.indexOf("/api/data/") == -1 && id.indexOf("/api/custom/data/") == -1 ) { - if (EcRemoteLinkedData.caching == true) + if (EcRemoteLinkedData.caching) EcRemoteLinkedData.tvfuCache[id] = id; return id; } if (!id.substring(id.lastIndexOf("/")).match("^\\/[0-9]+$")) { - if (EcRemoteLinkedData.caching == true) + if (EcRemoteLinkedData.caching) EcRemoteLinkedData.tvfuCache[id] = id; return id; } let rawId = id.substring(0, id.lastIndexOf("/")); if (rawId.endsWith("/")) rawId = rawId.substring(0, rawId.length - 1); - if (EcRemoteLinkedData.caching == true) + if (EcRemoteLinkedData.caching) EcRemoteLinkedData.tvfuCache[id] = rawId; return rawId; } @@ -209,8 +209,9 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { hasOwner(pk) { if (this.owner == null) return false; let pkPem = pk.toPem(); - for (let i = 0; i < this.owner.length; i++) - if (pkPem == EcPk.fromPem(this.owner[i]).toPem()) return true; + for (let ownerPem of this.owner) + if (pkPem == EcPk.fromPem(ownerPem).toPem()) + return true; return false; } /** @@ -225,8 +226,9 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { hasReader(pk) { if (this.reader == null) return false; let pkPem = pk.toPem(); - for (let i = 0; i < this.reader.length; i++) - if (pkPem == EcPk.fromPem(this.reader[i]).toPem()) return true; + for (let readerPem of this.reader) + if (pkPem == EcPk.fromPem(readerPem).toPem()) + return true; return false; } /** @@ -254,8 +256,9 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { canEditAny(ids) { if (this.owner == null || this.owner.length == 0) return true; if (ids == null) return false; - for (let i = 0; i < ids.length; i++) - if (this.hasOwner(ids[i])) return true; + for (let id of ids) + if (this.hasOwner(id)) + return true; return false; } /** @@ -269,18 +272,11 @@ module.exports = class EcRemoteLinkedData extends EcLinkedData { if (ppk instanceof EcPpkFacade) return; let signableJson = this.toSignableJson(); - // let signed = await EcRsaOaepAsync.sign(ppk, signableJson); - // if (this.signature != null) { - // for (let i = 0; i < this.signature.length; i++) - // if (this.signature[i] == signed) return; - // } else { - // this.signature = []; - // } - // this.signature.push(signed); let signedSha256 = await EcRsaOaepAsyncWorker.signSha256(ppk, signableJson); if (this.signatureSha256 != null) { - for (let i = 0; i < this.signatureSha256.length; i++) - if (this.signatureSha256[i] == signedSha256) return; + for (let signatureSha256Actual of this.signatureSha256) + if (signatureSha256Actual == signedSha256) + return; } else { this.signatureSha256 = []; } diff --git a/src/org/json/ld/EcLinkedData.js b/src/org/json/ld/EcLinkedData.js index 7d3a4481..06d89a07 100644 --- a/src/org/json/ld/EcLinkedData.js +++ b/src/org/json/ld/EcLinkedData.js @@ -47,8 +47,9 @@ global.jsonld = require("jsonld"); * @method isAtProperty */ static isAtProperty(key) { - for (let i = 0; i < EcLinkedData.atProperties.length; i++) - if (EcLinkedData.atProperties[i] == key) return true; + for (let atProperty of EcLinkedData.atProperties) + if (atProperty == key) + return true; return false; } /** @@ -107,12 +108,14 @@ global.jsonld = require("jsonld"); let a = []; for (let i = 0; i < o.length; i++) { if (EcObject.isObject(o[i])) { - if (o[i] instanceof EcLinkedData) a[i] = this.atIfyObject(o[i]); - else { + if (o[i] instanceof EcLinkedData) + a[i] = this.atIfyObject(o[i]); + else a[i] = o[i]; - } - } else if (EcArray.isArray(o[i])) a[i] = this.atIfyArray(o[i]); - else a[i] = o[i]; + } else if (EcArray.isArray(o[i])) + a[i] = this.atIfyArray(o[i]); + else + a[i] = o[i]; } return a; } @@ -120,23 +123,24 @@ global.jsonld = require("jsonld"); let keys = []; let me = o; for (let key in me) { - if (me["type"] != null) - if (EcLinkedData.isAtProperty(key)) key = "@" + key; + if (me["type"] != null && EcLinkedData.isAtProperty(key)) + key = "@" + key; //NOSONAR -- Reassignment of non-const variable is intended. keys.push(key); } - keys.sort(function (a, b) { - return a.localeCompare(b); - }); + keys.sort((a, b) => a.localeCompare(b)); let op = {}; - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; + for (let key of keys) { let value = me[key.replace("@", "")]; - if (value != null) - if (value instanceof EcLinkedData) value = value.atIfy(); - else if (EcArray.isArray(value)) value = this.atIfyArray(value); - if (value != null) op[key] = value; - else value = me[key]; - if (value != null) op[key] = value; + if (value != null && value instanceof EcLinkedData) + value = value.atIfy(); + else if (EcArray.isArray(value)) + value = this.atIfyArray(value); + if (value != null) + op[key] = value; + else + value = me[key]; + if (value != null) + op[key] = value; } return op; } @@ -160,11 +164,11 @@ global.jsonld = require("jsonld"); * @return {boolean} True if match, False if not. * @method isAny */ - isAny(type) { + isAny(types) { let computedType = this.getFullType(); - if (type.length == 0) return true; - for (let i = 0; i < type.length; i++) - if (type[i] == computedType || type[i] == this.type) + if (types.length == 0) return true; + for (let type of types) + if (type == computedType || type == this.type) return true; return false; } @@ -204,17 +208,26 @@ global.jsonld = require("jsonld"); * @method copyFrom */ copyFrom(that, eim) { - let me = this; - for (let key in me) { - if (typeof me[key] != "function") delete me[key]; + for (let key in this) { + if (typeof this[key] == "function") + continue; + delete this[key]; } - let you = that; - for (let key in you) { - if (typeof you[key] != "function") { - if (you["@type"] != null) me[key.replace("@", "")] = you[key]; - else me[key] = you[key]; - } + for (let key in that) { + if (typeof that[key] == "function") + continue; + if (that["@type"] != null) + this[key.replace("@", "")] = that[key]; + else + this[key] = that[key]; } + this.swapContext(); + this.upgrade(eim); + if (!this.isAny(this.getTypes())) + throw new Error("Incompatible type: " + this.getFullType() + that); + return this; + } + swapContext() { let stripNamespace = null; let newContext = null; if ( @@ -226,43 +239,31 @@ global.jsonld = require("jsonld"); if (typeParts.length == 2) { newContext = this.context[typeParts[0]]; stripNamespace = typeParts[0]; - if (!newContext.endsWith("/")) newContext += "/"; + if (!newContext.endsWith("/")) + newContext += "/"; } else if (this.context["@vocab"] != null) newContext = this.context["@vocab"]; } if (stripNamespace != null) - for (let key in me) { - if (typeof me[key] != "function") { - if (key.startsWith(stripNamespace + ":")) { - if (EcArray.isArray(me[key])) { - me[ - key.replace(stripNamespace + ":", "") - ] = JSON.parse( - JSON.stringify(me[key]).replace( - stripNamespace + ":", - "" - ) - ); - } else if (EcObject.isObject(me[key])) { - me[ - key.replace(stripNamespace + ":", "") - ] = JSON.parse( - JSON.stringify(me[key]).replace( - stripNamespace + ":", - "" - ) - ); - } else - me[key.replace(stripNamespace + ":", "")] = me[key]; - delete me[key]; - } - } + this.stripNamespace(); + if (newContext != null) + this.context = newContext; + } + stripNamespace() { + for (let key in this) { + if (typeof this[key] != "function" && key.startsWith(stripNamespace + ":")) { + if (EcArray.isArray(this[key]) || EcObject.isObject(this[key])) { + this[key.replace(stripNamespace + ":", "")] = JSON.parse( + JSON.stringify(this[key]).replace( + stripNamespace + ":", + "" + ) + ); + } else + this[key.replace(stripNamespace + ":", "")] = this[key]; + delete this[key]; } - if (newContext != null) this.context = newContext; - this.upgrade(eim); - if (!this.isAny(this.getTypes())) - throw "Incompatible type: " + this.getFullType() + that; - return this; + } } async recast(translationContext, targetContext) { let me = this; @@ -329,7 +330,7 @@ global.jsonld = require("jsonld"); * * @method upgrade */ - upgrade() {} + upgrade() { } //NOSONAR -- Method is a stub. /** * Removes the @ symbol from properties in order to make them more * accessible in Javascript. @@ -339,24 +340,16 @@ global.jsonld = require("jsonld"); * @internal */ deAtify() { - let me = this; - let typeFound = false; - if (me["@type"] != null) typeFound = true; - for (let key in me) { - if (me[key] == null) { + let typeFound = this["@type"] != null; + for (let key in this) { + if (this[key] == null) { if (typeFound) { - let value = me[key]; - if (value != null) - if (value instanceof EcLinkedData) - value = value.deAtify(); - me[key.replace("@", "")] = value; - } else { - let value = me[key]; - if (value != null) - if (value instanceof EcLinkedData) - value = value.deAtify(); - me[key] = value; - } + let value = this[key]; + if (value != null && value instanceof EcLinkedData) + value = value.deAtify(); + this[key.replace("@", "")] = value; + } else if (this?.[key] instanceof EcLinkedData) + this[key] = this[key].deAtify(); } } return this; diff --git a/src/test/EcAes.test.js b/src/test/EcAes.test.js index 68df7376..7952613f 100644 --- a/src/test/EcAes.test.js +++ b/src/test/EcAes.test.js @@ -1,7 +1,6 @@ let chai = require("chai"); const EcAes = require("../com/eduworks/ec/crypto/EcAes"); -let should = chai.should(); let expect = chai.expect; let assert = chai.assert; diff --git a/src/test/EcAesCtr.test.js b/src/test/EcAesCtr.test.js index c977d165..e577b11c 100644 --- a/src/test/EcAesCtr.test.js +++ b/src/test/EcAesCtr.test.js @@ -27,8 +27,8 @@ describe("EcAesCtr", () => { let randomString = EcAes.newIv(1024); let secret = EcAes.newSecret(16); let iv = EcAes.newIv(16); - let encrypted = EcAesCtr.encrypt(randomString, secret, iv); - let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); + let encrypted = EcAesCtr.encrypt(randomString, secret, iv); //NOSONAR + let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); //NOSONAR assert.isTrue(randomString == decrypted); }); it('encryption then decryption (utf-8)', () => { @@ -36,8 +36,8 @@ describe("EcAesCtr", () => { "abc\u16a0\u16c7\u16bb\u16eb\u16d2\u16e6\u16a6\u16eb\u16a0\u16b1\u16a9\u16a0\u16a2\u16b1\u16eb\u16a0\u16c1\u16b1\u16aa\u16eb\u16b7\u16d6\u16bb\u16b9\u16e6\u16da\u16b3\u16a2\u16d7"; let secret = EcAes.newSecret(16); let iv = EcAes.newIv(16); - let encrypted = EcAesCtr.encrypt(randomString, secret, iv); - let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); + let encrypted = EcAesCtr.encrypt(randomString, secret, iv); //NOSONAR + let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); //NOSONAR assert.isTrue(randomString == decrypted); }); it('large encryption then decryption w/caching', () => { @@ -45,17 +45,17 @@ describe("EcAesCtr", () => { let secret = EcAes.newSecret(16); let iv = EcAes.newIv(16); let hrTime = hrtime(); - let encrypted = EcAesCtr.encrypt(randomString, secret, iv); + let encrypted = EcAesCtr.encrypt(randomString, secret, iv); //NOSONAR let elapsed = (hrtime()[0]*1000000 + hrtime()[1]/1000 - hrTime[0] * 1000000 - hrTime[1] / 1000)/1000; console.log(randomString.length/1024+"KB encryption speed: " + elapsed+"ms"); hrTime = hrtime(); EcCrypto.caching = true; - let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); + let decrypted = EcAesCtr.decrypt(encrypted, secret, iv); //NOSONAR elapsed = (hrtime()[0]*1000000 + hrtime()[1]/1000 - hrTime[0] * 1000000 - hrTime[1] / 1000)/1000; console.log("decryption wout/caching speed: " + elapsed+"ms"); hrTime = hrtime(); decrypted = null; - decrypted = EcAesCtr.decrypt(encrypted, secret, iv); + decrypted = EcAesCtr.decrypt(encrypted, secret, iv); //NOSONAR elapsed = (hrtime()[0]*1000000 + hrtime()[1]/1000 - hrTime[0] * 1000000 - hrTime[1] / 1000)/1000; console.log("decryption w/caching speed: " + elapsed+"ms"); assert.isTrue(elapsed < 1); diff --git a/src/test/EcAlignment.test.js b/src/test/EcAlignment.test.js new file mode 100644 index 00000000..abfb0a1e --- /dev/null +++ b/src/test/EcAlignment.test.js @@ -0,0 +1,245 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcAlignment = require('../org/cass/competency/EcAlignment'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); + +const expect = chai.expect; + +describe('EcAlignment', function () { + describe('equals', function () { + it('should return true if obj has same source, target, and relationType', function () { + const alignment1 = new EcAlignment(); + alignment1.source = 'source1'; + alignment1.target = 'target1'; + alignment1.relationType = 'relationType1'; + + const alignment2 = { + source: 'source1', + target: 'target1', + relationType: 'relationType1' + }; + + expect(alignment1.equals(alignment2)).to.be.true; + }); + + it('should return false if obj has different source, target, or relationType', function () { + const alignment1 = new EcAlignment(); + alignment1.source = 'source1'; + alignment1.target = 'target1'; + alignment1.relationType = 'relationType1'; + + const alignment2 = { + source: 'source2', + target: 'target1', + relationType: 'relationType1' + }; + + expect(alignment1.equals(alignment2)).to.be.false; + }); + + it('should return true if obj has same id', function () { + const alignment1 = new EcAlignment(); + alignment1.id = 'id1'; + + const alignment2 = { + id: 'id1' + }; + + expect(alignment1.equals(alignment2)).to.be.true; + }); + }); + + describe('get', function () { + it('should call EcRepository.getAs with correct parameters', function () { + const stub = sinon.stub(EcRepository, 'getAs'); + const id = 'id1'; + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const eim = {}; + + EcAlignment.get(id, success, failure, repo, eim); + + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(id, sinon.match.instanceOf(EcAlignment), success, failure, repo, eim)).to.be.true; + + stub.restore(); + }); + }); + + describe('getBlocking', function () { + it('should call EcRepository.getAs with correct parameters', function () { + const stub = sinon.stub(EcRepository, 'getAs'); + const id = 'id1'; + const repo = {}; + const eim = {}; + + EcAlignment.getBlocking(id, repo, eim); + + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(id, sinon.match.instanceOf(EcAlignment), null, null, repo, eim)).to.be.true; + + stub.restore(); + }); + }); + + describe('search', function () { + it('should call EcRepository.searchAs with correct parameters', function () { + const stub = sinon.stub(EcRepository, 'searchAs'); + const repo = {}; + const query = 'query'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + EcAlignment.search(repo, query, success, failure, paramObj, eim); + + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(repo, query, sinon.match.func, success, failure, paramObj, eim)).to.be.true; + + stub.restore(); + }); + }); + + describe('searchBySource', function () { + it('should call EcAlignment.search with correct query', function () { + const stub = sinon.stub(EcAlignment, 'search'); + const repo = {}; + const sourceId = 'sourceId'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + EcAlignment.searchBySource(repo, sourceId, success, failure, paramObj, eim); + + const expectedQuery = 'source:"sourceId"'; + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(repo, expectedQuery, success, failure, paramObj, eim)).to.be.true; + + stub.restore(); + }); + }); + + describe('searchBySources', function () { + it('should call EcAlignment.search with correct query', function () { + const stub = sinon.stub(EcAlignment, 'search'); + const repo = {}; + const sourceIds = ['sourceId1', 'sourceId2']; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + EcAlignment.searchBySources(repo, sourceIds, success, failure, paramObj, eim); + + const expectedQuery = '(source:"sourceId1" OR source:"sourceId2")'; + expect(stub.calledOnce).to.be.true; + console.log(stub.returnsThis()); + expect(stub.calledWith(repo)).to.be.true; + + stub.restore(); + }); + }); + + describe('searchByCompetency', function () { + it('should call EcAlignment.search with correct query', function () { + const stub = sinon.stub(EcAlignment, 'search'); + const repo = {}; + const competencyId = 'competencyId'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + EcAlignment.searchByCompetency(repo, competencyId, success, failure, paramObj, eim); + + const expectedQuery = ' AND (source:"competencyId" OR target:"competencyId")'; + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(repo, expectedQuery, success, failure, paramObj, eim)).to.be.true; + + stub.restore(); + }); + }); + + describe('save', function () { + it('should throw error if source is missing', function () { + const alignment = new EcAlignment(); + alignment.target = 'target'; + alignment.relationType = 'relationType'; + + expect(() => alignment.save()).to.throw('Source Competency cannot be missing'); + }); + + it('should throw error if target is missing', function () { + const alignment = new EcAlignment(); + alignment.source = 'source'; + alignment.relationType = 'relationType'; + + expect(() => alignment.save()).to.throw('Target Competency cannot be missing'); + }); + + it('should throw error if relationType is missing', function () { + const alignment = new EcAlignment(); + alignment.source = 'source'; + alignment.target = 'target'; + + expect(() => alignment.save()).to.throw('Relation Type cannot be missing'); + }); + + it('should call EcRepository.save if repo is null', function () { + const stub = sinon.stub(EcRepository, 'save'); + const alignment = new EcAlignment(); + alignment.source = 'source'; + alignment.target = 'target'; + alignment.relationType = 'relationType'; + const success = sinon.spy(); + const failure = sinon.spy(); + const eim = {}; + + alignment.save(success, failure, null, eim); + + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(alignment, success, failure, null, eim)).to.be.true; + + stub.restore(); + }); + + it('should call repo.saveTo if repo is not null', function () { + const repo = { + saveTo: sinon.spy() + }; + const alignment = new EcAlignment(); + alignment.source = 'source'; + alignment.target = 'target'; + alignment.relationType = 'relationType'; + const success = sinon.spy(); + const failure = sinon.spy(); + const eim = {}; + + alignment.save(success, failure, repo, eim); + + expect(repo.saveTo.calledOnce).to.be.true; + expect(repo.saveTo.calledWith(alignment, success, failure, eim)).to.be.true; + }); + }); + + describe('_delete', function () { + it('should call EcRepository.DELETE with correct parameters', function () { + const stub = sinon.stub(EcRepository, 'DELETE'); + const alignment = new EcAlignment(); + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const eim = {}; + + alignment._delete(success, failure, repo, eim); + + expect(stub.calledOnce).to.be.true; + expect(stub.calledWith(alignment, success, failure, repo, eim)).to.be.true; + + stub.restore(); + }); + }); +}); \ No newline at end of file diff --git a/src/test/EcAssertion.test.js b/src/test/EcAssertion.test.js new file mode 100644 index 00000000..0daf161f --- /dev/null +++ b/src/test/EcAssertion.test.js @@ -0,0 +1,93 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcAssertion = require('../org/cass/profile/EcAssertion'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); +const EcPpk = require('../com/eduworks/ec/crypto/EcPpk'); +const Assertion = require('../org/cassproject/schema/cass/profile/Assertion'); + +const expect = chai.expect; + +describe('EcAssertion', function () { + let assertion; + + beforeEach(function () { + assertion = new EcAssertion(); + }); + + describe('equals', function () { + it('should return true if ids are equal', function () { + assertion.id = 'testId'; + const obj = { id: 'testId' }; + expect(assertion.equals(obj)).to.be.true; + }); + + it('should return false if ids are not equal', function () { + assertion.id = 'testId'; + const obj = { id: 'differentId' }; + expect(assertion.equals(obj)).to.be.false; + }); + }); + + describe('decrypt', function () { + it('should decrypt and return a new assertion', async function () { + let subject = EcPpk.generateKey(); + let agent = EcPpk.generateKey(); + sinon.stub(assertion, 'getSubject').resolves(subject.toPk()); + sinon.stub(assertion, 'getAgent').resolves(agent.toPk()); + sinon.stub(assertion, 'getAssertionDate').resolves(1234); + sinon.stub(assertion, 'getExpirationDate').resolves(2345); + sinon.stub(assertion, 'getEvidences').resolves('evidences'); + sinon.stub(assertion, 'getNegative').resolves(true); + sinon.stub(assertion, 'getDecayFunction').resolves('decayFunction'); + + const decryptedAssertion = await assertion.decrypt(); + + expect(decryptedAssertion).to.be.an.instanceof(Assertion); + expect(decryptedAssertion.subject).to.equal(subject.toPk().toPem()); + expect(decryptedAssertion.agent).to.equal(agent.toPk().toPem()); + expect(decryptedAssertion.assertionDate).to.equal(1234); + expect(decryptedAssertion.expirationDate).to.equal(2345); + expect(decryptedAssertion.evidence).to.equal('evidences'); + expect(decryptedAssertion.negative).to.equal(true); + expect(decryptedAssertion.decayFunction).to.equal('decayFunction'); + }); + }); + + describe('get', function () { + it('should call EcRepository.getAs with correct parameters', function () { + const getAsStub = sinon.stub(EcRepository, 'getAs'); + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const eim = {}; + + EcAssertion.get('testId', success, failure, repo, eim); + + expect(getAsStub.calledOnce).to.be.true; + expect(getAsStub.calledWith('testId', sinon.match.instanceOf(EcAssertion), success, failure, repo, eim)).to.be.true; + + getAsStub.restore(); + }); + }); + + describe('search', function () { + it('should call EcRepository.searchAs with correct parameters', function () { + const searchAsStub = sinon.stub(EcRepository, 'searchAs'); + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const query = 'testQuery'; + const paramObj = {}; + const eim = {}; + + EcAssertion.search(repo, query, success, failure, paramObj, eim); + + expect(searchAsStub.calledOnce).to.be.true; + expect(searchAsStub.calledWith(repo, query, sinon.match.func, success, failure, paramObj, eim)).to.be.true; + + searchAsStub.restore(); + }); + }); + + // Add more tests for other methods as needed +}); \ No newline at end of file diff --git a/src/test/EcCompetency.test.js b/src/test/EcCompetency.test.js new file mode 100644 index 00000000..69923d3c --- /dev/null +++ b/src/test/EcCompetency.test.js @@ -0,0 +1,144 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcCompetency = require('../org/cass/competency/EcCompetency'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); +const EcAlignment = require('../org/cass/competency/EcAlignment'); +const EcRollupRule = require('../org/cass/competency/EcRollupRule'); +const EcLevel = require('../org/cass/competency/EcLevel'); +const EcPpk = require('../com/eduworks/ec/crypto/EcPpk'); + +const expect = chai.expect; + +describe('EcCompetency', function () { + let competency; + + beforeEach(function () { + competency = new EcCompetency(); + }); + + it('should initialize with template values', function () { + EcCompetency.template = { '@name': 'Test Competency' }; + competency = new EcCompetency(); + expect(competency.name).to.equal('Test Competency'); + }); + + it('should check equality based on id', function () { + competency.id = 'testId'; + const obj = { id: 'testId' }; + expect(competency.equals(obj)).to.be.true; + }); + + it('should retrieve competency asynchronously', function (done) { + const stub = sinon.stub(EcRepository, 'getAs').callsFake((id, obj, success) => { + success(obj); + }); + + EcCompetency.get('testId', function (result) { + expect(result).to.be.instanceOf(EcCompetency); + stub.restore(); + done(); + }, done); + }); + + it('should retrieve competency synchronously', function () { + const stub = sinon.stub(EcRepository, 'getAs').returns(new EcCompetency()); + + const result = EcCompetency.getBlocking('testId'); + expect(result).to.be.instanceOf(EcCompetency); + stub.restore(); + }); + + it('should search for competencies', function (done) { + const stub = sinon.stub(EcRepository, 'searchAs').callsFake((repo, query, factory, success) => { + success([new EcCompetency()]); + }); + + EcCompetency.search(null, 'query', function (results) { + expect(results).to.be.an('array').that.is.not.empty; + stub.restore(); + done(); + }, done); + }); + + it('should add an alignment', async function () { + const stub = sinon.stub(EcAlignment.prototype, 'save').resolves(); + const target = new EcCompetency(); + const owner = EcPpk.generateKey(); + + const alignment = await competency.addAlignment(target, 'alignmentType', owner, 'serverUrl'); + expect(alignment).to.be.instanceOf(EcAlignment); + stub.restore(); + }); + + it('should search for relationships', function (done) { + const stub = sinon.stub(EcAlignment, 'search').callsFake((repo, query, success) => { + success([new EcAlignment()]); + }); + + competency.relations(null, function (result) { + expect(result).to.be.instanceOf(EcAlignment); + stub.restore(); + done(); + }, done); + }); + + it('should add a level', async function () { + const stub = sinon.stub(EcLevel.prototype, 'save').resolves(); + const owner = EcPpk.generateKey(); + + const level = await competency.addLevel('name', 'description', owner, 'serverUrl'); + expect(level).to.be.instanceOf(EcLevel); + stub.restore(); + }); + + it('should search for levels', function (done) { + const stub = sinon.stub(EcLevel, 'search').callsFake((repo, query, success) => { + success([new EcLevel()]); + }); + + competency.levels(null, function (result) { + expect(result).to.be.instanceOf(EcLevel); + stub.restore(); + done(); + }, done); + }); + + it('should add a rollup rule', async function () { + const stub = sinon.stub(EcRollupRule.prototype, 'save').resolves(); + const owner = EcPpk.generateKey(); + + const rollupRule = await competency.addRollupRule('name', 'description', owner, 'serverUrl'); + expect(rollupRule).to.be.instanceOf(EcRollupRule); + stub.restore(); + }); + + it('should search for rollup rules', function (done) { + const stub = sinon.stub(EcRollupRule, 'search').callsFake((repo, query, success) => { + success([new EcRollupRule()]); + }); + + competency.rollupRules(null, function (result) { + expect(result).to.be.instanceOf(EcRollupRule); + stub.restore(); + done(); + }, done); + }); + + it('should set scope', function () { + competency.setScope('testScope'); + expect(competency.scope).to.equal('testScope'); + }); + + it('should save competency', function (done) { + const stub = sinon.stub(EcRepository, 'save').callsFake((obj, success) => { + success(); + }); + + competency.name = 'testName'; + competency.save(function () { + stub.restore(); + done(); + }, done); + }); + +}); \ No newline at end of file diff --git a/src/test/EcDirectedGraph.test.js b/src/test/EcDirectedGraph.test.js new file mode 100644 index 00000000..d6b4a2a5 --- /dev/null +++ b/src/test/EcDirectedGraph.test.js @@ -0,0 +1,161 @@ +const { expect } = require('chai'); +const EcDirectedGraph = require('../com/eduworks/ec/graph/EcDirectedGraph'); + +describe('EcDirectedGraph', () => { + let graph; + let vertex1, vertex2, vertex3, edge1, edge2; + + beforeEach(() => { + graph = new EcDirectedGraph(); + vertex1 = { equals: (v) => v === vertex1 }; + vertex2 = { equals: (v) => v === vertex2 }; + vertex3 = { equals: (v) => v === vertex3 }; + edge1 = { equals: (e) => e === edge1 }; + edge2 = { equals: (e) => e === edge2 }; + }); + + it('should add vertices', () => { + graph.addVertex(vertex1); + graph.addVertex(vertex2); + expect(graph.getVertexCount()).to.equal(2); + expect(graph.containsVertex(vertex1)).to.be.true; + expect(graph.containsVertex(vertex2)).to.be.true; + }); + + it('should add edges', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.getEdgeCount()).to.equal(1); + expect(graph.containsEdge(edge1)).to.be.true; + }); + + it('should find edges between vertices', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.findEdge(vertex1, vertex2)).to.equal(edge1); + }); + + it('should get neighbors of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.getNeighbors(vertex1)).to.have.members([vertex2, vertex3]); + }); + + it('should get incident edges of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.getIncidentEdges(vertex1)).to.have.members([edge1, edge2]); + }); + + it('should get incident vertices of an edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.getIncidentVertices(edge1)).to.have.members([vertex1, vertex2]); + }); + + it('should remove vertices', () => { + graph.addVertex(vertex1); + graph.addVertex(vertex2); + graph.removeVertex(vertex1); + expect(graph.getVertexCount()).to.equal(1); + expect(graph.containsVertex(vertex1)).to.be.false; + }); + + it('should remove edges', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.removeEdge(edge1); + expect(graph.getEdgeCount()).to.equal(0); + expect(graph.containsEdge(edge1)).to.be.false; + }); + + it('should check if vertices are neighbors', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.isNeighbor(vertex1, vertex2)).to.be.true; + expect(graph.isNeighbor(vertex1, vertex3)).to.be.false; + }); + + it('should check if a vertex is incident to an edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.isIncident(vertex1, edge1)).to.be.true; + expect(graph.isIncident(vertex3, edge1)).to.be.false; + }); + + it('should get the degree of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.degree(vertex1)).to.equal(2); + }); + + it('should get the in-degree of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex3, vertex2); + expect(graph.inDegree(vertex2)).to.equal(2); + }); + + it('should get the out-degree of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.outDegree(vertex1)).to.equal(2); + }); + + it('should get the source of a directed edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.getSource(edge1)).to.equal(vertex1); + }); + + it('should get the destination of a directed edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.getDest(edge1)).to.equal(vertex2); + }); + + it('should get predecessors of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex3, vertex2); + expect(graph.getPredecessors(vertex2)).to.have.members([vertex1,vertex3]); + }); + + it('should get successors of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.getSuccessors(vertex1)).to.have.members([vertex2,vertex3]); + }); + + it('should check if a vertex is a predecessor of another vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.isPredecessor(vertex2, vertex1)).to.be.true; + expect(graph.isPredecessor(vertex1, vertex2)).to.be.false; + }); + + it('should check if a vertex is a successor of another vertex', () => { + graph.addEdge(edge1, vertex2, vertex1); + expect(graph.isSuccessor(vertex2, vertex1)).to.be.true; + expect(graph.isSuccessor(vertex1, vertex2)).to.be.false; + }); + + it('should get the predecessor count of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex3, vertex2); + expect(graph.getPredecessorCount(vertex2)).to.equal(2); + }); + + it('should get the successor count of a vertex', () => { + graph.addEdge(edge1, vertex1, vertex2); + graph.addEdge(edge2, vertex1, vertex3); + expect(graph.getSuccessorCount(vertex1)).to.equal(2); + }); + + it('should check if a vertex is the source of an edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.isSource(vertex1, edge1)).to.be.true; + expect(graph.isSource(vertex2, edge1)).to.be.false; + }); + + it('should check if a vertex is the destination of an edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.isDest(vertex2, edge1)).to.be.true; + expect(graph.isDest(vertex1, edge1)).to.be.false; + }); + + it('should get the opposite vertex of an edge', () => { + graph.addEdge(edge1, vertex1, vertex2); + expect(graph.getOpposite(vertex1, edge1)).to.equal(vertex2); + expect(graph.getOpposite(vertex2, edge1)).to.equal(vertex1); + }); +}); \ No newline at end of file diff --git a/src/test/EcFramework.test.js b/src/test/EcFramework.test.js new file mode 100644 index 00000000..c511730f --- /dev/null +++ b/src/test/EcFramework.test.js @@ -0,0 +1,137 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcFramework = require('../org/cass/competency/EcFramework'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); +const expect = chai.expect; + +describe('EcFramework', function () { + let framework; + + beforeEach(function () { + framework = new EcFramework(); + }); + + it('should initialize with template values if template is set', function () { + EcFramework.template = { "@name": "Test Framework" }; + framework = new EcFramework(); + expect(framework.name).to.equal("Test Framework"); + }); + + it('should return true if IDs match in equals method', function () { + framework.id = "testId"; + const obj = { id: "testId" }; + expect(framework.equals(obj)).to.be.true; + }); + + it('should add competency if not already present', function () { + const competencyId = "testCompetency"; + framework.addCompetency(competencyId); + expect(framework.competency).to.include(competencyId); + }); + + it('should not add duplicate competency', function () { + const competencyId = "testCompetency"; + framework.addCompetency(competencyId); + framework.addCompetency(competencyId); + expect(framework.competency.length).to.equal(1); + }); + + it('should remove competency and associated relations and levels', function (done) { + const competencyId = "testCompetency"; + framework.competency = [competencyId]; + framework.relation = ["relation1"]; + framework.level = ["level1"]; + + sinon.stub(framework, 'removeRelationshipsThatInclude').callsFake((id, i, success) => success()); + sinon.stub(framework, 'removeLevelsThatInclude').callsFake((id, i, success) => success()); + + framework.removeCompetency(competencyId, () => { + expect(framework.competency).to.not.include(competencyId); + done(); + }, done); + }); + + it('should add relation if not already present', function () { + const relationId = "testRelation"; + framework.addRelation(relationId); + expect(framework.relation).to.include(relationId); + }); + + it('should not add duplicate relation', function () { + const relationId = "testRelation"; + framework.addRelation(relationId); + framework.addRelation(relationId); + expect(framework.relation.length).to.equal(1); + }); + + it('should remove relation', function () { + const relationId = "testRelation"; + framework.relation = [relationId]; + framework.removeRelation(relationId); + expect(framework.relation).to.not.include(relationId); + }); + + it('should add level if not already present', function () { + const levelId = "testLevel"; + framework.addLevel(levelId); + expect(framework.level).to.include(levelId); + }); + + it('should not add duplicate level', function () { + const levelId = "testLevel"; + framework.addLevel(levelId); + framework.addLevel(levelId); + expect(framework.level.length).to.equal(1); + }); + + it('should remove level', function () { + const levelId = "testLevel"; + framework.level = [levelId]; + framework.removeLevel(levelId); + expect(framework.level).to.not.include(levelId); + }); + + it('should add rollup rule if not already present', function () { + const rollupRuleId = "testRollupRule"; + framework.addRollupRule(rollupRuleId); + expect(framework.rollupRule).to.include(rollupRuleId); + }); + + it('should not add duplicate rollup rule', function () { + const rollupRuleId = "testRollupRule"; + framework.addRollupRule(rollupRuleId); + framework.addRollupRule(rollupRuleId); + expect(framework.rollupRule.length).to.equal(1); + }); + + it('should remove rollup rule', function () { + const rollupRuleId = "testRollupRule"; + framework.rollupRule = [rollupRuleId]; + framework.removeRollupRule(rollupRuleId); + expect(framework.rollupRule).to.not.include(rollupRuleId); + }); + + it('should save framework if name is not empty', function (done) { + framework.name = "Test Framework"; + const stub = sinon.stub(EcRepository, 'save').callsFake((obj, success) => success()); + framework.save(() => { + expect(EcRepository.save.calledOnce).to.be.true; + stub.restore(); + done(); + }, done); + }); + + it('should not save framework if name is empty', function () { + framework.name = ""; + expect(() => framework.save()).to.throw("Framework Name Cannot be Empty"); + }); + + it('should delete framework', function (done) { + const stub = sinon.stub(EcRepository, 'DELETE').callsFake((obj, success) => success()); + framework._delete(() => { + expect(EcRepository.DELETE.calledOnce).to.be.true; + stub.restore(); + done(); + }, done); + }); +}); \ No newline at end of file diff --git a/src/test/EcLevel.test.js b/src/test/EcLevel.test.js new file mode 100644 index 00000000..0aa634c3 --- /dev/null +++ b/src/test/EcLevel.test.js @@ -0,0 +1,156 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); +const EcLevel = require('../org/cass/competency/EcLevel'); +const EcAlignment = require('../org/cass/competency/EcAlignment'); +const EcPpk = require('../com/eduworks/ec/crypto/EcPpk'); +const EcIdentityManager = require('../org/cassproject/ebac/identity/EcIdentityManager'); + +const { expect } = chai; + +describe('EcLevel', () => { + let sandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + describe('get', () => { + it('should retrieve a level by ID', (done) => { + const id = 'testId'; + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const eim = {}; + + sandbox.stub(EcRepository, 'getAs').callsFake((id, level, successCallback, failureCallback, repo, eim) => { + successCallback(level); + }); + + EcLevel.get(id, success, failure, repo, eim); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + done(); + }); + }); + + describe('getBlocking', () => { + it('should retrieve a level by ID synchronously', () => { + const id = 'testId'; + const repo = {}; + const eim = {}; + + sandbox.stub(EcRepository, 'getAs').returns(new EcLevel()); + + const result = EcLevel.getBlocking(id, repo, eim); + + expect(result).to.be.instanceOf(EcLevel); + }); + }); + + describe('search', () => { + it('should search for levels with a query', (done) => { + const repo = {}; + const query = 'testQuery'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + sandbox.stub(EcRepository, 'searchAs').callsFake((repo, query, levelFactory, successCallback, failureCallback, paramObj, eim) => { + successCallback([new EcLevel()]); + }); + + EcLevel.search(repo, query, success, failure, paramObj, eim); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + done(); + }); + }); + + describe('searchByCompetency', () => { + it('should search for levels by competency ID', (done) => { + const repo = {}; + const competencyId = 'testCompetencyId'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + sandbox.stub(EcLevel, 'search').callsFake((repo, query, successCallback, failureCallback, paramObj, eim) => { + successCallback([new EcLevel()]); + }); + + EcLevel.searchByCompetency(repo, competencyId, success, failure, paramObj, eim); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + done(); + }); + + it('should call failure callback if no competency ID is provided', () => { + const repo = {}; + const competencyId = ''; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + EcLevel.searchByCompetency(repo, competencyId, success, failure, paramObj, eim); + + expect(failure.calledOnce).to.be.true; + expect(success.called).to.be.false; + }); + }); + + describe('addRelationship', () => { + it('should add a relationship between levels', async () => { + const level = new EcLevel(); + level.id = 'sourceId'; + const targetLevel = new EcLevel(); + targetLevel.id = 'targetId'; + const alignmentType = 'testType'; + const identity = EcPpk.generateKey(); + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = new EcRepository(); + await repo.init(process.env.CASS_LOOPBACK || 'http://localhost/api/'); + const eim = EcIdentityManager.default; + + let a = await level.addRelationship(targetLevel, alignmentType, identity, success, failure, repo, eim); + + expect(a.source).to.equal(level.id); + expect(a.target).to.equal(targetLevel.id); + expect(a.relationType).to.equal(alignmentType); + }); + }); + + describe('setName', () => { + it('should set the name of the level', () => { + const level = new EcLevel(); + const name = 'testName'; + + level.setName(name); + + expect(level.name).to.equal(name); + }); + }); + + describe('setDescription', () => { + it('should set the description of the level', () => { + const level = new EcLevel(); + const description = 'testDescription'; + + level.setDescription(description); + + expect(level.description).to.equal(description); + }); + }); + +}); \ No newline at end of file diff --git a/src/test/EcRemote.test.js b/src/test/EcRemote.test.js new file mode 100644 index 00000000..aa2996cc --- /dev/null +++ b/src/test/EcRemote.test.js @@ -0,0 +1,51 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcRemote = require('../com/eduworks/ec/remote/EcRemote'); + +const { expect } = chai; +if ((typeof Cypress !== 'undefined') && Cypress != null && Cypress.env != null) + process.env.CASS_LOOPBACK = Cypress.env('CASS_LOOPBACK'); + +describe('EcRemote', function () { + describe('postExpectingObject', function () { + it('should call postInner with correct parameters', async function () { + const server = process.env.CASS_LOOPBACK || 'http://localhost/api/'; + const service = 'ping'; + const fd = new FormData(); + const success = sinon.spy(); + const failure = sinon.spy(); + + await EcRemote.postExpectingObject(server, service, fd, success, failure); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + }); + }); + + describe('getExpectingObject', function () { + it('should call fetch with correct URL', async function () { + const server = process.env.CASS_LOOPBACK || 'http://localhost/api/'; + const service = 'ping'; + const success = sinon.spy(); + const failure = sinon.spy(); + + await EcRemote.getExpectingObject(server, service, success, failure); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + }); + }); + + describe('_delete', function () { + it('should call fetch with DELETE method', async function () { + const url = (process.env.CASS_LOOPBACK || 'http://localhost/api/')+'ping'; + const success = sinon.spy(); + const failure = sinon.spy(); + + await EcRemote._delete(url, null, success, failure); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + }); + }); +}); \ No newline at end of file diff --git a/src/test/EcRollupRule.test.js b/src/test/EcRollupRule.test.js new file mode 100644 index 00000000..38377c05 --- /dev/null +++ b/src/test/EcRollupRule.test.js @@ -0,0 +1,89 @@ +const chai = require('chai'); +const sinon = require('sinon'); +const EcRepository = require('../org/cassproject/ebac/repository/EcRepository'); +const EcRollupRule = require('../org/cass/competency/EcRollupRule'); +const expect = chai.expect; + +describe('EcRollupRule', function () { + describe('get', function () { + it('should retrieve a rollup rule from the server', function (done) { + const id = 'testId'; + const success = sinon.spy(); + const failure = sinon.spy(); + const repo = {}; + const eim = {}; + + sinon.stub(EcRepository, 'getAs').callsFake((id, obj, successCallback, failureCallback, repo, eim) => { + successCallback(obj); + }); + + EcRollupRule.get(id, success, failure, repo, eim); + + expect(success.calledOnce).to.be.true; + expect(failure.called).to.be.false; + EcRepository.getAs.restore(); + done(); + }); + }); + + describe('getBlocking', function () { + it('should retrieve a rollup rule from the server without callbacks', function () { + const id = 'testId'; + const repo = {}; + const eim = {}; + + sinon.stub(EcRepository, 'getAs').returns(new EcRollupRule()); + + const result = EcRollupRule.getBlocking(id, repo, eim); + + expect(result).to.be.an.instanceof(EcRollupRule); + EcRepository.getAs.restore(); + }); + }); + + describe('search', function () { + it('should search for rollup rules with a query', function (done) { + const repo = {}; + const query = 'testQuery'; + const success = sinon.spy(); + const failure = sinon.spy(); + const paramObj = {}; + const eim = {}; + + sinon.stub(EcRepository, 'searchAs').callsFake((repo, query, objFactory, successCallback, failureCallback, paramObj, eim) => { + successCallback([objFactory()]); + }); + + EcRollupRule.search(repo, query, success, failure, paramObj, eim); + + expect(success.calledOnce).to.be.true; + expect(success.args[0][0][0]).to.be.an.instanceof(EcRollupRule); + expect(failure.called).to.be.false; + EcRepository.searchAs.restore(); + done(); + }); + }); + + describe('setName', function () { + it('should set the name of the rollup rule', function () { + const rule = new EcRollupRule(); + const name = 'Test Name'; + + rule.setName(name); + + expect(rule.name).to.equal(name); + }); + }); + + describe('setDescription', function () { + it('should set the description of the rollup rule', function () { + const rule = new EcRollupRule(); + const description = 'Test Description'; + + rule.setDescription(description); + + expect(rule.description).to.equal(description); + }); + }); + +}); \ No newline at end of file