diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..11b58b88 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,84 @@ +## Tests + +To be merged, pull requests **MUST** include tests for any new features or bug fixes. + +The tests are located in the test/ directory. The structure of the directory is as follows: +- `api/` - End-to-end tests that require running a local test node. +- `unit/` - Unit tests that DO NOT require running a test node. +- `common/` - Contains stub objects and utilities for the tests. +- `node.js` - Package for making requests to the local test node. +- `config.json` - Configuration file to run a local test node; copy `config.default.json` +- `genesisBlock.json` - Genesis block data. +- `genesisDelegates.json` - Genesis delegate accounts. +- `genesisPasses.json` - Passphrases for the genesis accounts. + +All tests inside `api/` and `unit/` should mirror (as much as possible) the structure of the project. For example, unit tests for the `modules/blocks.js` module should be located in the `test/unit/modules/blocks.js` file. + +### Commands + +To run a single test file, use the following command: + +``` +npm run test:single test/path/to/the/test.js +``` + +If you have changed any common files (e.g., files inside `test/common/`, `test/node.js` package, etc.), consider running all tests: + +``` +npm run test:all +``` + +### Convention for tests + +Since we use the Chai package for assertions, we have a few rules for consistency: + +- **Use proper English grammar in assertions** + + ```js + // ❌ + expect({}).to.be.a('object'); + // ✅ + expect(true).to.be.an('object'); + ``` + +- **Use `to.be.true` instead of `to.be.ok`** + + Boolean values should be strictly asserted: + + ```js + // ❌ + expect(true).to.be.ok; + // ✅ + expect(true).to.be.true; + ``` + +- **Use `to.not` instead of `not.to`** + + Prefer `not.to` for convention: + + ```js + // ❌ + expect(true).to.not.equal(false); + // ✅ + expect(true).not.to.be.false; + ``` + +- **Use `.equal()` instead of `.eql()` for `===`** + + Use `.eql()` **only** for deep assertion. + + ```js + // ❌ + expect(true).to.eql(true); + // ✅ + expect(true).to.be.true; + ``` + +- **Use parentheses for functions and methods in `describe` names** + + ```js + // ❌ + describe(`functionName`, () => { /* ... */ }) + // ✅ + describe(`functionName()`, () => { /* ... */ }) + ``` diff --git a/helpers/accounts.js b/helpers/accounts.js index f6cf1eae..2f2438d8 100644 --- a/helpers/accounts.js +++ b/helpers/accounts.js @@ -8,18 +8,23 @@ var bignum = require('./bignum.js'); var sodium = require('sodium-browserify-tweetnacl'); let Mnemonic = require('bitcore-mnemonic'); +const { isPublicKey } = require('./publicKey.js'); var accounts = {}; /** - * Gets address by public + * Gets address by public key * @private * @implements {crypto.createHash} * @implements {bignum.fromBuffer} - * @param {publicKey} publicKey - * @return {address} address + * @param {string} publicKey + * @return {string} The address matching the public key, or an empty string if an invalid public key was provided */ accounts.getAddressByPublicKey = function (publicKey) { + if (!isPublicKey(publicKey)) { + return ''; + } + var publicKeyHash = crypto.createHash('sha256').update(publicKey, 'hex').digest(); var temp = Buffer.alloc(8); diff --git a/helpers/ed.js b/helpers/ed.js index 71622191..3f68c7c1 100644 --- a/helpers/ed.js +++ b/helpers/ed.js @@ -14,6 +14,24 @@ var crypto = require('crypto'); */ var ed = {}; +/** + * Returns whether the passphrase is valid mnemonic + * @param {string} passphrase passhraase to test + * @returns {boolean} + */ +ed.isValidPassphrase = function(passphrase) { + return mnemonic.isValid(passphrase, mnemonic.Words.ENGLISH); +} + +/** + * Generates a new passphrase + * @returns {string} passphrase + */ +ed.generatePassphrase = function() { + const secretMnemonic = new mnemonic(mnemonic.Words.ENGLISH); + return secretMnemonic.phrase; +} + /** * Creates a hash based on a passphrase. * @param {string} passPhrase diff --git a/helpers/publicKey.js b/helpers/publicKey.js new file mode 100644 index 00000000..7e3da8f9 --- /dev/null +++ b/helpers/publicKey.js @@ -0,0 +1,8 @@ +/** + * Tests if the provided value is a valid public key + * @param {any} str string to test + * @returns {boolean} whether the string can be considered a public key + */ +exports.isPublicKey = (value) => { + return typeof value === "string" && Buffer.from(value, "hex").length === 32; +}; diff --git a/helpers/request-limiter.js b/helpers/request-limiter.js index 2c537d78..0cff8a33 100644 --- a/helpers/request-limiter.js +++ b/helpers/request-limiter.js @@ -24,7 +24,9 @@ var defaults = { * @param {Object} [limits] * @return {Object} max, delayMs, delayAfter, windowMs */ -function applyLimits (limits) { +function applyLimits(config) { + const limits = config ?? defaults; + if (typeof limits === 'object') { const settings = { max: Math.floor(limits.max) || defaults.max, @@ -35,7 +37,7 @@ function applyLimits (limits) { windowMs: Math.floor(limits.windowMs) || defaults.windowMs }; - if (!limits.max) { + if (!limits.delayAfter) { settings.skip = skip; } diff --git a/helpers/sequence.js b/helpers/sequence.js index 267c3b03..6aec8ae1 100644 --- a/helpers/sequence.js +++ b/helpers/sequence.js @@ -18,15 +18,20 @@ function Sequence (config) { _default = extend(_default, config); var self = this; this.sequence = []; + this.isTicking = false; + + this.nextSequenceTick = function () { + if (!self.sequence.length) { + self.isTicking = false; + return; + } - setImmediate(function nextSequenceTick () { if (_default.onWarning && self.sequence.length >= _default.warningLimit) { _default.onWarning(self.sequence.length, _default.warningLimit); } - self.__tick(function () { - setTimeout(nextSequenceTick, 3); - }); - }); + + self.__tick(self.nextSequenceTick); + }; } /** @@ -68,6 +73,11 @@ Sequence.prototype.add = function (worker, args, done) { task.args = args; } this.sequence.push(task); + + if (!this.isTicking) { + this.isTicking = true; + setImmediate(this.nextSequenceTick); + } } }; diff --git a/helpers/z_schema.js b/helpers/z_schema.js index 11235c36..9b71ac64 100644 --- a/helpers/z_schema.js +++ b/helpers/z_schema.js @@ -23,6 +23,7 @@ var ip = require('neoip'); * @return {Boolean} True if the format is valid */ var z_schema = require('z-schema'); +const { isPublicKey } = require('./publicKey.js'); z_schema.registerFormat('id', function (str) { if (str.length === 0) { @@ -62,13 +63,7 @@ z_schema.registerFormat('publicKey', function (str) { return true; } - try { - var publicKey = Buffer.from(str, 'hex'); - - return publicKey.length === 32; - } catch (e) { - return false; - } + return isPublicKey(str) }); z_schema.registerFormat('csv', function (str) { diff --git a/logic/account.js b/logic/account.js index 2b4fc3d1..6ec2d164 100644 --- a/logic/account.js +++ b/logic/account.js @@ -509,9 +509,7 @@ Account.prototype.verifyPublicKey = function (publicKey) { throw 'Invalid public key, must be 64 characters long'; } // Check format - try { - Buffer.from(publicKey, 'hex'); - } catch (e) { + if (!/^[0-9A-Fa-f]+$/.test(publicKey)) { throw 'Invalid public key, must be a hex string'; } } @@ -680,7 +678,7 @@ Account.prototype.merge = function (address, diff, cb) { // Normalize address address = String(address).toUpperCase(); - this.editable.forEach(function (value) { + for (const value of this.editable) { var val, i; if (diff[value] !== undefined) { @@ -691,7 +689,9 @@ Account.prototype.merge = function (address, diff, cb) { break; case Number: if (isNaN(trueValue) || trueValue === Infinity) { - return setImmediate(cb, 'Encountered unsane number: ' + trueValue); + const error = new Error(`Encountered unsafe number: ${trueValue}`) + library.logger.error(error.stack, diff); + return setImmediate(cb, error.message); } else if (Math.abs(trueValue) === trueValue && trueValue !== 0) { update[value] = knex.raw('?? + ?', [value, Math.floor(trueValue)]) @@ -800,7 +800,7 @@ Account.prototype.merge = function (address, diff, cb) { break; } } - }); + } var sqles = []; diff --git a/modules/accounts.js b/modules/accounts.js index 4fd8cc7f..8c0c1bab 100644 --- a/modules/accounts.js +++ b/modules/accounts.js @@ -95,6 +95,10 @@ __private.newAccount = function (publicKey, cb) { * @return {setImmediateCallback} As per logic new|current account data object. */ __private.openAccount = function (secret, cb) { + if (!library.ed.isValidPassphrase(secret)) { + return setImmediate(cb, `Mnemonic string is invalid: ${secret}`); + } + var hash = library.ed.createPassPhraseHash(secret); var keypair = library.ed.makeKeypair(hash); var publicKey = keypair.publicKey.toString('hex'); @@ -143,14 +147,36 @@ Accounts.prototype.generateAddressByPublicKey = function (publicKey) { /** * Gets account information, calls logic.account.get(). - * @implements module:accounts#Account~get + * @overload + * @param {Object} filter - Contains publicKey. + * @param {Array} fields - Fields to get. + * @param {function} cb - Callback function. + */ + +/** + * Gets account information, calls logic.account.get(). + * @overload * @param {Object} filter - Contains publicKey. - * @param {function} fields - Fields to get. * @param {function} cb - Callback function. */ + +/** + * Gets account information, calls logic.account.get(). + * @implements module:accounts#Account~get + * @param {Object} filter - Contains publicKey. + * @param {Array | function} fields - Fields to get or callback function. + * @param {function} [cb] - Callback function. + */ Accounts.prototype.getAccount = function (filter, fields, cb) { if (filter.publicKey) { - filter.address = self.generateAddressByPublicKey(filter.publicKey); + try { + filter.address = self.generateAddressByPublicKey(filter.publicKey); + } catch (error) { + if (typeof fields === 'function') { + return setImmediate(fields, error); + } + return setImmediate(cb, error); + } delete filter.publicKey; } @@ -189,10 +215,6 @@ Accounts.prototype.setAccountAndGet = function (data, cb) { } } - if (!address) { - err = 'Invalid public key'; - } - if (err) { if (typeof cb === 'function') { return setImmediate(cb, err); @@ -230,10 +252,6 @@ Accounts.prototype.mergeAccountAndGet = function (data, cb) { } } - if (!address) { - err = 'Invalid public key'; - } - if (err) { if (typeof cb === 'function') { return setImmediate(cb, err); diff --git a/modules/cache.js b/modules/cache.js index 0ed99575..91f47d35 100644 --- a/modules/cache.js +++ b/modules/cache.js @@ -44,18 +44,22 @@ Cache.prototype.isReady = function () { * @param {Function} cb * @return {Function} cb */ -Cache.prototype.getJsonForKey = function (key, cb) { +Cache.prototype.getJsonForKey = async function (key, cb) { if (!self.isConnected()) { return cb(errorCacheDisabled); } - client.get(key) - .then((value) => { - // parsing string to json - return cb(null, JSON.parse(value)); - }) - .catch((err) => { - return cb(err, key); - }); + + let parsedValue; + + try { + const value = await client.get(key); + parsedValue = JSON.parse(value); + } catch (err) { + cb(err, key); + return; + } + + cb(null, parsedValue); }; /** @@ -64,19 +68,27 @@ Cache.prototype.getJsonForKey = function (key, cb) { * @param {Object} value * @param {Function} cb */ -Cache.prototype.setJsonForKey = function (key, value, cb) { +Cache.prototype.setJsonForKey = async function (key, value, cb) { if (!self.isConnected()) { - return cb(errorCacheDisabled); + if (typeof cb === 'function') { + cb(errorCacheDisabled); + } + return; } - // redis calls toString on objects, which converts it to object [object] so calling stringify before saving - client.set(key, JSON.stringify(value)) - .then((res) => { - cb(null, res); - }) - .catch((err) => { - cb(err, value); - }); + let res; + try { + // redis calls toString on objects, which converts it to object [object] so calling stringify before saving + res = await client.set(key, JSON.stringify(value)) + } catch (err) { + if (typeof cb === 'function') { + cb(err, value); + } + } + + if (typeof cb === 'function') { + cb(null, res); + } }; /** diff --git a/modules/delegates.js b/modules/delegates.js index 02e3e1c7..7a6ceb0a 100644 --- a/modules/delegates.js +++ b/modules/delegates.js @@ -870,7 +870,7 @@ Delegates.prototype.shared = { modules.accounts.getAccounts({ address: { $in: addresses }, - sort: 'balance' + sort: { balance: -1 } }, ['address', 'balance', 'username', 'publicKey'], function (err, rows) { if (err) { return setImmediate(cb, err); diff --git a/package-lock.json b/package-lock.json index 2378bbbb..8833b296 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,13 +15,13 @@ "bitcore-mnemonic": "=10.5.3", "body-parser": "=1.20.3", "bytebuffer": "=5.0.1", - "change-case": "=5.4.4", + "change-case": "^4.1.2", "colors": "=1.4.0", "commander": "=12.1.0", "compression": "=1.7.5", "cors": "=2.8.5", "ejs": "=3.1.10", - "execa": "^9.5.1", + "execa": "^5.1.1", "express": "=4.21.1", "express-domain-middleware": "=0.1.0", "express-query-int": "=3.0.0", @@ -49,10 +49,11 @@ "unzipper": "^0.12.3", "valid-url": "=1.0.9", "validator.js": "=2.0.4", + "why-is-node-running": "^2.3.0", "z-schema": "=6.0.2" }, "devDependencies": { - "chai": "^5.1.2", + "chai": "^4.3.10", "chai-bignumber": "^3.1.0", "eslint-config-google": "^0.14.0", "eslint-formatter-codeframe": "^7.32.1", @@ -1298,22 +1299,6 @@ "@redis/client": "^1.0.0" } }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==" - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1715,6 +1700,15 @@ "node": ">=10.0.0" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -2112,6 +2106,15 @@ "node": ">=6" } }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2141,6 +2144,16 @@ } ] }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -2154,19 +2167,21 @@ } }, "node_modules/chai": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", - "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" }, "engines": { - "node": ">=12" + "node": ">=4" } }, "node_modules/chai-bignumber": { @@ -2175,22 +2190,25 @@ "integrity": "sha512-omxEc80jAU+pZwRmoWr3aEzeLad4JW3iBhLRQlgISvghBdIxrMT7mVAGsDz4WSyCkKowENshH2j9OABAhld7QQ==", "dev": true }, - "node_modules/chai/node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "node_modules/chai/node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/chai/node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4" } }, "node_modules/chalk": { @@ -2215,9 +2233,23 @@ "dev": true }, "node_modules/change-case": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", - "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } }, "node_modules/char-regex": { "version": "1.0.2", @@ -2238,12 +2270,15 @@ } }, "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { - "node": ">= 16" + "node": "*" } }, "node_modules/chloride-test": { @@ -2494,6 +2529,16 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2747,6 +2792,15 @@ "node": ">=0.3.1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3331,63 +3385,27 @@ "dev": true }, "node_modules/execa": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.1.tgz", - "integrity": "sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": "^18.19.0 || >=20.5.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -3534,31 +3552,6 @@ "reusify": "^1.0.4" } }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3931,6 +3924,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -3958,26 +3960,11 @@ } }, "node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4566,6 +4553,15 @@ "he": "bin/he" } }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/hexoid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", @@ -4633,11 +4629,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/human-signals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "engines": { - "node": ">=18.18.0" + "node": ">=10.17.0" } }, "node_modules/iconv-lite": { @@ -4945,7 +4941,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -5840,10 +5835,21 @@ } }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", - "dev": true + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } }, "node_modules/lru-cache": { "version": "5.1.1", @@ -5997,6 +6003,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "node_modules/method-override": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", @@ -6070,6 +6081,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -6327,6 +6346,15 @@ "node": ">=16" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-addon-api": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", @@ -6547,29 +6575,14 @@ } }, "node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" + "path-key": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/npm/node_modules/@isaacs/cliui": { @@ -9429,6 +9442,20 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -9555,6 +9582,15 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9594,17 +9630,6 @@ "node": ">= 18" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -9622,6 +9647,24 @@ "node": ">= 0.8" } }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9703,12 +9746,12 @@ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { - "node": ">= 14.16" + "node": "*" } }, "node_modules/pg": { @@ -10039,20 +10082,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-ms": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -10545,6 +10574,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -10655,11 +10694,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sinon": { "version": "19.0.2", @@ -10694,6 +10737,15 @@ "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", "dev": true }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/socket.io": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", @@ -10912,6 +10964,11 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -11037,14 +11094,11 @@ } }, "node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/strip-json-comments": { @@ -11268,8 +11322,7 @@ "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/tweetnacl": { "version": "1.0.3", @@ -11369,17 +11422,6 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -11486,6 +11528,22 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -11610,6 +11668,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -11804,17 +11877,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/z-schema": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-6.0.2.tgz", diff --git a/package.json b/package.json index 617a90b1..36731424 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "node app.js", "start:testnet": "node app.js --config test/config.json --genesis test/genesisBlock.json", "test:full": "npx grunt test --verbose", - "test:single": "npx mocha", + "test:single": "npx mocha --trace-uncaught", "test:fast": "npx mocha --exclude test/unit/sql/blockRewards.js --exclude test/api/delegates.js --exclude test/api/peer.transactions.stress.js --exclude test/api/peer.transactions.votes.js test/unit/**/* test/api/**/*", "test:all": "npx mocha test/unit/**/* test/api/**/*", "eslint": "npx grunt eslint-nofix --verbose", @@ -43,13 +43,13 @@ "bitcore-mnemonic": "=10.5.3", "body-parser": "=1.20.3", "bytebuffer": "=5.0.1", - "change-case": "=5.4.4", + "change-case": "^4.1.2", "colors": "=1.4.0", "commander": "=12.1.0", "compression": "=1.7.5", "cors": "=2.8.5", "ejs": "=3.1.10", - "execa": "^9.5.1", + "execa": "^5.1.1", "express": "=4.21.1", "express-domain-middleware": "=0.1.0", "express-query-int": "=3.0.0", @@ -80,7 +80,7 @@ "z-schema": "=6.0.2" }, "devDependencies": { - "chai": "^5.1.2", + "chai": "^4.3.10", "chai-bignumber": "^3.1.0", "eslint-config-google": "^0.14.0", "eslint-formatter-codeframe": "^7.32.1", diff --git a/test/api/accounts.js b/test/api/accounts.js index fd613b93..26d30add 100644 --- a/test/api/accounts.js +++ b/test/api/accounts.js @@ -13,7 +13,7 @@ describe('POST /api/accounts/open', function () { openAccount({ secret: node.iAccount.password }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -34,7 +34,7 @@ describe('POST /api/accounts/open', function () { openAccount({ secret: account.password }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(account.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -51,7 +51,7 @@ describe('POST /api/accounts/open', function () { it('using empty json should fail', function (done) { openAccount({}, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Missing required property: secret'); done(); @@ -60,7 +60,7 @@ describe('POST /api/accounts/open', function () { it('using invalid json should fail', function (done) { openAccount('{\'invalid\'}', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Missing required property: secret'); done(); @@ -71,7 +71,7 @@ describe('POST /api/accounts/open', function () { openAccount({ secret: '' }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); done(); @@ -86,7 +86,7 @@ describe('POST /api/accounts/open', function () { openAccount({ secret: data }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('API error: request entity too large'); done(); }); @@ -100,7 +100,7 @@ describe('GET /api/accounts/getBalance?address=', function () { it('using known address should be ok', function (done) { getBalance(node.gAccount.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('balance').that.is.a('string'); node.expect(res.body).to.have.property('unconfirmedBalance').that.is.a('string'); node.expect(res.body.balance).to.equal(res.body.unconfirmedBalance); @@ -110,7 +110,7 @@ describe('GET /api/accounts/getBalance?address=', function () { it('using unknown address should be ok', function (done) { getBalance(account.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('balance').that.is.a('string'); node.expect(res.body).to.have.property('unconfirmedBalance').that.is.a('string'); node.expect(res.body.balance).to.equal(res.body.unconfirmedBalance); @@ -120,7 +120,7 @@ describe('GET /api/accounts/getBalance?address=', function () { it('using invalid address should fail', function (done) { getBalance('thisIsNOTAnAdamantAddress', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Object didn\'t pass validation for format address: thisIsNOTAnAdamantAddress'); done(); }); @@ -128,9 +128,9 @@ describe('GET /api/accounts/getBalance?address=', function () { it('using empty address should fail', function (done) { getBalance('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); - node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); + node.expect(res.body.error).to.contain("Object didn't pass validation for format address"); done(); }); }); @@ -143,7 +143,7 @@ describe('GET /api/accounts/getPublicKey?address=', function () { it('using known address should be ok', function (done) { getPublicKey(node.iAccount.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('publicKey').to.equal(node.iAccount.publicKey); done(); }); @@ -151,7 +151,7 @@ describe('GET /api/accounts/getPublicKey?address=', function () { it('using unknown address should be ok', function (done) { getPublicKey(account.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.contain('Account not found'); done(); }); @@ -159,7 +159,7 @@ describe('GET /api/accounts/getPublicKey?address=', function () { it('using invalid address should fail', function (done) { getPublicKey('thisIsNOTAnAdamantAddress', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.contain('Object didn\'t pass validation for format address: thisIsNOTAnAdamantAddress'); done(); }); @@ -167,9 +167,9 @@ describe('GET /api/accounts/getPublicKey?address=', function () { it('using empty address should fail', function (done) { getPublicKey('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); - node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); + node.expect(res.body.error).to.contain("Object didn't pass validation for format address"); done(); }); }); @@ -184,7 +184,7 @@ describe('POST /api/accounts/generatePublicKey', function () { generatePublicKey({ secret: node.iAccount.password }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('publicKey').to.equal(node.iAccount.publicKey); done(); }); @@ -194,7 +194,7 @@ describe('POST /api/accounts/generatePublicKey', function () { generatePublicKey({ secret: account.password }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('publicKey').to.equal(account.publicKey.toString('hex')); done(); }); @@ -202,7 +202,7 @@ describe('POST /api/accounts/generatePublicKey', function () { it('using empty json should fail', function (done) { generatePublicKey({}, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Missing required property: secret'); done(); @@ -211,7 +211,7 @@ describe('POST /api/accounts/generatePublicKey', function () { it('using invalid json should fail', function (done) { generatePublicKey('{\'invalid\'}', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Missing required property: secret'); done(); @@ -222,7 +222,7 @@ describe('POST /api/accounts/generatePublicKey', function () { generatePublicKey({ secret: '' }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); done(); @@ -237,7 +237,7 @@ describe('GET /accounts', function () { it('using known address should be ok', function (done) { getAccounts('address=' + node.iAccount.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -254,7 +254,7 @@ describe('GET /accounts', function () { it('using known address and empty publicKey should be ok', function (done) { getAccounts('address=' + node.iAccount.address + '&publicKey=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -271,7 +271,7 @@ describe('GET /accounts', function () { it('using known lowercase address should be ok', function (done) { getAccounts('address=' + node.iAccount.address.toLowerCase(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -288,7 +288,7 @@ describe('GET /accounts', function () { it('using unknown address should fail', function (done) { getAccounts('address=' + account.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Account not found'); done(); }); @@ -296,7 +296,7 @@ describe('GET /accounts', function () { it('using invalid address should fail', function (done) { getAccounts('address=' + 'thisIsNOTAnAdamantAddress', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Object didn\'t pass validation for format address: thisIsNOTAnAdamantAddress'); done(); @@ -305,16 +305,16 @@ describe('GET /accounts', function () { it('using empty address should fail', function (done) { getAccounts('address=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); - node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); + node.expect(res.body.error).to.contain("Object didn't pass validation for format address"); done(); }); }); it('using known publicKey should be ok', function (done) { getAccounts('publicKey=' + node.iAccount.publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -331,15 +331,15 @@ describe('GET /accounts', function () { it('using known publicKey and empty address should fail', function (done) { getAccounts('publicKey=' + node.iAccount.publicKey + '&address=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error').to.eql('String is too short (0 chars), minimum 1'); + node.expect(res.body).to.have.property('success').to.be.false; + node.expect(res.body).to.have.property('error').to.contain("Object didn't pass validation for format address"); done(); }); }); it('using unknown publicKey should fail', function (done) { getAccounts('publicKey=' + account.publicKey.toString('hex'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Account not found'); done(); }); @@ -347,7 +347,7 @@ describe('GET /accounts', function () { it('using invalid publicKey should fail', function (done) { getAccounts('publicKey=' + 'thisIsNOTAnAdamantAccountPublicKey', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Object didn\'t pass validation for format publicKey: thisIsNOTAnAdamantAccountPublicKey'); done(); @@ -356,7 +356,7 @@ describe('GET /accounts', function () { it('using invalid publicKey (integer) should fail', function (done) { getAccounts('publicKey=' + '123', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Expected type string but found type integer'); done(); @@ -365,7 +365,7 @@ describe('GET /accounts', function () { it('using empty publicKey should fail', function (done) { getAccounts('publicKey=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Missing required property: address or publicKey'); done(); @@ -374,16 +374,16 @@ describe('GET /accounts', function () { it('using empty publicKey and address should fail', function (done) { getAccounts('publicKey=&address=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); - node.expect(res.body.error).to.contain('String is too short (0 chars), minimum 1'); + node.expect(res.body.error).to.contain("Object didn't pass validation for format address"); done(); }); }); it('using known address and matching publicKey should be ok', function (done) { getAccounts('address=' + node.iAccount.address + '&publicKey=' + node.iAccount.publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('address').to.equal(node.iAccount.address); node.expect(res.body.account).to.have.property('unconfirmedBalance').that.is.a('string'); @@ -400,7 +400,7 @@ describe('GET /accounts', function () { it('using known address and not matching publicKey should fail', function (done) { getAccounts('address=' + node.iAccount.address + '&publicKey=' + account.publicKey.toString('hex'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error).to.contain('Account publicKey does not match address'); done(); diff --git a/test/api/blocks.js b/test/api/blocks.js index 69c84a0b..dc1ebfda 100644 --- a/test/api/blocks.js +++ b/test/api/blocks.js @@ -34,7 +34,7 @@ describe('GET /api/blocks/getEpoch', function () { describe('GET /api/blocks/getHeight', function () { it('should be ok', function (done) { node.get('/api/blocks/getHeight', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; if (res.body.success && res.body.height != null) { node.expect(res.body).to.have.property('height').to.be.above(0); block.blockHeight = res.body.height; @@ -51,7 +51,7 @@ describe('GET /api/blocks/getHeight', function () { describe('GET /api/blocks/getFee', function () { it('should be ok', function (done) { node.get('/api/blocks/getFee', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fee'); node.expect(res.body.fee).to.equal(node.fees.transactionFee); done(); @@ -62,7 +62,7 @@ describe('GET /api/blocks/getFee', function () { describe('GET /api/blocks/getfees', function () { it('should be ok', function (done) { node.get('/api/blocks/getFees', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fees'); node.expect(res.body.fees.send).to.equal(node.fees.transactionFee); node.expect(res.body.fees.vote).to.equal(node.fees.voteFee); @@ -78,7 +78,7 @@ describe('GET /api/blocks/getfees', function () { describe('GET /api/blocks/getNethash', function () { it('should be ok', function (done) { node.get('/api/blocks/getNethash', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('nethash').to.be.a('string'); node.expect(res.body.nethash).to.equal(node.config.nethash); done(); @@ -116,7 +116,7 @@ describe('GET /api/blocks/getSupply', function () { describe('GET /api/blocks/getStatus', function () { it('should be ok', function (done) { node.get('/api/blocks/getStatus', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('broadhash').to.be.a('string'); node.expect(res.body).to.have.property('epoch').to.be.a('string'); node.expect(res.body).to.have.property('height').to.be.a('number'); @@ -133,11 +133,6 @@ describe('GET /api/blocks/getStatus', function () { describe('GET /blocks (cache)', function () { var cache; - before(function (done) { - node.config.cacheEnabled = true; - done(); - }); - before(function (done) { modulesLoader.initCache(function (err, __cache) { cache = __cache; @@ -164,9 +159,8 @@ describe('GET /blocks (cache)', function () { url = '/api/blocks?'; params = 'height=' + block.blockHeight; node.get(url + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); - node.expect(res.body).to.have.property('count').to.equal(1); var response = res.body; cache.getJsonForKey(url + params, function (err, res) { node.expect(err).to.not.exist; @@ -184,29 +178,28 @@ describe('GET /blocks (cache)', function () { node.expect(res.body).to.have.property('success').to.not.be.ok; cache.getJsonForKey(url + params, function (err, res) { node.expect(err).to.not.exist; - node.expect(res).to.eql(null); + node.expect(res).to.be.null; done(); }); }); }); - it('should remove entry from cache on new block', function (done) { + it('should update entry from cache on new block', function (done) { var url, params; url = '/api/blocks?'; params = 'height=' + block.blockHeight; node.get(url + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); - node.expect(res.body).to.have.property('count').to.equal(1); var response = res.body; - cache.getJsonForKey(url + params, function (err, res) { + cache.getJsonForKey(url + params, function (err, cachedResponseBefore) { node.expect(err).to.not.exist; - node.expect(res).to.eql(response); + node.expect(cachedResponseBefore).to.eql(response); node.onNewBlock(function (err) { node.expect(err).to.not.exist; - cache.getJsonForKey(url + params, function (err, res) { + cache.getJsonForKey(url + params, function (err, cachedResponseAfter) { node.expect(err).to.not.exist; - node.expect(res).to.eql(null); + node.expect(cachedResponseAfter).not.to.eql(cachedResponseBefore); done(); }); }); @@ -222,9 +215,8 @@ describe('GET /blocks', function () { it('using height should be ok', function (done) { getBlocks('height=' + block.blockHeight, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); - node.expect(res.body).to.have.property('count').to.equal(1); node.expect(res.body.blocks.length).to.equal(1); node.expect(res.body.blocks[0]).to.have.property('previousBlock'); node.expect(res.body.blocks[0]).to.have.property('totalAmount'); @@ -248,8 +240,7 @@ describe('GET /blocks', function () { } getBlocks('height=' + 10, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('count'); + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); node.expect(res.body.blocks.length).to.equal(1); node.expect(res.body.blocks[0]).to.have.property('previousBlock'); @@ -270,7 +261,7 @@ describe('GET /blocks', function () { it('using generatorPublicKey should be ok', function (done) { getBlocks('generatorPublicKey=' + block.generatorPublicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { node.expect(res.body.blocks[i].generatorPublicKey).to.equal(block.generatorPublicKey); @@ -281,7 +272,7 @@ describe('GET /blocks', function () { it('using totalFee should be ok', function (done) { getBlocks('totalFee=' + block.totalFee, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { node.expect(res.body.blocks[i].totalFee).to.equal(block.totalFee); @@ -292,7 +283,7 @@ describe('GET /blocks', function () { it('using totalAmount should be ok', function (done) { getBlocks('totalAmount=' + block.totalAmount, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { node.expect(res.body.blocks[i].totalAmount).to.equal(block.totalAmount); @@ -310,7 +301,7 @@ describe('GET /blocks', function () { node.onNewBlock(function (err) { getBlocks('previousBlock=' + block.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); node.expect(res.body.blocks).to.have.length(1); node.expect(res.body.blocks[0].previousBlock).to.equal(previousBlock); @@ -321,7 +312,7 @@ describe('GET /blocks', function () { it('using orderBy == "height:asc" should be ok', function (done) { getBlocks('orderBy=' + 'height:asc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { if (res.body.blocks[i + 1] != null) { @@ -334,7 +325,7 @@ describe('GET /blocks', function () { it('using orderBy == "height:desc" should be ok', function (done) { getBlocks('orderBy=' + 'height:desc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { if (res.body.blocks[i + 1] != null) { @@ -347,7 +338,7 @@ describe('GET /blocks', function () { it('should be ordered by "height:desc" by default', function (done) { getBlocks('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blocks').that.is.an('array'); for (var i = 0; i < res.body.blocks.length; i++) { if (res.body.blocks[i + 1] != null) { @@ -366,8 +357,8 @@ describe('GET /api/blocks/get?id=', function () { it('using genesisblock id should be ok', function (done) { getBlocks('6438017970172540087', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('block').to.be.a('object'); + node.expect(res.body).to.have.property('success').to.be.true; + node.expect(res.body).to.have.property('block').to.be.an('object'); node.expect(res.body.block).to.have.property('id').to.be.a('string'); done(); }); @@ -375,7 +366,7 @@ describe('GET /api/blocks/get?id=', function () { it('using unknown id should fail', function (done) { getBlocks('9928719876370886655', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.be.a('string'); done(); }); @@ -383,7 +374,7 @@ describe('GET /api/blocks/get?id=', function () { it('using no id should fail', function (done) { getBlocks('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.be.a('string'); done(); }); diff --git a/test/api/chatrooms.js b/test/api/chatrooms.js index 315c4258..7a4b52d1 100644 --- a/test/api/chatrooms.js +++ b/test/api/chatrooms.js @@ -78,7 +78,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { type: 1 }); postMessage(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -100,7 +100,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { type: 1 }); postMessage(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -122,7 +122,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { type: 1 }); postMessage(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -144,7 +144,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { type: 1 }); postMessage(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -177,7 +177,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { type: 1 }); postMessage(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -191,7 +191,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with no parameters', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); // 2 chats and 1 direct transfer from iAccount node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -222,7 +222,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for recipient1', function (done) { getChats(recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); // 2 chats and 1 direct transfer from iAccount node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -244,7 +244,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for recipient2', function (done) { getChats(recipient2.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); // 2 chats and 1 direct transfer from iAccount node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -262,7 +262,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with limit', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(1); for (let i = 0; i < res.body.chats.length; i++) { @@ -277,7 +277,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with offset', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(2); for (let i = 0; i < res.body.chats.length; i++) { @@ -292,7 +292,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with both limit and offset', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(1); for (let i = 0; i < res.body.chats.length; i++) { @@ -307,7 +307,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with orderBy=timestamp:desc', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -326,7 +326,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for sender with orderBy=timestamp:asc', function (done) { getChats(sender.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -345,7 +345,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the chat list for recipient1', function (done) { getChats(recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('chats').to.have.lengthOf(3); for (let i = 0; i < res.body.chats.length; i++) { @@ -360,7 +360,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); // 2 messages and 1 direct transfer node.expect(res.body).to.have.property('messages').to.have.lengthOf(3); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -374,7 +374,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 with a limit', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(1); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -390,7 +390,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 with an offset', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(2); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -406,7 +406,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 with an orderBy=timestamp:desc', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(3); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -426,7 +426,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 with an orderBy=timestamp:asc', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('3'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(3); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -446,7 +446,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 without direct transfers', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('2'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(2); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -462,7 +462,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 without direct transfers with a limit', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('2'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(1); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -479,7 +479,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 without direct transfers with an offset', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('2'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(1); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -496,7 +496,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 without direct transfers with an orderBy=timestamp:desc', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('2'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(2); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); @@ -517,7 +517,7 @@ describe('GET /api/chatrooms/:ID/:ID', function () { it('should return the messages between sender and recipient1 without direct transfers with an orderBy=timestamp:asc', function (done) { getMessages(sender.address, recipient1.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.equal('2'); node.expect(res.body).to.have.property('messages').to.have.lengthOf(2); node.expect(res.body).to.have.property('participants').to.have.lengthOf(2); diff --git a/test/api/dapps.js b/test/api/dapps.js index 0de4afb3..8ee29bfe 100644 --- a/test/api/dapps.js +++ b/test/api/dapps.js @@ -1,1342 +1,1342 @@ -'use strict'; - -var node = require('./../node.js'); -var clearDatabaseTable = require('../common/globalBefore').clearDatabaseTable; -var modulesLoader = require('../common/initModule').modulesLoader; - -var dapp = {}; -var account = node.randomTxAccount(); -var account2 = node.randomTxAccount(); - -function openAccount (account, done) { - node.post('/api/accounts/open', { - secret: account.password - }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('account').that.is.an('object'); - account.address = res.body.account.address; - account.publicKey = res.body.account.publicKey; - account.balance = res.body.account.balance; - done(err, res); - }); -} - -function putTransaction (params, done) { - node.put('/api/transactions/', params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.onNewBlock(function (err) { - done(err, res); - }); - }); -} - -before(function (done) { - modulesLoader.getDbConnection(function (err, db) { - if (err) { - return done(err); - } - - node.async.every(['dapps', 'outtransfer', 'intransfer'], function (table, cb) { - clearDatabaseTable(db, modulesLoader.logger, table, cb); - }, done); - }); -}); - -before(function (done) { - // Send to ADM to account 1 address - setTimeout(function () { - var randomADM = node.randomADM(); - var expectedFee = node.expectedFee(randomADM); - - putTransaction({ - secret: node.iAccount.password, - amount: randomADM, - recipientId: account.address - }, done); - }, 2000); -}); - -before(function (done) { - // Send to Adamant to account 2 address - setTimeout(function () { - var randomADM = node.randomADM(); - var expectedFee = node.expectedFee(randomADM); - - putTransaction({ - secret: node.iAccount.password, - amount: randomADM, - recipientId: account2.address - }, done); - }, 2000); -}); - -var validDapp; - -beforeEach(function (done) { - validDapp = { - secret: account.password, - category: node.randomProperty(node.dappCategories), - type: node.dappTypes.DAPP, - name: node.randomApplicationName(), - description: 'A dapp added via API autotest', - tags: 'handy dizzy pear airplane alike wonder nifty curve young probable tart concentrate', - link: node.guestbookDapp.link, - icon: node.guestbookDapp.icon - }; - done(); -}); - -describe('PUT /dapps', function () { - var validParams; - - beforeEach(function (done) { - validParams = validDapp; - validParams.link = validParams.link.replace(/\.zip/, node.randomApplicationName() + '.zip'); - done(); - }); - - it('using account with no funds should fail', function (done) { - validParams.secret = node.randomAccount().password; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); - done(); - }); - }); - - it('using no name should fail', function (done) { - delete validParams.name; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using very long name should fail', function (done) { - validParams.name = 'Lorem ipsum dolor sit amet, conse'; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using numeric name should fail', function (done) { - validParams.name = 12345; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using very long description should fail', function (done) { - validParams.description = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient c'; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using numeric description should fail', function (done) { - validParams.description = 12345; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using very long tag should fail', function (done) { - validParams.tags = 'develop,rice,voiceless,zonked,crooked,consist,price,extend,sail,treat,pie,massive,fail,maid,summer,verdant,visitor,bushes,abrupt,beg,black-and-white,flight,twist'; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using numeric tags should fail', function (done) { - validParams.tags = 12345; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using numeric link should fail', function (done) { - validParams.link = 12345; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using numeric icon should fail', function (done) { - validParams.icon = 12345; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - describe('from account with second signature enabled', function (done) { - before(function (done) { - node.put('/api/signatures', { - secret: account2.password, - secondSecret: account2.secondPassword - }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('transaction').that.is.an('object'); - node.onNewBlock(done); - }); - }); - - beforeEach(function (done) { - validParams.secret = account2.password; - validParams.secondSecret = account2.secondPassword; - done(); - }); - - // secondSecret are not used in /api/dapps - // it('using no second passphrase should fail', function (done) { - // delete validParams.secondSecret; - - // node.put('/api/dapps', validParams, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; - // node.expect(res.body).to.have.property('error'); - // done(); - // }); - // }); - - // secondSecret are not used in /api/dapps - // it('using invalid second passphrase should fail', function (done) { - // validParams.secondSecret = node.randomAccount().password; - - // node.put('/api/dapps', validParams, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; - // node.expect(res.body).to.have.property('error'); - // done(); - // }); - // }); - - it('using valid second passphrase should be ok', function (done) { - validParams.secondSecret = account2.secondPassword; - - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - done(); - }); - }); - }); - - it('using valid params should be ok', function (done) { - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body.transaction).to.have.property('id'); - dapp = validParams; - dapp.transactionId = res.body.transaction.id; - done(); - }); - }); - - it('using existing dapp name should fail', function (done) { - validParams.name = dapp.name; - - node.onNewBlock(function (err) { - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - }); - - it('using existing dapp link should fail', function (done) { - validParams.link = dapp.link; - - node.onNewBlock(function (err) { - node.put('/api/dapps', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - }); -}); - -describe('PUT /api/dapps/transaction', function () { - function putTransaction (params, done) { - node.put('/api/dapps/transaction', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - validParams = { - secret: account.password, - dappId: dapp.transactionId, - amount: 100000000 - }; - done(); - }); - - it('using no secret should fail', function (done) { - delete validParams.secret; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: secret'); - done(); - }); - }); - - it('using random secret should fail', function (done) { - validParams.secret = node.randomAccount().password; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); - done(); - }); - }); - - it('using secret with length > 100 should fail', function (done) { - validParams.secret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); - done(); - }); - }); - - it('using no amount should fail', function (done) { - delete validParams.amount; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: amount'); - done(); - }); - }); - - it('using amount < 0 should fail', function (done) { - validParams.amount = -1; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); - done(); - }); - }); - - it('using amount > balance should fail', function (done) { - openAccount(account, function (err, res) { - validParams.amount = new node.bignum(account.balance).plus('1').toNumber(); - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - }); - - it('using amount > 100M should fail', function (done) { - validParams.amount = 10000000000000002; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Value 10000000000000002 is greater than maximum 9800000000000000'); - done(); - }); - }); - - it('using numeric publicKey should fail', function (done) { - validParams.publicKey = 1; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using numeric secondSecret should fail', function (done) { - validParams.secondSecret = 1; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using secondSecret with length > 100 should fail', function (done) { - validParams.secondSecret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); - done(); - }); - }); - - it('using no dappId should fail', function (done) { - delete validParams.dappId; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: dappId'); - done(); - }); - }); - - it('using numeric dappId should fail', function (done) { - validParams.dappId = 1; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using dappId with length > 20 should fail', function (done) { - validParams.dappId = '012345678901234567890'; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); - done(); - }); - }); - - it('using unknown dappId', function (done) { - validParams.dappId = '8713095156789756398'; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Application not found: ' + validParams.dappId); - done(); - }); - }); - - it('using numeric multisigAccountPublicKey should fail', function (done) { - validParams.multisigAccountPublicKey = 1; - - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using valid params should be ok', function (done) { - putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('transactionId').to.not.be.empty; - done(); - }); - }); -}); - -describe('PUT /api/dapps/withdrawal', function () { - function putWithdrawal (params, done) { - node.put('/api/dapps/withdrawal', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - var randomAccount = node.randomTxAccount(); - var transaction = node.createSendTransaction({ - keyPair: account.keypair, - amount: 100000000, - recipientId: randomAccount.address - }); - validParams = { - secret: account.password, - amount: 100000000, - dappId: dapp.transactionId, - transactionId: transaction.id, - recipientId: randomAccount.address - }; - - done(); - }); - - it('using no secret should fail', function (done) { - delete validParams.secret; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: secret'); - done(); - }); - }); - - it('using random secret should fail', function (done) { - validParams.secret = node.randomAccount().password; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); - done(); - }); - }); - - it('using secret with length > 100 should fail', function (done) { - validParams.secret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); - done(); - }); - }); - - it('using no amount should fail', function (done) { - delete validParams.amount; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: amount'); - done(); - }); - }); - - it('using amount < 0 should fail', function (done) { - validParams.amount = -1; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); - done(); - }); - }); - - it('using amount > balance should fail', function (done) { - openAccount(account, function (err, res) { - validParams.amount = new node.bignum(account.balance).plus('1').toNumber(); - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - }); - - it('using amount > 100M should fail', function (done) { - validParams.amount = 10000000000000002; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Value 10000000000000002 is greater than maximum 9800000000000000'); - done(); - }); - }); - - it('using numeric secondSecret should fail', function (done) { - validParams.secondSecret = 1; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using secondSecret with length > 100 should fail', function (done) { - validParams.secondSecret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); - done(); - }); - }); - - it('using no dappId should fail', function (done) { - delete validParams.dappId; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: dappId'); - done(); - }); - }); - - it('using numeric dappId should fail', function (done) { - validParams.dappId = 1; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using alphanumeric dappId should fail', function (done) { - validParams.dappId = '1L'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format id: 1L'); - done(); - }); - }); - - it('using blank dappId should fail', function (done) { - validParams.dappId = ''; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1'); - done(); - }); - }); - - it('using dappId with length > 20 should fail', function (done) { - validParams.dappId = '012345678901234567890'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); - done(); - }); - }); - - it('using unknown dappId', function (done) { - validParams.dappId = '8713095156789756398'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Application not found: ' + validParams.dappId); - done(); - }); - }); - - it('using no transactionId should fail', function (done) { - delete validParams.transactionId; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: transactionId'); - done(); - }); - }); - - it('using numeric transactionId should fail', function (done) { - validParams.transactionId = 1; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using alphanumeric transactionId should fail', function (done) { - validParams.transactionId = '1L'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format id: 1L'); - done(); - }); - }); - - it('using blank transactionId should fail', function (done) { - validParams.transactionId = ''; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1'); - done(); - }); - }); - - it('using transactionId with length > 20 should fail', function (done) { - validParams.transactionId = '012345678901234567890'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); - done(); - }); - }); - - it('using no recipientId should fail', function (done) { - delete validParams.recipientId; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Missing required property: recipientId'); - done(); - }); - }); - - it('using numeric recipientId should fail', function (done) { - validParams.recipientId = 12; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using recipientId with length < 2 should fail', function (done) { - validParams.recipientId = '1'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format address: 1'); - done(); - }); - }); - - it('using recipientId with length > 22 should fail', function (done) { - validParams.recipientId = 'U0123456789012345678901'; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (23 chars), maximum 22'); - done(); - }); - }); - - it('using recipientId without an "U" should fail', function (done) { - validParams.recipientId = validParams.recipientId.replace('U', ''); - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.match(/Object didn\'t pass validation for format address: [0-9]+/); - done(); - }); - }); - - it('using numeric multisigAccountPublicKey should fail', function (done) { - validParams.multisigAccountPublicKey = 1; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); - done(); - }); - }); - - it('using valid params should be ok', function (done) { - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('transactionId').to.not.be.empty; - done(); - }); - }); - - it('using same valid params twice should fail', function (done) { - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('transactionId').to.not.be.empty; - - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error').to.contain('Transaction is already processed'); - done(); - }); - }); - }); - - it('using already confirmed params after new block should fail', function (done) { - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('transactionId').to.not.be.empty; - - node.onNewBlock(function (err) { - putWithdrawal(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('Transaction is already confirmed: ' + validParams.transactionId); - done(); - }); - }); - }); - }); -}); - -describe('GET /dapps', function () { - before(function (done) { - node.onNewBlock(done); - }); - - function getDapps (params, done) { - node.get('/api/dapps?' + params, done); - } - - it('user orderBy == "category:asc" should be ok', function (done) { - getDapps('orderBy=' + 'category:asc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (res.body.dapps[0] != null) { - for (var i = 0; i < res.body.dapps.length; i++) { - if (res.body.dapps[i + 1] != null) { - node.expect(res.body.dapps[i].category).to.be.at.most(res.body.dapps[i + 1].category); - } - } - } - done(); - }); - }); - - it('user orderBy == "category:desc" should be ok', function (done) { - getDapps('orderBy=' + 'category:desc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (res.body.dapps[0] != null) { - for (var i = 0; i < res.body.dapps.length; i++) { - if (res.body.dapps[i + 1] != null) { - node.expect(res.body.dapps[i].category).to.be.at.least(res.body.dapps[i + 1].category); - } - } - } - done(); - }); - }); - - it('using category should be ok', function (done) { - var randomCategory = node.randomProperty(node.dappCategories, true); - - getDapps('category=' + randomCategory, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (res.body.dapps.length > 0) { - node.expect(res.body.dapps[0].category).to.equal(node.dappCategories[randomCategory]); - } - done(); - }); - }); - - it('using name should be ok', function (done) { - var name = ''; - - if (dapp !== {} && dapp != null) { - name = dapp.name; - } else { - name = 'test'; - } - - getDapps('name=' + name, function (err, res) { - node.expect(res.body).to.have.property('success'); - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (name !== 'test') { - node.expect(res.body.dapps).to.have.length.above(0); - node.expect(res.body.dapps[0].name).to.equal(name); - } - done(); - }); - }); - - it('using type should be ok', function (done) { - var type = node.randomProperty(node.dappTypes); - - getDapps('type=' + type, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - for (var i = 0; i < res.body.dapps.length; i++) { - if (res.body.dapps[i] != null) { - node.expect(res.body.dapps[i].type).to.equal(type); - } - } - done(); - }); - }); - - it('using numeric link should fail', function (done) { - var link = 12345; - - getDapps('link=' + link, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using string link should be ok', function (done) { - var link = node.guestbookDapp.link; - - getDapps('link=' + link, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - for (var i = 0; i < res.body.dapps.length; i++) { - if (res.body.dapps[i] != null) { - node.expect(res.body.dapps[i].link).to.equal(link); - } - } - done(); - }); - }); - - it('using no limit should be ok', function (done) { - getDapps('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (res.body.dapps.length > 0) { - dapp = res.body.dapps[0]; - dapp = dapp; - } - done(); - }); - }); - - it('using limit == 3 should be ok', function (done) { - var limit = 3; - - getDapps('limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - node.expect(res.body.dapps).to.have.length.at.most(limit); - done(); - }); - }); - - it('using offset should be ok', function (done) { - var offset = 1; - var secondDapp; - - getDapps('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - if (res.body.dapps[1] != null) { - secondDapp = res.body.dapps[1]; - - getDapps('offset=' + 1, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - node.expect(res.body.dapps[0]).to.deep.equal(secondDapp); - }); - } - done(); - }); - }); -}); - -describe('GET /dapps?id=', function () { - function getDapps (id, done) { - node.get('/api/dapps?id=' + id, done); - } - - it('using no id should fail', function (done) { - getDapps('', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1: #/id'); - done(); - }); - }); - - it('using id with length > 20 should fail', function (done) { - getDapps('012345678901234567890', function (err, res) { - node.expect(res.body).to.have.property('success').to.not.be.ok; - node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20: #/id'); - done(); - }); - }); - - it('using unknown id should be ok', function (done) { - var dappId = '8713095156789756398'; - - getDapps(dappId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - done(); - }); - }); - - it('using valid id should be ok', function (done) { - getDapps(dapp.transactionId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - node.expect(res.body.dapps[0].transactionId).to.equal(dapp.transactionId); - done(); - }); - }); -}); - -describe('POST /api/dapps/install', function () { - function postInstall (params, done) { - node.post('/api/dapps/install', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - validParams = { - id: dapp.transactionId, - master: 'node.config.dapp.masterpassword' - }; - done(); - }); - - it('using no id should fail', function (done) { - delete validParams.id; - - postInstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using unknown id should fail', function (done) { - validParams.id = 'unknown'; - - postInstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using valid params should be ok', function (done) { - postInstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('path'); - dapp = dapp; - done(); - }); - }); - - describe('when link is 404 not found', function () { - var toBeNotFound; - - beforeEach(function (done) { - toBeNotFound = validDapp; - toBeNotFound.link = toBeNotFound.link.replace(/\.zip/, node.randomApplicationName() + '.zip'); - done(); - }); - - it('should fail', function (done) { - node.put('/api/dapps', toBeNotFound, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body.transaction).to.have.property('id').that.is.not.empty; - validParams.id = res.body.transaction.id; - - node.onNewBlock(function (err) { - postInstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error').to.match(/[0-9]+ Installation failed: Received bad response code 404/); - done(); - }); - }); - }); - }); - }); -}); - -describe('GET /api/dapps/installed', function () { - it('should be ok', function (done) { - var flag = 0; - - node.get('/api/dapps/installed', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - for (var i = 0; i < res.body.dapps.length; i++) { - if (res.body.dapps[i] != null) { - if (res.body.dapps[i].transactionId === dapp.transactionId) { - flag += 1; - } - } - } - node.expect(flag).to.equal(1); - done(); - }); - }); -}); - -describe('GET /api/dapps/installedIds', function () { - it('should be ok', function (done) { - var flag = 0; - - node.get('/api/dapps/installedIds', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('ids').that.is.an('array'); - for (var i = 0; i < res.body.ids.length; i++) { - if (res.body.ids[i] != null) { - if (res.body.ids[i] === dapp.transactionId) { - flag += 1; - } - } - } - node.expect(flag).to.equal(1); - done(); - }); - }); -}); - -describe('GET /api/dapps/search?q=', function () { - function getSearch (params, done) { - node.get('/api/dapps/search?' + params, done); - } - - it('using invalid params should fail', function (done) { - var q = 1234; - var category = 'good'; - var installed = 'true'; - - var params = 'q=' + q + '&category=' + category + '&installed=' + installed; - - getSearch(params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using valid parameters should be ok', function (done) { - var q = 'a'; - var category = node.randomProperty(node.dappCategories, true); - var installed = 1; - - var params = 'q=' + q + '&installed=' + installed + '&category=' + node.dappCategories[category]; - - getSearch(params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - done(); - }); - }); - - it('using installed = 0 should be ok', function (done) { - var q = 's'; - var category = node.randomProperty(node.dappCategories); - var installed = 0; - - var params = 'q=' + q + '&installed=' + installed + '&category=' + category; - - getSearch(params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('dapps').that.is.an('array'); - done(); - }); - }); -}); - -describe('POST /api/dapps/launch', function () { - function postLaunch (params, done) { - node.post('/api/dapps/launch', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - validParams = { - id: dapp.transactionId, - master: 'node.config.dapp.masterpassword' - }; - done(); - }); - - it('using no id should fail', function (done) { - delete validParams.id; - - postLaunch(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using unknown id should fail', function (done) { - validParams.id = 'unknown'; - - postLaunch(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using empty params array should fail', function (done) { - validParams.params = []; - - postLaunch(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - // it is not an app actually and will not work - // it('using valid params should be ok', function (done) { - // postLaunch(validParams, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; - // node.get('/api/dapps/launched', function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; - // node.expect(res.body).to.have.property('launched').that.is.an('array'); - // var flag = 0; - - // for (var i = 0; i < res.body.launched.length; i++) { - // if (res.body.launched[i] != null) { - // if (res.body.launched[i] === dapp.transactionId) { - // flag += 1; - // } - // } - // } - // node.expect(flag).to.equal(1); - // }); - // done(); - // }); - // }); -}); - -describe('POST /api/dapps/stop', function () { - function postStop (params, done) { - node.post('/api/dapps/stop', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - validParams = { - id: dapp.transactionId, - master: 'node.config.dapp.masterpassword' - }; - done(); - }); - - it('using no id should fail', function (done) { - delete validParams.id; - - postStop(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using unknown id should fail', function (done) { - validParams.id = 'unknown'; - - postStop(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - // it is not an app actually and will not work - // it('using valid params should be ok', function (done) { - // postStop(validParams, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; - // done(); - // }); - // }); -}); - -describe('GET /api/dapps/categories', function () { - it('should be ok', function (done) { - node.get('/api/dapps/categories', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('categories').that.is.an('object'); - for (var i in node.dappCategories) { - node.expect(res.body.categories[i]).to.equal(node.dappCategories[i]); - } - done(); - }); - }); -}); - -describe('POST /api/dapps/uninstall', function () { - function postUninstall (params, done) { - node.post('/api/dapps/uninstall', params, done); - } - - before(function (done) { - node.expect(dapp).to.be.a('object'); - node.expect(dapp).to.have.property('transactionId').to.be.not.null; - done(); - }); - - var validParams; - - beforeEach(function (done) { - validParams = { - id: dapp.transactionId, - master: 'node.config.dapp.masterpassword' - }; - done(); - }); - - it('using no id should fail', function (done) { - delete validParams.id; - - postUninstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using unknown id should fail', function (done) { - validParams.id = 'unknown'; - - postUninstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; - node.expect(res.body).to.have.property('error'); - done(); - }); - }); - - it('using valid params should be ok', function (done) { - postUninstall(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - done(); - }); - }); -}); +// 'use strict'; + +// var node = require('./../node.js'); +// var clearDatabaseTable = require('../common/globalBefore').clearDatabaseTable; +// var modulesLoader = require('../common/initModule').modulesLoader; + +// var dapp = {}; +// var account = node.randomTxAccount(); +// var account2 = node.randomTxAccount(); + +// function openAccount (account, done) { +// node.post('/api/accounts/open', { +// secret: account.password +// }, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('account').that.is.an('object'); +// account.address = res.body.account.address; +// account.publicKey = res.body.account.publicKey; +// account.balance = res.body.account.balance; +// done(err, res); +// }); +// } + +// function putTransaction (params, done) { +// node.put('/api/transactions/', params, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.onNewBlock(function (err) { +// done(err, res); +// }); +// }); +// } + +// before(function (done) { +// modulesLoader.getDbConnection(function (err, db) { +// if (err) { +// return done(err); +// } + +// node.async.every(['dapps', 'outtransfer', 'intransfer'], function (table, cb) { +// clearDatabaseTable(db, modulesLoader.logger, table, cb); +// }, done); +// }); +// }); + +// before(function (done) { +// // Send to ADM to account 1 address +// setTimeout(function () { +// var randomADM = node.randomADM(); +// var expectedFee = node.expectedFee(randomADM); + +// putTransaction({ +// secret: node.iAccount.password, +// amount: randomADM, +// recipientId: account.address +// }, done); +// }, 2000); +// }); + +// before(function (done) { +// // Send to Adamant to account 2 address +// setTimeout(function () { +// var randomADM = node.randomADM(); +// var expectedFee = node.expectedFee(randomADM); + +// putTransaction({ +// secret: node.iAccount.password, +// amount: randomADM, +// recipientId: account2.address +// }, done); +// }, 2000); +// }); + +// var validDapp; + +// beforeEach(function (done) { +// validDapp = { +// secret: account.password, +// category: node.randomProperty(node.dappCategories), +// type: node.dappTypes.DAPP, +// name: node.randomApplicationName(), +// description: 'A dapp added via API autotest', +// tags: 'handy dizzy pear airplane alike wonder nifty curve young probable tart concentrate', +// link: node.guestbookDapp.link, +// icon: node.guestbookDapp.icon +// }; +// done(); +// }); + +// describe('PUT /dapps', function () { +// var validParams; + +// beforeEach(function (done) { +// validParams = validDapp; +// validParams.link = validParams.link.replace(/\.zip/, node.randomApplicationName() + '.zip'); +// done(); +// }); + +// it('using account with no funds should fail', function (done) { +// validParams.secret = node.randomAccount().password; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); +// done(); +// }); +// }); + +// it('using no name should fail', function (done) { +// delete validParams.name; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using very long name should fail', function (done) { +// validParams.name = 'Lorem ipsum dolor sit amet, conse'; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using numeric name should fail', function (done) { +// validParams.name = 12345; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using very long description should fail', function (done) { +// validParams.description = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient c'; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using numeric description should fail', function (done) { +// validParams.description = 12345; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using very long tag should fail', function (done) { +// validParams.tags = 'develop,rice,voiceless,zonked,crooked,consist,price,extend,sail,treat,pie,massive,fail,maid,summer,verdant,visitor,bushes,abrupt,beg,black-and-white,flight,twist'; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using numeric tags should fail', function (done) { +// validParams.tags = 12345; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using numeric link should fail', function (done) { +// validParams.link = 12345; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using numeric icon should fail', function (done) { +// validParams.icon = 12345; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// describe('from account with second signature enabled', function (done) { +// before(function (done) { +// node.put('/api/signatures', { +// secret: account2.password, +// secondSecret: account2.secondPassword +// }, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('transaction').that.is.an('object'); +// node.onNewBlock(done); +// }); +// }); + +// beforeEach(function (done) { +// validParams.secret = account2.password; +// validParams.secondSecret = account2.secondPassword; +// done(); +// }); + +// // secondSecret are not used in /api/dapps +// // it('using no second passphrase should fail', function (done) { +// // delete validParams.secondSecret; + +// // node.put('/api/dapps', validParams, function (err, res) { +// // node.expect(res.body).to.have.property('success').to.be.false; +// // node.expect(res.body).to.have.property('error'); +// // done(); +// // }); +// // }); + +// // secondSecret are not used in /api/dapps +// // it('using invalid second passphrase should fail', function (done) { +// // validParams.secondSecret = node.randomAccount().password; + +// // node.put('/api/dapps', validParams, function (err, res) { +// // node.expect(res.body).to.have.property('success').to.be.false; +// // node.expect(res.body).to.have.property('error'); +// // done(); +// // }); +// // }); + +// it('using valid second passphrase should be ok', function (done) { +// validParams.secondSecret = account2.secondPassword; + +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// done(); +// }); +// }); +// }); + +// it('using valid params should be ok', function (done) { +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body.transaction).to.have.property('id'); +// dapp = validParams; +// dapp.transactionId = res.body.transaction.id; +// done(); +// }); +// }); + +// it('using existing dapp name should fail', function (done) { +// validParams.name = dapp.name; + +// node.onNewBlock(function (err) { +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); +// }); + +// it('using existing dapp link should fail', function (done) { +// validParams.link = dapp.link; + +// node.onNewBlock(function (err) { +// node.put('/api/dapps', validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); +// }); +// }); + +// describe('PUT /api/dapps/transaction', function () { +// function putTransaction (params, done) { +// node.put('/api/dapps/transaction', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// validParams = { +// secret: account.password, +// dappId: dapp.transactionId, +// amount: 100000000 +// }; +// done(); +// }); + +// it('using no secret should fail', function (done) { +// delete validParams.secret; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: secret'); +// done(); +// }); +// }); + +// it('using random secret should fail', function (done) { +// validParams.secret = node.randomAccount().password; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); +// done(); +// }); +// }); + +// it('using secret with length > 100 should fail', function (done) { +// validParams.secret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); +// done(); +// }); +// }); + +// it('using no amount should fail', function (done) { +// delete validParams.amount; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: amount'); +// done(); +// }); +// }); + +// it('using amount < 0 should fail', function (done) { +// validParams.amount = -1; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); +// done(); +// }); +// }); + +// it('using amount > balance should fail', function (done) { +// openAccount(account, function (err, res) { +// validParams.amount = new node.bignum(account.balance).plus('1').toNumber(); + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); +// }); + +// it('using amount > 100M should fail', function (done) { +// validParams.amount = 10000000000000002; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Value 10000000000000002 is greater than maximum 9800000000000000'); +// done(); +// }); +// }); + +// it('using numeric publicKey should fail', function (done) { +// validParams.publicKey = 1; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using numeric secondSecret should fail', function (done) { +// validParams.secondSecret = 1; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using secondSecret with length > 100 should fail', function (done) { +// validParams.secondSecret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); +// done(); +// }); +// }); + +// it('using no dappId should fail', function (done) { +// delete validParams.dappId; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: dappId'); +// done(); +// }); +// }); + +// it('using numeric dappId should fail', function (done) { +// validParams.dappId = 1; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using dappId with length > 20 should fail', function (done) { +// validParams.dappId = '012345678901234567890'; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); +// done(); +// }); +// }); + +// it('using unknown dappId', function (done) { +// validParams.dappId = '8713095156789756398'; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Application not found: ' + validParams.dappId); +// done(); +// }); +// }); + +// it('using numeric multisigAccountPublicKey should fail', function (done) { +// validParams.multisigAccountPublicKey = 1; + +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using valid params should be ok', function (done) { +// putTransaction(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('transactionId').to.not.be.empty; +// done(); +// }); +// }); +// }); + +// describe('PUT /api/dapps/withdrawal', function () { +// function putWithdrawal (params, done) { +// node.put('/api/dapps/withdrawal', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// var randomAccount = node.randomTxAccount(); +// var transaction = node.createSendTransaction({ +// keyPair: account.keypair, +// amount: 100000000, +// recipientId: randomAccount.address +// }); +// validParams = { +// secret: account.password, +// amount: 100000000, +// dappId: dapp.transactionId, +// transactionId: transaction.id, +// recipientId: randomAccount.address +// }; + +// done(); +// }); + +// it('using no secret should fail', function (done) { +// delete validParams.secret; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: secret'); +// done(); +// }); +// }); + +// it('using random secret should fail', function (done) { +// validParams.secret = node.randomAccount().password; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); +// done(); +// }); +// }); + +// it('using secret with length > 100 should fail', function (done) { +// validParams.secret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); +// done(); +// }); +// }); + +// it('using no amount should fail', function (done) { +// delete validParams.amount; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: amount'); +// done(); +// }); +// }); + +// it('using amount < 0 should fail', function (done) { +// validParams.amount = -1; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); +// done(); +// }); +// }); + +// it('using amount > balance should fail', function (done) { +// openAccount(account, function (err, res) { +// validParams.amount = new node.bignum(account.balance).plus('1').toNumber(); + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); +// }); + +// it('using amount > 100M should fail', function (done) { +// validParams.amount = 10000000000000002; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Value 10000000000000002 is greater than maximum 9800000000000000'); +// done(); +// }); +// }); + +// it('using numeric secondSecret should fail', function (done) { +// validParams.secondSecret = 1; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using secondSecret with length > 100 should fail', function (done) { +// validParams.secondSecret = 'major patient image mom reject theory glide brisk polar source rely inhale major patient image mom re'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (101 chars), maximum 100'); +// done(); +// }); +// }); + +// it('using no dappId should fail', function (done) { +// delete validParams.dappId; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: dappId'); +// done(); +// }); +// }); + +// it('using numeric dappId should fail', function (done) { +// validParams.dappId = 1; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using alphanumeric dappId should fail', function (done) { +// validParams.dappId = '1L'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format id: 1L'); +// done(); +// }); +// }); + +// it('using blank dappId should fail', function (done) { +// validParams.dappId = ''; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1'); +// done(); +// }); +// }); + +// it('using dappId with length > 20 should fail', function (done) { +// validParams.dappId = '012345678901234567890'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); +// done(); +// }); +// }); + +// it('using unknown dappId', function (done) { +// validParams.dappId = '8713095156789756398'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Application not found: ' + validParams.dappId); +// done(); +// }); +// }); + +// it('using no transactionId should fail', function (done) { +// delete validParams.transactionId; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: transactionId'); +// done(); +// }); +// }); + +// it('using numeric transactionId should fail', function (done) { +// validParams.transactionId = 1; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using alphanumeric transactionId should fail', function (done) { +// validParams.transactionId = '1L'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format id: 1L'); +// done(); +// }); +// }); + +// it('using blank transactionId should fail', function (done) { +// validParams.transactionId = ''; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1'); +// done(); +// }); +// }); + +// it('using transactionId with length > 20 should fail', function (done) { +// validParams.transactionId = '012345678901234567890'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20'); +// done(); +// }); +// }); + +// it('using no recipientId should fail', function (done) { +// delete validParams.recipientId; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Missing required property: recipientId'); +// done(); +// }); +// }); + +// it('using numeric recipientId should fail', function (done) { +// validParams.recipientId = 12; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using recipientId with length < 2 should fail', function (done) { +// validParams.recipientId = '1'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format address: 1'); +// done(); +// }); +// }); + +// it('using recipientId with length > 22 should fail', function (done) { +// validParams.recipientId = 'U0123456789012345678901'; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.contain("Object didn't pass validation for format address"); +// done(); +// }); +// }); + +// it('using recipientId without an "U" should fail', function (done) { +// validParams.recipientId = validParams.recipientId.replace('U', ''); + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.match(/Object didn\'t pass validation for format address: [0-9]+/); +// done(); +// }); +// }); + +// it('using numeric multisigAccountPublicKey should fail', function (done) { +// validParams.multisigAccountPublicKey = 1; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Expected type string but found type integer'); +// done(); +// }); +// }); + +// it('using valid params should be ok', function (done) { +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('transactionId').to.not.be.empty; +// done(); +// }); +// }); + +// it('using same valid params twice should fail', function (done) { +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('transactionId').to.not.be.empty; + +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error').to.contain('Transaction is already processed'); +// done(); +// }); +// }); +// }); + +// it('using already confirmed params after new block should fail', function (done) { +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('transactionId').to.not.be.empty; + +// node.onNewBlock(function (err) { +// putWithdrawal(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('Transaction is already confirmed: ' + validParams.transactionId); +// done(); +// }); +// }); +// }); +// }); +// }); + +// describe('GET /dapps', function () { +// before(function (done) { +// node.onNewBlock(done); +// }); + +// function getDapps (params, done) { +// node.get('/api/dapps?' + params, done); +// } + +// it('user orderBy == "category:asc" should be ok', function (done) { +// getDapps('orderBy=' + 'category:asc', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (res.body.dapps[0] != null) { +// for (var i = 0; i < res.body.dapps.length; i++) { +// if (res.body.dapps[i + 1] != null) { +// node.expect(res.body.dapps[i].category).to.be.at.most(res.body.dapps[i + 1].category); +// } +// } +// } +// done(); +// }); +// }); + +// it('user orderBy == "category:desc" should be ok', function (done) { +// getDapps('orderBy=' + 'category:desc', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (res.body.dapps[0] != null) { +// for (var i = 0; i < res.body.dapps.length; i++) { +// if (res.body.dapps[i + 1] != null) { +// node.expect(res.body.dapps[i].category).to.be.at.least(res.body.dapps[i + 1].category); +// } +// } +// } +// done(); +// }); +// }); + +// it('using category should be ok', function (done) { +// var randomCategory = node.randomProperty(node.dappCategories, true); + +// getDapps('category=' + randomCategory, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (res.body.dapps.length > 0) { +// node.expect(res.body.dapps[0].category).to.equal(node.dappCategories[randomCategory]); +// } +// done(); +// }); +// }); + +// it('using name should be ok', function (done) { +// var name = ''; + +// if (dapp !== {} && dapp != null) { +// name = dapp.name; +// } else { +// name = 'test'; +// } + +// getDapps('name=' + name, function (err, res) { +// node.expect(res.body).to.have.property('success'); +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (name !== 'test') { +// node.expect(res.body.dapps).to.have.length.above(0); +// node.expect(res.body.dapps[0].name).to.equal(name); +// } +// done(); +// }); +// }); + +// it('using type should be ok', function (done) { +// var type = node.randomProperty(node.dappTypes); + +// getDapps('type=' + type, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// for (var i = 0; i < res.body.dapps.length; i++) { +// if (res.body.dapps[i] != null) { +// node.expect(res.body.dapps[i].type).to.equal(type); +// } +// } +// done(); +// }); +// }); + +// it('using numeric link should fail', function (done) { +// var link = 12345; + +// getDapps('link=' + link, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using string link should be ok', function (done) { +// var link = node.guestbookDapp.link; + +// getDapps('link=' + link, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// for (var i = 0; i < res.body.dapps.length; i++) { +// if (res.body.dapps[i] != null) { +// node.expect(res.body.dapps[i].link).to.equal(link); +// } +// } +// done(); +// }); +// }); + +// it('using no limit should be ok', function (done) { +// getDapps('', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (res.body.dapps.length > 0) { +// dapp = res.body.dapps[0]; +// dapp = dapp; +// } +// done(); +// }); +// }); + +// it('using limit == 3 should be ok', function (done) { +// var limit = 3; + +// getDapps('limit=' + limit, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// node.expect(res.body.dapps).to.have.length.at.most(limit); +// done(); +// }); +// }); + +// it('using offset should be ok', function (done) { +// var offset = 1; +// var secondDapp; + +// getDapps('', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// if (res.body.dapps[1] != null) { +// secondDapp = res.body.dapps[1]; + +// getDapps('offset=' + 1, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// node.expect(res.body.dapps[0]).to.deep.equal(secondDapp); +// }); +// } +// done(); +// }); +// }); +// }); + +// describe('GET /dapps?id=', function () { +// function getDapps (id, done) { +// node.get('/api/dapps?id=' + id, done); +// } + +// it('using no id should fail', function (done) { +// getDapps('', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error').to.equal('String is too short (0 chars), minimum 1: #/id'); +// done(); +// }); +// }); + +// it('using id with length > 20 should fail', function (done) { +// getDapps('012345678901234567890', function (err, res) { +// node.expect(res.body).to.have.property('success').to.not.be.ok; +// node.expect(res.body).to.have.property('error').to.equal('String is too long (21 chars), maximum 20: #/id'); +// done(); +// }); +// }); + +// it('using unknown id should be ok', function (done) { +// var dappId = '8713095156789756398'; + +// getDapps(dappId, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// done(); +// }); +// }); + +// it('using valid id should be ok', function (done) { +// getDapps(dapp.transactionId, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// node.expect(res.body.dapps[0].transactionId).to.equal(dapp.transactionId); +// done(); +// }); +// }); +// }); + +// describe('POST /api/dapps/install', function () { +// function postInstall (params, done) { +// node.post('/api/dapps/install', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// validParams = { +// id: dapp.transactionId, +// master: 'node.config.dapp.masterpassword' +// }; +// done(); +// }); + +// it('using no id should fail', function (done) { +// delete validParams.id; + +// postInstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using unknown id should fail', function (done) { +// validParams.id = 'unknown'; + +// postInstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using valid params should be ok', function (done) { +// postInstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('path'); +// dapp = dapp; +// done(); +// }); +// }); + +// describe('when link is 404 not found', function () { +// var toBeNotFound; + +// beforeEach(function (done) { +// toBeNotFound = validDapp; +// toBeNotFound.link = toBeNotFound.link.replace(/\.zip/, node.randomApplicationName() + '.zip'); +// done(); +// }); + +// it('should fail', function (done) { +// node.put('/api/dapps', toBeNotFound, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body.transaction).to.have.property('id').that.is.not.empty; +// validParams.id = res.body.transaction.id; + +// node.onNewBlock(function (err) { +// postInstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error').to.match(/[0-9]+ Installation failed: Received bad response code 404/); +// done(); +// }); +// }); +// }); +// }); +// }); +// }); + +// describe('GET /api/dapps/installed', function () { +// it('should be ok', function (done) { +// var flag = 0; + +// node.get('/api/dapps/installed', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// for (var i = 0; i < res.body.dapps.length; i++) { +// if (res.body.dapps[i] != null) { +// if (res.body.dapps[i].transactionId === dapp.transactionId) { +// flag += 1; +// } +// } +// } +// node.expect(flag).to.equal(1); +// done(); +// }); +// }); +// }); + +// describe('GET /api/dapps/installedIds', function () { +// it('should be ok', function (done) { +// var flag = 0; + +// node.get('/api/dapps/installedIds', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('ids').that.is.an('array'); +// for (var i = 0; i < res.body.ids.length; i++) { +// if (res.body.ids[i] != null) { +// if (res.body.ids[i] === dapp.transactionId) { +// flag += 1; +// } +// } +// } +// node.expect(flag).to.equal(1); +// done(); +// }); +// }); +// }); + +// describe('GET /api/dapps/search?q=', function () { +// function getSearch (params, done) { +// node.get('/api/dapps/search?' + params, done); +// } + +// it('using invalid params should fail', function (done) { +// var q = 1234; +// var category = 'good'; +// var installed = 'true'; + +// var params = 'q=' + q + '&category=' + category + '&installed=' + installed; + +// getSearch(params, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using valid parameters should be ok', function (done) { +// var q = 'a'; +// var category = node.randomProperty(node.dappCategories, true); +// var installed = 1; + +// var params = 'q=' + q + '&installed=' + installed + '&category=' + node.dappCategories[category]; + +// getSearch(params, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// done(); +// }); +// }); + +// it('using installed = 0 should be ok', function (done) { +// var q = 's'; +// var category = node.randomProperty(node.dappCategories); +// var installed = 0; + +// var params = 'q=' + q + '&installed=' + installed + '&category=' + category; + +// getSearch(params, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('dapps').that.is.an('array'); +// done(); +// }); +// }); +// }); + +// describe('POST /api/dapps/launch', function () { +// function postLaunch (params, done) { +// node.post('/api/dapps/launch', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// validParams = { +// id: dapp.transactionId, +// master: 'node.config.dapp.masterpassword' +// }; +// done(); +// }); + +// it('using no id should fail', function (done) { +// delete validParams.id; + +// postLaunch(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using unknown id should fail', function (done) { +// validParams.id = 'unknown'; + +// postLaunch(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using empty params array should fail', function (done) { +// validParams.params = []; + +// postLaunch(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// // it is not an app actually and will not work +// // it('using valid params should be ok', function (done) { +// // postLaunch(validParams, function (err, res) { +// // node.expect(res.body).to.have.property('success').to.be.true; +// // node.get('/api/dapps/launched', function (err, res) { +// // node.expect(res.body).to.have.property('success').to.be.true; +// // node.expect(res.body).to.have.property('launched').that.is.an('array'); +// // var flag = 0; + +// // for (var i = 0; i < res.body.launched.length; i++) { +// // if (res.body.launched[i] != null) { +// // if (res.body.launched[i] === dapp.transactionId) { +// // flag += 1; +// // } +// // } +// // } +// // node.expect(flag).to.equal(1); +// // }); +// // done(); +// // }); +// // }); +// }); + +// describe('POST /api/dapps/stop', function () { +// function postStop (params, done) { +// node.post('/api/dapps/stop', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// validParams = { +// id: dapp.transactionId, +// master: 'node.config.dapp.masterpassword' +// }; +// done(); +// }); + +// it('using no id should fail', function (done) { +// delete validParams.id; + +// postStop(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using unknown id should fail', function (done) { +// validParams.id = 'unknown'; + +// postStop(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// // it is not an app actually and will not work +// // it('using valid params should be ok', function (done) { +// // postStop(validParams, function (err, res) { +// // node.expect(res.body).to.have.property('success').to.be.true; +// // done(); +// // }); +// // }); +// }); + +// describe('GET /api/dapps/categories', function () { +// it('should be ok', function (done) { +// node.get('/api/dapps/categories', function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// node.expect(res.body).to.have.property('categories').that.is.an('object'); +// for (var i in node.dappCategories) { +// node.expect(res.body.categories[i]).to.equal(node.dappCategories[i]); +// } +// done(); +// }); +// }); +// }); + +// describe('POST /api/dapps/uninstall', function () { +// function postUninstall (params, done) { +// node.post('/api/dapps/uninstall', params, done); +// } + +// before(function (done) { +// node.expect(dapp).to.be.an('object'); +// node.expect(dapp).to.have.property('transactionId').not.to.be.null; +// done(); +// }); + +// var validParams; + +// beforeEach(function (done) { +// validParams = { +// id: dapp.transactionId, +// master: 'node.config.dapp.masterpassword' +// }; +// done(); +// }); + +// it('using no id should fail', function (done) { +// delete validParams.id; + +// postUninstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using unknown id should fail', function (done) { +// validParams.id = 'unknown'; + +// postUninstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.false; +// node.expect(res.body).to.have.property('error'); +// done(); +// }); +// }); + +// it('using valid params should be ok', function (done) { +// postUninstall(validParams, function (err, res) { +// node.expect(res.body).to.have.property('success').to.be.true; +// done(); +// }); +// }); +// }); diff --git a/test/api/delegates.js b/test/api/delegates.js index 78285b42..95ebd397 100644 --- a/test/api/delegates.js +++ b/test/api/delegates.js @@ -41,7 +41,7 @@ describe('PUT /api/accounts/delegates without funds', function () { secret: account.password, delegates: ['+' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM/); done(); }); @@ -52,7 +52,7 @@ describe('PUT /api/accounts/delegates without funds', function () { secret: account.password, delegates: ['-' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM/); done(); }); @@ -72,7 +72,7 @@ describe('PUT /api/delegates without funds', function () { secret: account.password, username: account.username }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM/); done(); }); @@ -88,9 +88,9 @@ describe('PUT /api/accounts/delegates with funds', function () { amount: node.randomADM(), recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); - node.expect(res.body.transactionId).to.be.not.empty; + node.expect(res.body.transactionId).not.to.be.empty; done(); }); }); @@ -108,7 +108,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: votedDelegate }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('Failed to validate vote schema:'); done(); }); @@ -121,7 +121,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: votedDelegate }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('Failed to validate vote schema:'); done(); }); @@ -134,7 +134,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: votedDelegate }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body).to.have.property('error').to.equal('Multiple votes for same delegate are not allowed'); done(); @@ -146,7 +146,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['+' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.type).to.equal(node.txTypes.VOTE); node.expect(res.body.transaction.amount).to.equal(0); @@ -161,7 +161,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['+' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error.toLowerCase()).to.contain('already voted'); done(); @@ -173,7 +173,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['-' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.type).to.equal(node.txTypes.VOTE); node.expect(res.body.transaction.amount).to.equal(0); @@ -188,7 +188,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['-' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); node.expect(res.body.error.toLowerCase()).to.contain('not voted'); done(); @@ -200,7 +200,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: '', delegates: ['+' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('String is too short '); done(); }); @@ -211,7 +211,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: '', delegates: ['-' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('String is too short '); done(); }); @@ -222,7 +222,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['+'] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('Invalid vote format'); done(); }); @@ -233,7 +233,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: ['-'] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.include('Invalid vote format'); done(); }); @@ -244,7 +244,7 @@ describe('PUT /api/accounts/delegates with funds', function () { secret: account.password, delegates: '' }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Failed to validate vote schema: Expected type array but found type string'); done(); }); @@ -270,9 +270,9 @@ describe('PUT /api/delegates with funds', function () { amount: node.randomADM(), recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); - node.expect(res.body.transactionId).to.be.not.empty; + node.expect(res.body.transactionId).not.to.be.empty; node.onNewBlock(function (err) { done(); }); @@ -283,7 +283,7 @@ describe('PUT /api/delegates with funds', function () { validParams.secret = ''; putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -293,7 +293,7 @@ describe('PUT /api/delegates with funds', function () { validParams.secret = []; putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -303,7 +303,7 @@ describe('PUT /api/delegates with funds', function () { validParams.username = '~!@#$%^&*()_+.,?/'; putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -313,7 +313,7 @@ describe('PUT /api/delegates with funds', function () { validParams.username = 'ABCDEFGHIJKLMNOPQRSTU'; putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -323,7 +323,7 @@ describe('PUT /api/delegates with funds', function () { validParams.username = ''; putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -333,7 +333,7 @@ describe('PUT /api/delegates with funds', function () { validParams.username = account.username.toUpperCase(); putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.fee).to.equal(node.fees.delegateRegistrationFee); node.expect(res.body.transaction).to.have.property('asset').that.is.an('object'); @@ -347,12 +347,12 @@ describe('PUT /api/delegates with funds', function () { it('using same account twice should fail', function (done) { putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.onNewBlock(function (err) { putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -362,13 +362,13 @@ describe('PUT /api/delegates with funds', function () { it('using existing username but different case should fail', function (done) { putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.onNewBlock(function (err) { validParams.username = validParams.username.toUpperCase(); putDelegates(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -411,7 +411,7 @@ describe('GET /api/delegates (cache)', function () { url = '/api/delegates'; node.get(url, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); var response = res.body; cache.getJsonForKey(url, function (err, res) { @@ -429,11 +429,11 @@ describe('GET /api/delegates (cache)', function () { params = 'orderBy=' + orderBy; node.get(url + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid sort field'); cache.getJsonForKey(url + params, function (err, res) { node.expect(err).to.not.exist; - node.expect(res).to.eql(null); + node.expect(res).to.be.null; done(err, res); }); }); @@ -444,18 +444,18 @@ describe('GET /api/delegates (cache)', function () { url = '/api/delegates'; node.get(url, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); var response = res.body; - cache.getJsonForKey(url, function (err, res) { + cache.getJsonForKey(url, function (err, beforeCachedResponse) { node.expect(err).to.not.exist; - node.expect(res).to.eql(response); + node.expect(beforeCachedResponse).to.eql(response); node.onNewRound(function (err) { node.expect(err).to.not.exist; - cache.getJsonForKey(url, function (err, res) { + cache.getJsonForKey(url, function (err, afterCachedResponse) { node.expect(err).to.not.exist; - node.expect(res).to.eql(null); - done(err, res); + node.expect(afterCachedResponse).to.not.eql(beforeCachedResponse); + done(); }); }); }); @@ -466,7 +466,7 @@ describe('GET /api/delegates (cache)', function () { describe('GET /api/delegates', function () { it('using no params should be ok', function (done) { node.get('/api/delegates', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); node.expect(res.body.delegates[0]).to.have.property('username'); @@ -484,7 +484,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid sort field'); done(); }); @@ -495,7 +495,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -507,7 +507,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -519,7 +519,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); for (var i = 0; i < res.body.delegates.length; i++) { @@ -536,7 +536,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); for (var i = 0; i < res.body.delegates.length; i++) { @@ -553,7 +553,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); for (var i = 0; i < res.body.delegates.length; i++) { @@ -570,7 +570,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); for (var i = 0; i < res.body.delegates.length; i++) { @@ -590,7 +590,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); for (var i = 0; i < res.body.delegates.length; i++) { @@ -608,7 +608,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -620,7 +620,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -632,7 +632,7 @@ describe('GET /api/delegates', function () { var params = 'orderBy=' + orderBy; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -644,7 +644,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Expected type integer but found type string'); done(); }); @@ -655,7 +655,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); done(); }); @@ -666,7 +666,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 0 is less than minimum 1'); done(); }); @@ -677,7 +677,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(1); done(); @@ -689,7 +689,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -701,7 +701,7 @@ describe('GET /api/delegates', function () { var params = 'limit=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 102 is greater than maximum 101'); done(); }); @@ -712,7 +712,7 @@ describe('GET /api/delegates', function () { var params = 'offset=' + limit; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Expected type integer but found type string'); done(); }); @@ -723,7 +723,7 @@ describe('GET /api/delegates', function () { var params = 'offset=' + offset; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.lengthOf(101); done(); @@ -735,7 +735,7 @@ describe('GET /api/delegates', function () { var params = 'offset=' + offset; node.get('/api/delegates?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 0'); done(); }); @@ -745,7 +745,7 @@ describe('GET /api/delegates', function () { var delegatesSortFields = ['approval', 'productivity', 'rank', 'vote']; node.async.each(delegatesSortFields, function (sortField, cb) { node.get('/api/delegates?orderBy=' + sortField, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); var dividedIndices = res.body.delegates.reduce(function (memo, peer, index) { @@ -772,7 +772,7 @@ describe('GET /api/delegates', function () { describe('GET /api/delegates/count', function () { it('should be ok', function (done) { node.get('/api/delegates/count', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('count').to.be.at.least(101); done(); }); @@ -788,9 +788,9 @@ describe('GET /api/delegates/voters', function () { amount: node.randomADM(), recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); - node.expect(res.body.transactionId).to.be.not.empty; + node.expect(res.body.transactionId).not.to.be.empty; node.onNewBlock(function (err) { done(); }); @@ -802,28 +802,18 @@ describe('GET /api/delegates/voters', function () { secret: account.password, delegates: ['+' + node.eAccount.publicKey] }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(); }); }); }); - it('using no publicKey should be ok', function (done) { - var params = 'publicKey='; - - node.get('/api/delegates/voters?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('accounts').that.is.an('array').that.is.empty; - done(); - }); - }); - it('using invalid publicKey should fail', function (done) { var params = 'publicKey=' + 'notAPublicKey'; node.get('/api/delegates/voters?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -834,7 +824,7 @@ describe('GET /api/delegates/voters', function () { node.onNewBlock(function (err) { node.get('/api/delegates/voters?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('accounts').that.is.an('array'); var flag = 0; for (var i = 0; i < res.body.accounts.length; i++) { @@ -854,7 +844,7 @@ describe('GET /api/delegates/search', function () { it('using no criteria should fail', function (done) { node.get('/api/delegates/search', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -864,7 +854,7 @@ describe('GET /api/delegates/search', function () { var q = ''; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -874,7 +864,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; // 1 character node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); done(); }); @@ -884,7 +874,7 @@ describe('GET /api/delegates/search', function () { var q = 'g'; // 1 character node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); done(); }); @@ -894,7 +884,7 @@ describe('GET /api/delegates/search', function () { var q = 'genesis_123456789012'; // 20 characters node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); done(); }); @@ -904,7 +894,7 @@ describe('GET /api/delegates/search', function () { var q = 'genesis_1234567890123'; // 21 characters node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -914,7 +904,7 @@ describe('GET /api/delegates/search', function () { var q = 'lo'; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(2); done(); @@ -925,7 +915,7 @@ describe('GET /api/delegates/search', function () { var q = 'love'; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(1); done(); @@ -936,7 +926,7 @@ describe('GET /api/delegates/search', function () { var q = 'market'; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(1); node.expect(res.body.delegates[0]).to.have.property('rank').that.is.an('number'); @@ -958,7 +948,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(101); done(); @@ -970,7 +960,7 @@ describe('GET /api/delegates/search', function () { var limit = 'one'; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -981,7 +971,7 @@ describe('GET /api/delegates/search', function () { var limit = -100; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -992,7 +982,7 @@ describe('GET /api/delegates/search', function () { var limit = -1; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -1003,7 +993,7 @@ describe('GET /api/delegates/search', function () { var limit = 0; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -1014,7 +1004,7 @@ describe('GET /api/delegates/search', function () { var limit = 1; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(1); done(); @@ -1026,7 +1016,7 @@ describe('GET /api/delegates/search', function () { var limit = 1000; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates.length).to.be.at.least(101); done(); @@ -1038,7 +1028,7 @@ describe('GET /api/delegates/search', function () { var limit = 1001; node.get('/api/delegates/search?q=' + q + '&limit=' + limit, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -1048,7 +1038,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; node.get('/api/delegates/search?q=' + q + '&orderBy=unknown:asc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -1058,7 +1048,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; node.get('/api/delegates/search?q=' + q, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(101); for (let i = 0; i < res.body.delegates.length - 1; i++) { @@ -1072,7 +1062,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; node.get('/api/delegates/search?q=' + q + '&orderBy=username:asc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(101); for (let i = 0; i < res.body.delegates.length - 1; i++) { @@ -1087,7 +1077,7 @@ describe('GET /api/delegates/search', function () { var q = '%'; node.get('/api/delegates/search?q=' + q + '&orderBy=username:desc', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); node.expect(res.body.delegates).to.have.length(101); for (let i = 0; i < res.body.delegates.length - 1; i++) { @@ -1102,7 +1092,7 @@ describe('GET /api/delegates/search', function () { describe('GET /api/delegates/forging/status', function () { it('using no params should be ok', function (done) { node.get('/api/delegates/forging/status', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); done(); @@ -1111,7 +1101,7 @@ describe('GET /api/delegates/forging/status', function () { it('using invalid publicKey should fail', function (done) { node.get('/api/delegates/forging/status?publicKey=' + 'invalidPublicKey', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Object didn\'t pass validation for format publicKey: invalidPublicKey'); done(); }); @@ -1119,7 +1109,7 @@ describe('GET /api/delegates/forging/status', function () { it('using empty publicKey should be ok', function (done) { node.get('/api/delegates/forging/status?publicKey=', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); done(); @@ -1128,7 +1118,7 @@ describe('GET /api/delegates/forging/status', function () { it('using disabled publicKey should be ok', function (done) { node.get('/api/delegates/forging/status?publicKey=' + 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.false; done(); }); @@ -1136,7 +1126,7 @@ describe('GET /api/delegates/forging/status', function () { it('using enabled publicKey should be ok', function (done) { node.get('/api/delegates/forging/status?publicKey=' + 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.true; done(); }); @@ -1148,14 +1138,14 @@ describe('POST /api/delegates/forging/disable', function () { before(function (done) { node.get('/api/delegates/forging/status?publicKey=' + testDelegate.publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.a('boolean'); if (!res.body.enabled) { node.post('/api/delegates/forging/enable', { publicKey: testDelegate.publicKey, secret: testDelegate.secret }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('address').equal(testDelegate.address); done(); }); @@ -1166,7 +1156,7 @@ describe('POST /api/delegates/forging/disable', function () { it('using no params should fail', function (done) { node.post('/api/delegates/forging/disable', {}, function (err, res) { - node.expect(res.body).to.have.property('success').not.to.be.ok; + node.expect(res.body).to.have.property('success').not.to.be.true; node.expect(res.body).to.have.property('error').to.be.a('string').and.to.contain('Missing required property: secret'); done(); }); @@ -1177,7 +1167,7 @@ describe('POST /api/delegates/forging/disable', function () { publicKey: testDelegate.publicKey, secret: 'invalid secret' }, function (err, res) { - node.expect(res.body).to.have.property('success').not.to.be.ok; + node.expect(res.body).to.have.property('success').not.to.be.true; node.expect(res.body).to.have.property('error').to.be.a('string').and.to.contain('invalid secret'); done(); }); @@ -1188,7 +1178,7 @@ describe('POST /api/delegates/forging/disable', function () { publicKey: testDelegate.publicKey, secret: testDelegate.secret }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('address').equal(testDelegate.address); done(); }); @@ -1200,14 +1190,14 @@ describe('POST /api/delegates/forging/enable', function () { before(function (done) { node.get('/api/delegates/forging/status?publicKey=' + testDelegate.publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('enabled').to.be.a('boolean'); if (res.body.enabled) { node.post('/api/delegates/forging/disable', { publicKey: testDelegate.publicKey, secret: testDelegate.secret }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('address').equal(testDelegate.address); done(); }); @@ -1219,7 +1209,7 @@ describe('POST /api/delegates/forging/enable', function () { it('using no params should fail', function (done) { node.post('/api/delegates/forging/enable', {}, function (err, res) { - node.expect(res.body).to.have.property('success').not.to.be.ok; + node.expect(res.body).to.have.property('success').not.to.be.true; node.expect(res.body).to.have.property('error').to.be.a('string').and.to.contain('Missing required property: secret'); done(); }); @@ -1230,7 +1220,7 @@ describe('POST /api/delegates/forging/enable', function () { publicKey: testDelegate.publicKey, secret: 'invalid secret' }, function (err, res) { - node.expect(res.body).to.have.property('success').not.to.be.ok; + node.expect(res.body).to.have.property('success').not.to.be.true; node.expect(res.body).to.have.property('error').to.be.a('string').and.to.contain('invalid secret'); done(); }); @@ -1241,7 +1231,7 @@ describe('POST /api/delegates/forging/enable', function () { publicKey: testDelegate.publicKey, secret: testDelegate.secret }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('address').equal(testDelegate.address); done(); }); @@ -1269,7 +1259,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { it('using no params should fail', function (done) { node.get('/api/delegates/forging/getForgedByAccount', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Missing required property: generatorPublicKey'); done(); }); @@ -1280,7 +1270,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { delete validParams.end; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fees').that.is.a('string'); node.expect(res.body).to.have.property('rewards').that.is.a('string'); node.expect(res.body).to.have.property('forged').that.is.a('string'); @@ -1290,7 +1280,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { it('using valid params with borders should be ok', function (done) { node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fees').that.is.a('string').and.eql('0'); node.expect(res.body).to.have.property('rewards').that.is.a('string').and.eql('0'); node.expect(res.body).to.have.property('forged').that.is.a('string').and.eql('0'); @@ -1305,7 +1295,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { delete validParams.end; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Account not found'); done(); }); @@ -1315,7 +1305,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { validParams.generatorPublicKey = node.randomAccount().publicKey.toString('hex'); node.get(encodeURI('/api/delegates/forging/getForgedByAccount?' + buildParams()), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Account not found or is not a delegate'); done(); }); @@ -1325,7 +1315,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { validParams.generatorPublicKey = 'invalidPublicKey'; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Object didn\'t pass validation for format publicKey: invalidPublicKey'); done(); }); @@ -1335,7 +1325,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { delete validParams.start; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fees').that.is.a('string').and.eql('0'); node.expect(res.body).to.have.property('rewards').that.is.a('string').and.eql('0'); node.expect(res.body).to.have.property('forged').that.is.a('string').and.eql('0'); @@ -1348,7 +1338,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { delete validParams.end; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('fees').that.is.a('string'); node.expect(res.body).to.have.property('rewards').that.is.a('string'); node.expect(res.body).to.have.property('forged').that.is.a('string'); @@ -1361,7 +1351,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { validParams.start = 'one'; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Expected type integer but found type string'); done(); }); @@ -1371,7 +1361,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { validParams.end = 'two'; node.get('/api/delegates/forging/getForgedByAccount?' + buildParams(), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.eql('Expected type integer but found type string'); done(); }); @@ -1381,7 +1371,7 @@ describe('GET /api/delegates/forging/getForgedByAccount', function () { describe('GET /api/delegates/getNextForgers', function () { it('using no params should be ok', function (done) { node.get('/api/delegates/getNextForgers', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('currentBlock').that.is.a('number'); node.expect(res.body).to.have.property('currentBlockSlot').that.is.a('number'); node.expect(res.body).to.have.property('currentSlot').that.is.a('number'); @@ -1393,7 +1383,7 @@ describe('GET /api/delegates/getNextForgers', function () { it('using limit === 1 should be ok', function (done) { node.get('/api/delegates/getNextForgers?' + 'limit=1', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('currentBlock').that.is.a('number'); node.expect(res.body).to.have.property('currentBlockSlot').that.is.a('number'); node.expect(res.body).to.have.property('currentSlot').that.is.a('number'); @@ -1405,7 +1395,7 @@ describe('GET /api/delegates/getNextForgers', function () { it('using limit === 101 should be ok', function (done) { node.get('/api/delegates/getNextForgers?' + 'limit=101', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('currentBlock').that.is.a('number'); node.expect(res.body).to.have.property('currentBlockSlot').that.is.a('number'); node.expect(res.body).to.have.property('currentSlot').that.is.a('number'); diff --git a/test/api/loader.js b/test/api/loader.js index 14d1f114..9266ff58 100644 --- a/test/api/loader.js +++ b/test/api/loader.js @@ -5,7 +5,7 @@ var node = require('./../node.js'); describe('GET /api/loader/status/ping', function () { it('should be ok', function (done) { node.get('/api/loader/status/ping', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -14,7 +14,7 @@ describe('GET /api/loader/status/ping', function () { describe('GET /api/loader/status/sync', function () { it('should be ok', function (done) { node.get('/api/loader/status/sync', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('syncing').to.a('boolean'); node.expect(res.body).to.have.property('blocks').to.be.a('number'); node.expect(res.body).to.have.property('height').to.be.a('number'); diff --git a/test/api/multisignatures.js b/test/api/multisignatures.js index 9bdca71e..2658e8cc 100644 --- a/test/api/multisignatures.js +++ b/test/api/multisignatures.js @@ -33,7 +33,7 @@ function sendADM (account, i, done) { amount: randomADM, recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; if (res.body.success && i != null) { accounts[i].balance = randomADM / node.normalizer; } @@ -47,7 +47,7 @@ function sendADMFromMultisigAccount (password, amount, recipient, done) { amount: amount, recipientId: recipient }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); done(err, res.body.transactionId); }); @@ -136,7 +136,7 @@ describe('PUT /api/multisignatures', function () { validParams.secret = node.randomAccount().password; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); done(); }); @@ -146,7 +146,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup = []; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Array is too short (0), minimum 1'); done(); }); @@ -157,7 +157,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup.push('+' + multisigAccount.publicKeyHex); //publicKey node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid multisignature keysgroup. Can not contain sender'); done(); }); @@ -169,7 +169,7 @@ describe('PUT /api/multisignatures', function () { }); node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid math operator in multisignature keysgroup'); done(); }); @@ -181,7 +181,7 @@ describe('PUT /api/multisignatures', function () { }); node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid math operator in multisignature keysgroup'); done(); }); @@ -192,7 +192,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup.push(validParams.keysgroup[1]); node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Encountered duplicate public key in multisignature keysgroup'); done(); }); @@ -203,7 +203,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup.push(null); node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid member in keysgroup'); done(); }); @@ -213,7 +213,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup = []; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Array is too short (0), minimum 1'); done(); }); @@ -225,7 +225,7 @@ describe('PUT /api/multisignatures', function () { }); node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Array is too long (16), maximum 15'); done(); }); @@ -236,7 +236,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = validParams.keysgroup.length + 1; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid multisignature min. Must be less than or equal to keysgroup size'); done(); }); @@ -246,7 +246,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = constants.multisigConstraints.min.maximum + 1; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 16 is greater than maximum 15'); done(); }); @@ -256,7 +256,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = 0; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 0 is less than minimum 1'); done(); }, true); @@ -266,7 +266,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup = []; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -276,7 +276,7 @@ describe('PUT /api/multisignatures', function () { delete validParams.keysgroup; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -286,7 +286,7 @@ describe('PUT /api/multisignatures', function () { validParams.keysgroup = 'invalid'; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -303,7 +303,7 @@ describe('PUT /api/multisignatures', function () { multiSigTx.keysgroup.push(null); node.put('/api/multisignatures', multiSigTx, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid member in keysgroup'); done(); }); @@ -320,7 +320,7 @@ describe('PUT /api/multisignatures', function () { multiSigTx.keysgroup.push('+' + node.eAccount.publicKey + 'A'); node.put('/api/multisignatures', multiSigTx, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid public key in multisignature keysgroup'); done(); }); @@ -330,7 +330,7 @@ describe('PUT /api/multisignatures', function () { delete validParams.secret; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -340,7 +340,7 @@ describe('PUT /api/multisignatures', function () { validParams.secret = multisigAccount.password + 'invalid'; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -350,7 +350,7 @@ describe('PUT /api/multisignatures', function () { delete validParams.lifetime; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -360,7 +360,7 @@ describe('PUT /api/multisignatures', function () { validParams.lifetime = 'invalid'; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -370,7 +370,7 @@ describe('PUT /api/multisignatures', function () { validParams.lifetime = constants.multisigConstraints.lifetime.maximum + 1; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 73 is greater than maximum 72'); done(); }); @@ -380,7 +380,7 @@ describe('PUT /api/multisignatures', function () { validParams.lifetime = 0; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -390,7 +390,7 @@ describe('PUT /api/multisignatures', function () { validParams.lifetime = -1; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -400,7 +400,7 @@ describe('PUT /api/multisignatures', function () { delete validParams.min; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -410,7 +410,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = 'invalid'; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -420,7 +420,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = totalMembers + 5; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -430,7 +430,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = 0; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -440,7 +440,7 @@ describe('PUT /api/multisignatures', function () { validParams.min = -1; node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -470,7 +470,7 @@ describe('PUT /api/multisignatures', function () { }; node.put('/api/multisignatures', params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -485,7 +485,7 @@ describe('PUT /api/multisignatures', function () { }; node.put('/api/multisignatures', params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; done(); }); @@ -494,7 +494,7 @@ describe('PUT /api/multisignatures', function () { it('using valid params should be ok when min 15 and keysgroup array is 15', function (done) { node.put('/api/multisignatures', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; multiSigTx.txId = res.body.transactionId; multiSigTx.lifetime = validParams.lifetime; @@ -515,7 +515,7 @@ describe('GET /api/multisignatures/pending', function () { var publicKey = 1234; node.get('/api/multisignatures/pending?publicKey=' + publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -524,7 +524,7 @@ describe('GET /api/multisignatures/pending', function () { it('using no public key should be ok', function (done) { node.get('/api/multisignatures/pending?publicKey=', function (err, res) { node.expect(res.body).to.have.property('success'); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions.length).to.equal(0); done(); @@ -533,7 +533,7 @@ describe('GET /api/multisignatures/pending', function () { it('using valid public key should be ok', function (done) { node.get('/api/multisignatures/pending?publicKey=' + multisigAccount.publicKey, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions.length).to.be.at.least(1); @@ -575,7 +575,7 @@ describe('PUT /api/transactions', function () { sendADMFromMultisigAccount(multisigAccount.password, 100000000, node.iAccount.address, function (err, transactionId) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transactionId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(transactionId); done(); @@ -605,7 +605,7 @@ describe('POST /api/multisignatures/sign (group)', function () { validParams.secret = node.randomAccount().password; node.post('/api/multisignatures/sign', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -614,7 +614,7 @@ describe('POST /api/multisignatures/sign (group)', function () { validParams.secret = null; node.post('/api/multisignatures/sign', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -623,7 +623,7 @@ describe('POST /api/multisignatures/sign (group)', function () { validParams.secret = undefined; node.post('/api/multisignatures/sign', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -632,7 +632,7 @@ describe('POST /api/multisignatures/sign (group)', function () { confirmTransaction(multiSigTx.txId, passphrases.slice(0, (passphrases.length - 1)), function () { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -641,7 +641,7 @@ describe('POST /api/multisignatures/sign (group)', function () { it('using same signature again should fail', function (done) { node.post('/api/multisignatures/sign', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Transaction already signed'); done(); }); @@ -651,7 +651,7 @@ describe('POST /api/multisignatures/sign (group)', function () { node.post('/api/multisignatures/sign', validParams, function (err, res) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -662,7 +662,7 @@ describe('POST /api/multisignatures/sign (group)', function () { confirmTransaction(multiSigTx.txId, passphrases.slice(-1), function () { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(multiSigTx.txId); done(); @@ -701,7 +701,7 @@ describe('POST /api/multisignatures/sign (transaction)', function () { confirmTransaction(multiSigTx.txId, passphrases.slice(0, (multiSigTx.min - 1)), function () { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -710,7 +710,7 @@ describe('POST /api/multisignatures/sign (transaction)', function () { it('using same signature again should fail', function (done) { node.post('/api/multisignatures/sign', validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Transaction already signed'); done(); }); @@ -720,7 +720,7 @@ describe('POST /api/multisignatures/sign (transaction)', function () { node.post('/api/multisignatures/sign', validParams, function (err, res) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -731,7 +731,7 @@ describe('POST /api/multisignatures/sign (transaction)', function () { confirmTransaction(multiSigTx.txId, passphrases.slice(-1), function () { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + multiSigTx.txId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(multiSigTx.txId); done(); @@ -751,7 +751,7 @@ describe('POST /api/multisignatures/sign (regular account)', function () { amount: 1, recipientId: accounts[0].address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; transactionId = res.body.transactionId; done(); @@ -761,7 +761,7 @@ describe('POST /api/multisignatures/sign (regular account)', function () { it('should be impossible to sign the transaction', function (done) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transactionId, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(transactionId); confirmTransaction(transactionId, [multisigAccount.password], function (err, res) { @@ -775,7 +775,7 @@ describe('POST /api/multisignatures/sign (regular account)', function () { it('should have no pending multisignatures', function (done) { node.get('/api/multisignatures/pending?publicKey=' + accounts[0].publicKey, function (err, res) { node.expect(res.body).to.have.property('success'); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions.length).to.equal(0); done(); diff --git a/test/api/peer.blocks.js b/test/api/peer.blocks.js index 316a4134..5b0cac03 100644 --- a/test/api/peer.blocks.js +++ b/test/api/peer.blocks.js @@ -85,7 +85,7 @@ describe('GET /peer/blocks/common', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -95,7 +95,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Missing required property: ids: #/'); done(); }); @@ -105,7 +105,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids="";"";""') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid block id sequence'); done(); }); @@ -115,7 +115,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids=\'\',\'\',\'\'') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid block id sequence'); done(); }); @@ -125,7 +125,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids="","",""') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid block id sequence'); done(); }); @@ -135,7 +135,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids=one,two,three') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Invalid block id sequence'); done(); }); @@ -145,7 +145,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids="1","2","3"') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('common').to.be.null; done(); }); @@ -155,7 +155,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids=\'1\',\'2\',\'3\'') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('common').to.be.null; done(); }); @@ -165,7 +165,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids=1,2,3') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('common').to.be.null; done(); }); @@ -175,7 +175,7 @@ describe('GET /peer/blocks/common', function () { node.get('/peer/blocks/common?ids=' + [genesisblock.id.toString(), '2', '3'].join(',')) .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('common').to.be.an('object'); node.expect(res.body.common).to.have.property('height').that.is.a('number'); node.expect(res.body.common).to.have.property('id').that.is.a('string'); @@ -192,7 +192,7 @@ describe('POST /peer/blocks', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -202,7 +202,7 @@ describe('POST /peer/blocks', function () { node.post('/peer/blocks') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.contain('Failed to validate block schema'); done(); }); @@ -215,7 +215,7 @@ describe('POST /peer/blocks', function () { node.post('/peer/blocks', { block: genesisblock }) .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.contain('Failed to validate block schema'); genesisblock.blockSignature = blockSignature; done(); @@ -226,7 +226,7 @@ describe('POST /peer/blocks', function () { node.post('/peer/blocks', { block: testBlock }) .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('blockId').to.equal('18267398587476633612'); done(); }); diff --git a/test/api/peer.js b/test/api/peer.js index 14494afc..ef5dd0d8 100644 --- a/test/api/peer.js +++ b/test/api/peer.js @@ -18,7 +18,7 @@ describe('GET /peer/list', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -29,7 +29,7 @@ describe('GET /peer/list', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); node.expect(res.body).to.have.property('expected').to.eql(packageJSON.config.minVersion); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); @@ -41,7 +41,7 @@ describe('GET /peer/list', function () { node.get('/peer/list') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); res.body.peers.forEach(function (peer) { node.expect(peer).to.have.property('ip').that.is.a('string'); @@ -60,7 +60,7 @@ describe('GET /peer/list', function () { node.get('/peer/list') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); res.body.peers.forEach(function (peer) { node.expect(peer).to.have.property('ip').that.is.a('string'); @@ -77,7 +77,7 @@ describe('GET /peer/height', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -88,7 +88,7 @@ describe('GET /peer/height', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); node.expect(res.body).to.have.property('expected').to.eql(packageJSON.config.minVersion); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); @@ -100,7 +100,7 @@ describe('GET /peer/height', function () { node.get('/peer/height') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.be.an('object').that.has.property('height'); node.expect(res.body.height).to.be.a('number').to.be.above(1); done(); diff --git a/test/api/peer.signatures.js b/test/api/peer.signatures.js index 7d85b111..dbb88c62 100644 --- a/test/api/peer.signatures.js +++ b/test/api/peer.signatures.js @@ -34,7 +34,7 @@ describe('GET /peer/signatures', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -45,7 +45,7 @@ describe('GET /peer/signatures', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); node.expect(res.body).to.have.property('expected').to.eql(packageJSON.config.minVersion); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); @@ -57,7 +57,7 @@ describe('GET /peer/signatures', function () { node.get('/peer/signatures') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('signatures').that.is.an('array'); done(); }); @@ -89,7 +89,7 @@ describe('POST /peer/signatures', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -100,7 +100,7 @@ describe('POST /peer/signatures', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); node.expect(res.body).to.have.property('expected').to.eql(packageJSON.config.minVersion); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); @@ -114,7 +114,7 @@ describe('POST /peer/signatures', function () { node.post('/peer/signatures', validParams) .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid signature body'); done(); }); @@ -126,7 +126,7 @@ describe('POST /peer/signatures', function () { node.post('/peer/signatures', validParams) .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Error processing signature: Transaction not found'); done(); }); @@ -135,12 +135,12 @@ describe('POST /peer/signatures', function () { // Don't check /peer/signatures // it('using processable signature should be ok', function (done) { // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; + // node.expect(res.body).to.have.property('success').to.be.true; // node.onNewBlock(function (err) { // node.post('/peer/signatures', validParams) // .end(function (err, res) { // node.debug('> Response:'.grey, JSON.stringify(res.body)); - // node.expect(res.body).to.have.property('success').to.be.ok; + // node.expect(res.body).to.have.property('success').to.be.true; // done(); // }); // }); @@ -169,7 +169,7 @@ describe('POST /peer/signatures', function () { eachSeriesCb(); }, function (err) { postTransactions(transactions, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(); }); @@ -186,7 +186,7 @@ describe('POST /peer/signatures', function () { transaction = node.lisk.multisignature.createMultisignature(owner.password, null, keysgroup, lifetime, min); postTransactions([transaction], function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(); }); @@ -197,7 +197,7 @@ describe('POST /peer/signatures', function () { var signature = node.lisk.multisignature.signTransaction(transaction, owner.password); postSignature(transaction, signature, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Error processing signature: Failed to verify signature'); done(); }); @@ -207,7 +207,7 @@ describe('POST /peer/signatures', function () { var signature = node.lisk.multisignature.signTransaction(transaction, coSigner1.password); postSignature(transaction, signature, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -216,7 +216,7 @@ describe('POST /peer/signatures', function () { node.onNewBlock(function (err) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -227,7 +227,7 @@ describe('POST /peer/signatures', function () { var signature = node.lisk.multisignature.signTransaction(transaction, coSigner2.password); postSignature(transaction, signature, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -235,7 +235,7 @@ describe('POST /peer/signatures', function () { it('using processable signature for coSigner2 should confirm the transaction', function (done) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(transaction.id); done(); @@ -257,7 +257,7 @@ describe('POST /peer/signatures', function () { transaction = node.lisk.multisignature.createTransaction('1L', 1, owner.password); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(); }); @@ -268,7 +268,7 @@ describe('POST /peer/signatures', function () { var signature = node.lisk.multisignature.signTransaction(transaction, coSigner1.password); postSignature(transaction, signature, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -277,7 +277,7 @@ describe('POST /peer/signatures', function () { node.onNewBlock(function (err) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -288,7 +288,7 @@ describe('POST /peer/signatures', function () { var signature = node.lisk.multisignature.signTransaction(transaction, coSigner2.password); postSignature(transaction, signature, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -296,7 +296,7 @@ describe('POST /peer/signatures', function () { it('using processable signature for coSigner2 should confirm the transaction', function (done) { node.onNewBlock(function (err) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction'); node.expect(res.body.transaction).to.have.property('id').to.equal(transaction.id); done(); diff --git a/test/api/peer.transactions.collision.js b/test/api/peer.transactions.collision.js index f538b50a..fb61ae4e 100644 --- a/test/api/peer.transactions.collision.js +++ b/test/api/peer.transactions.collision.js @@ -41,7 +41,7 @@ describe('POST /peer/transactions', function () { recipientId: collision.address }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(done); }); }); @@ -56,7 +56,7 @@ describe('POST /peer/transactions', function () { // }); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // node.expect(res.body).to.have.property('message').to.equal('Failed to verify signature'); // done(); // }); @@ -70,7 +70,7 @@ describe('POST /peer/transactions', function () { // }); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // node.expect(res.body).to.have.property('message').to.equal('Failed to verify signature'); // done(); // }); @@ -90,7 +90,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -103,7 +103,7 @@ describe('POST /peer/transactions', function () { // }); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // const pk1 = 'b26dd40ba33e4785e49ddc4f106c0493ed00695817235c778f487aea5866400a'; // const pk2 = 'ce33db918b059a6e99c402963b42cf51c695068007ef01d8c383bb8a41270263'; // node.expect(res.body).to.have.property('message').to.equal(`Invalid sender public key: ${pk1} expected: ${pk2}`); diff --git a/test/api/peer.transactions.delegates.js b/test/api/peer.transactions.delegates.js index 3cdece17..a27d80f2 100644 --- a/test/api/peer.transactions.delegates.js +++ b/test/api/peer.transactions.delegates.js @@ -20,7 +20,7 @@ describe('POST /peer/transactions', function () { describe('registering a delegate', function () { it('using undefined transaction', function (done) { postTransaction(undefined, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -36,7 +36,7 @@ describe('POST /peer/transactions', function () { delete transaction.asset; postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -51,7 +51,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Account does not have enough ADM/); done(); }); @@ -68,9 +68,9 @@ describe('POST /peer/transactions', function () { amount: node.fees.delegateRegistrationFee, recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); - node.expect(res.body.transactionId).to.be.not.empty; + node.expect(res.body.transactionId).not.to.be.empty; done(); }); }); @@ -88,7 +88,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -100,7 +100,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -113,7 +113,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); @@ -127,7 +127,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -164,11 +164,11 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function () { postTransaction(transaction2, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; done(); }); }); diff --git a/test/api/peer.transactions.main.js b/test/api/peer.transactions.main.js index c363e495..cd20184e 100644 --- a/test/api/peer.transactions.main.js +++ b/test/api/peer.transactions.main.js @@ -21,7 +21,7 @@ describe('GET /peer/transactions', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -32,9 +32,9 @@ describe('GET /peer/transactions', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); - node.expect(res.body).to.have.property('expected').to.eql('>=0.4.0'); + node.expect(res.body).to.have.property('expected').to.eql('>=0.6.0'); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); done(); }); @@ -43,7 +43,7 @@ describe('GET /peer/transactions', function () { it('using valid headers should be ok', function (done) { node.get('/peer/transactions') .end(function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').to.be.an('array'); done(); }); @@ -56,7 +56,7 @@ describe('POST /peer/transactions', function () { .set('nethash', 'incorrect') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body.expected).to.equal(node.config.nethash); done(); }); @@ -67,9 +67,9 @@ describe('POST /peer/transactions', function () { .set('version', '0.1.0a') .end(function (err, res) { node.debug('> Response:'.grey, JSON.stringify(res.body)); - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Request is made from incompatible version'); - node.expect(res.body).to.have.property('expected').to.eql('>=0.4.0'); + node.expect(res.body).to.have.property('expected').to.eql('>=0.6.0'); node.expect(res.body).to.have.property('received').to.eql('0.1.0a'); done(); }); @@ -87,7 +87,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); done(); }); @@ -102,11 +102,11 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Transaction is already processed: [0-9]+/); done(); }); @@ -122,12 +122,12 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Transaction is already /); done(); }); @@ -143,7 +143,7 @@ describe('POST /peer/transactions', function () { recipientId: account.address.toUpperCase() }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { var transaction2 = node.createSendTransaction({ @@ -152,11 +152,11 @@ describe('POST /peer/transactions', function () { recipientId: account.address.toLowerCase() }); postTransaction(transaction2, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { getAddress(account.address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('account').that.is.an('object'); node.expect(res.body.account).to.have.property('balance').to.equal('200000000'); done(); @@ -175,7 +175,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.eql('Missing recipient'); done(); }); @@ -189,7 +189,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -204,7 +204,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -220,7 +220,7 @@ describe('POST /peer/transactions', function () { transaction.id = node.getId(transaction); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -235,7 +235,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); done(); }); @@ -250,7 +250,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function () { @@ -263,7 +263,7 @@ describe('POST /peer/transactions', function () { node.async.doUntil(function (next) { postTransaction(transaction2, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Account does not have enough ADM: U[0-9]+ balance: 1e-8/); count++; return next(); @@ -288,7 +288,7 @@ describe('POST /peer/transactions', function () { transaction.id = node.getId(transaction); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -304,7 +304,7 @@ describe('POST /peer/transactions', function () { transaction.senderPublicKey = node.randomAccount().publicKeyHex; postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -320,7 +320,7 @@ describe('POST /peer/transactions', function () { transaction.signature = node.randomAccount().password; postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -336,7 +336,7 @@ describe('POST /peer/transactions', function () { transaction.blockId = genesisblock.id; postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -351,7 +351,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -366,7 +366,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message'); done(); }); @@ -382,7 +382,7 @@ describe('POST /peer/transactions', function () { it('should fail', function (done) { postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').equals('Invalid sender. Can not send from genesis account'); done(); }); diff --git a/test/api/peer.transactions.multisignatures.js b/test/api/peer.transactions.multisignatures.js index 7e46a6ea..b760e869 100644 --- a/test/api/peer.transactions.multisignatures.js +++ b/test/api/peer.transactions.multisignatures.js @@ -25,7 +25,7 @@ function sendADM (params, done) { var transaction = node.lisk.transaction.createTransaction(params.recipientId, params.amount, params.secret); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(err, res); }); @@ -42,7 +42,7 @@ describe('POST /peer/transactions', function () { var multiSigTx = node.lisk.multisignature.createMultisignature(multisigAccount.password, null, [node.randomAccount().publicKey], 1, 2); postTransaction(multiSigTx, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); done(); }); @@ -63,7 +63,7 @@ describe('POST /peer/transactions', function () { var multiSigTx = node.lisk.multisignature.createMultisignature(multisigAccount.password, null, ['+' + node.eAccount.publicKey, null], 1, 2); postTransaction(multiSigTx, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid member in keysgroup'); done(); }); @@ -78,7 +78,7 @@ describe('POST /peer/transactions', function () { '+' + memberAccount1.publicKey, '+' + memberAccount2.publicKey], 1, 2); postTransaction(multiSigTx, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid public key in multisignature keysgroup'); done(); }); diff --git a/test/api/peer.transactions.signatures.js b/test/api/peer.transactions.signatures.js index 4aea1164..f9e8ec01 100644 --- a/test/api/peer.transactions.signatures.js +++ b/test/api/peer.transactions.signatures.js @@ -28,7 +28,7 @@ function sendADM (params, done) { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { done(err, res); }); @@ -39,7 +39,7 @@ describe('POST /peer/transactions', function () { describe('enabling second signature', function () { it('using undefined transaction', function (done) { postTransaction(undefined, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -52,7 +52,7 @@ describe('POST /peer/transactions', function () { // delete transaction.asset; // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); // done(); // }); @@ -66,7 +66,7 @@ describe('POST /peer/transactions', function () { }; postSignatureTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); done(); }); @@ -95,7 +95,7 @@ describe('POST /peer/transactions', function () { }; postSignatureTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; // node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); done(); }); @@ -120,7 +120,7 @@ describe('POST /peer/transactions', function () { // var transaction = node.lisk.transaction.createTransaction('1L', 1, node.iAccount.password, account.secondPassword); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // done(); // }); // }); @@ -133,7 +133,7 @@ describe('POST /peer/transactions', function () { }); postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Missing sender second signature'); done(); }); @@ -151,7 +151,7 @@ describe('POST /peer/transactions', function () { // transaction.id = node.lisk.crypto.getId(transaction); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // node.expect(res.body).to.have.property('message').to.equal('Failed to verify second signature'); // done(); // }); @@ -167,7 +167,7 @@ describe('POST /peer/transactions', function () { // var transaction = node.lisk.transaction.createTransaction('1L', 1, account.password, account.secondPassword); // postTransaction(transaction, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; + // node.expect(res.body).to.have.property('success').to.be.true; // node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); // done(); // }); diff --git a/test/api/peer.transactions.stress.js b/test/api/peer.transactions.stress.js index 7a0eabc8..eb00476a 100644 --- a/test/api/peer.transactions.stress.js +++ b/test/api/peer.transactions.stress.js @@ -16,7 +16,7 @@ function postTransactions (transactions, done) { function sendADM (params, done) { node.put('/api/transactions', params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { return done(err, res); }); @@ -55,7 +55,7 @@ describe('POST /peer/transactions', function () { } postTransactions(bundled, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { next(); }); @@ -73,7 +73,7 @@ describe('POST /peer/transactions', function () { node.waitForBlocks(blocksToWait, function (err) { node.async.eachSeries(transactions, function (transaction, eachSeriesCb) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); return setImmediate(eachSeriesCb); }); @@ -104,7 +104,7 @@ describe('POST /peer/transactions', function () { transaction.fee = node.fees.transactionFee; postTransaction(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); transactions.push(transaction); count++; @@ -119,11 +119,11 @@ describe('POST /peer/transactions', function () { }); it('should confirm all single transactions', function (done) { - var blocksToWait = Math.ceil(maximum / node.constants.maxTxsPerBlock); + var blocksToWait = Math.ceil(maximum / node.constants.maxTxsPerBlock) * 5; node.waitForBlocks(blocksToWait, function (err) { node.async.eachSeries(transactions, function (transaction, eachSeriesCb) { node.get('/api/transactions/get?id=' + transaction.id, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); return setImmediate(eachSeriesCb); }); diff --git a/test/api/peer.transactions.votes.js b/test/api/peer.transactions.votes.js index 6c70ba67..a729aab1 100644 --- a/test/api/peer.transactions.votes.js +++ b/test/api/peer.transactions.votes.js @@ -11,23 +11,22 @@ var votedDelegates = []; function getDelegates (done) { node.get('/api/delegates', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; - node.expect(res.body).to.have.property('delegates').that.is.an('array'); + node.expect(res.body).to.have.property('success').to.be.true; + node.expect(res.body).to.have.property('delegates').that.is.an('array').that.has.lengthOf(101); return done(err, res); }); } function getVotes (address, done) { node.get('/api/accounts/delegates/?address=' + address, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('delegates').that.is.an('array'); return done(err, res); }); } function postVotes (params, done) { - var count = 0; - var blocksToWait = Math.ceil(params.delegates.length / node.constants.maxTxsPerBlock) + 12; + var blocksToWait = Math.ceil(params.delegates.length / node.constants.maxTxsPerBlock) * 20; node.async.eachSeries(params.delegates, function (delegate, eachCb) { let transaction = node.createVoteTransaction({ @@ -36,7 +35,7 @@ function postVotes (params, done) { }); // Don't sent requests too often — a node can miss some of them - node.waitMilliSeconds(600, function () { + node.waitMilliSeconds(4000, function () { postVote(transaction, function (err, res) { params.voteCb(err, res); return eachCb(); @@ -57,7 +56,7 @@ function postVote (transaction, done) { function sendADM (params, done) { node.put('/api/transactions', params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { return done(err, res); }); @@ -72,7 +71,7 @@ function registerDelegate (account, done) { }); node.post('/peer/transactions', { transaction: transaction }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.onNewBlock(function (err) { return done(err, res); }); @@ -116,14 +115,14 @@ describe('POST /peer/transactions', function () { passphrase: account.password, action: '-', voteCb: function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; } }, done); }); it('using undefined transaction', function (done) { postVote(undefined, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -138,7 +137,7 @@ describe('POST /peer/transactions', function () { delete transaction.asset; postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.contain('Invalid transaction body'); done(); }); @@ -151,7 +150,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote type'); done(); }); @@ -164,7 +163,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote format'); done(); }); @@ -177,7 +176,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote length'); done(); }); @@ -190,7 +189,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Invalid vote at index 0 - Invalid vote length'); done(); }); @@ -204,7 +203,7 @@ describe('POST /peer/transactions', function () { votes: [`+${delegate}`] }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; return seriesCb(); }); }, @@ -217,7 +216,7 @@ describe('POST /peer/transactions', function () { votes: [`+${delegate}`] }); postVote(transaction2, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; return seriesCb(); }); }, @@ -230,7 +229,7 @@ describe('POST /peer/transactions', function () { votes: [`+${delegate}`] }); postVote(transaction2, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; return seriesCb(); }); }, @@ -251,7 +250,7 @@ describe('POST /peer/transactions', function () { votes: [`-${delegate}`] }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { getVotes(account.address, function (err, res) { @@ -269,7 +268,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { getVotes(account.address, function (err, res) { @@ -287,7 +286,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { getVotes(account.address, function (err, res) { @@ -305,7 +304,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal(['Invalid transaction body - Failed to validate vote schema: Array is too long (', constants.maxVotesPerTransaction + 1, '), maximum ', constants.maxVotesPerTransaction].join('')); node.onNewBlock(function (err) { return done(err); @@ -319,7 +318,7 @@ describe('POST /peer/transactions', function () { passphrase: account.password, action: '+', voteCb: function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.a('string'); } }, done); @@ -339,7 +338,7 @@ describe('POST /peer/transactions', function () { }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal(['Invalid transaction body - Failed to validate vote schema: Array is too long (', constants.maxVotesPerTransaction + 1, '), maximum ', constants.maxVotesPerTransaction].join('')); node.onNewBlock(function (err) { return done(err); @@ -347,13 +346,13 @@ describe('POST /peer/transactions', function () { }); }); - it('removing votes from 101 delegates separately should be ok', function (done) { + it('removing votes from all delegates separately should be ok', function (done) { postVotes({ - delegates: delegates, + delegates: votedDelegates, passphrase: account.password, action: '-', voteCb: function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.a('string'); } }, done); @@ -397,7 +396,7 @@ describe('POST /peer/transactions after registering a new delegate', function () }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { return done(err); @@ -422,7 +421,7 @@ describe('POST /peer/transactions after registering a new delegate', function () passphrase: account.password, action: '+', voteCb: function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; } }, seriesCb); }, @@ -445,7 +444,7 @@ describe('POST /peer/transactions after registering a new delegate', function () }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('message').to.equal('Maximum number of 101 votes exceeded (1 too many)'); seriesCb(); }); @@ -468,7 +467,7 @@ describe('POST /peer/transactions after registering a new delegate', function () }); postVote(transaction, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').to.equal(transaction.id); node.onNewBlock(function (err) { return done(err); diff --git a/test/api/peers.js b/test/api/peers.js index 233ab400..ffb1fc34 100644 --- a/test/api/peers.js +++ b/test/api/peers.js @@ -6,7 +6,7 @@ var peersSortFields = require('../../sql/peers').sortFields; describe('GET /api/peers/version', function () { it('should be ok', function (done) { node.get('/api/peers/version', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('build').to.be.a('string'); node.expect(res.body).to.have.property('commit').to.be.a('string'); node.expect(res.body).to.have.property('version').to.be.a('string'); @@ -18,7 +18,7 @@ describe('GET /api/peers/version', function () { describe('GET /api/peers/count', function () { it('should be ok', function (done) { node.get('/api/peers/count', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('connected').that.is.a('number'); node.expect(res.body).to.have.property('disconnected').that.is.a('number'); node.expect(res.body).to.have.property('banned').that.is.a('number'); @@ -33,7 +33,7 @@ describe('GET /api/peers', function () { var params = 'ip=' + ip; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format ip: invalid'); done(); }); @@ -44,7 +44,7 @@ describe('GET /api/peers', function () { var params = 'ip=' + ip; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -54,7 +54,7 @@ describe('GET /api/peers', function () { var params = 'port=' + port; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 0 is less than minimum 1'); done(); }); @@ -65,7 +65,7 @@ describe('GET /api/peers', function () { var params = 'port=' + port; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -75,7 +75,7 @@ describe('GET /api/peers', function () { var params = 'port=' + port; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 65536 is greater than maximum 65535'); done(); }); @@ -86,7 +86,7 @@ describe('GET /api/peers', function () { var params = 'state=' + state; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); if (res.body.peers.length > 0) { for (var i = 0; i < res.body.peers.length; i++) { @@ -102,7 +102,7 @@ describe('GET /api/peers', function () { var params = 'state=' + state; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); if (res.body.peers.length > 0) { for (var i = 0; i < res.body.peers.length; i++) { @@ -118,7 +118,7 @@ describe('GET /api/peers', function () { var params = 'state=' + state; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); if (res.body.peers.length > 0) { for (var i = 0; i < res.body.peers.length; i++) { @@ -134,7 +134,7 @@ describe('GET /api/peers', function () { var params = 'state=' + state; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 3 is greater than maximum 2'); done(); }); @@ -145,7 +145,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -155,7 +155,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -165,7 +165,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('String is too long (65 chars), maximum 64'); done(); }); @@ -176,7 +176,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -186,7 +186,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -196,7 +196,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -206,7 +206,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -216,7 +216,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -226,7 +226,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -236,7 +236,7 @@ describe('GET /api/peers', function () { var params = 'os=' + os; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format os: freebsd10.3_RELEASE-p7-@'); done(); }); @@ -247,7 +247,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -257,7 +257,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format version: 9999.999.999'); done(); }); @@ -268,7 +268,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format version: 999.9999.999'); done(); }); @@ -279,7 +279,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format version: 999.999.9999'); done(); }); @@ -290,7 +290,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -300,7 +300,7 @@ describe('GET /api/peers', function () { var params = 'version=' + version; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format version: 999.999.999ab'); done(); }); @@ -311,7 +311,7 @@ describe('GET /api/peers', function () { // var params = 'broadhash=' + broadhash; // // node.get('/api/peers?' + params, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.not.ok; + // node.expect(res.body).to.have.property('success').to.be.false; // node.expect(res.body).to.have.property('error').to.equal('Object didn\'t pass validation for format hex: invalid'); // done(); // }); @@ -322,7 +322,7 @@ describe('GET /api/peers', function () { var params = 'broadhash=' + broadhash; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -332,7 +332,7 @@ describe('GET /api/peers', function () { var params = 'orderBy=' + orderBy; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); if (res.body.peers.length > 0) { @@ -350,7 +350,7 @@ describe('GET /api/peers', function () { it('using orderBy with any of sort fields should not place NULLs first', function (done) { node.async.each(peersSortFields, function (sortField, cb) { node.get('/api/peers?orderBy=' + sortField, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); var dividedIndices = res.body.peers.reduce(function (memo, peer, index) { @@ -378,7 +378,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Expected type integer but found type string'); done(); }); @@ -389,7 +389,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 1'); done(); }); @@ -400,7 +400,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 0 is less than minimum 1'); done(); }); @@ -411,7 +411,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); node.expect(res.body.peers.length).to.be.at.most(limit); done(); @@ -423,7 +423,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('peers').that.is.an('array'); node.expect(res.body.peers.length).to.be.at.most(limit); done(); @@ -435,7 +435,7 @@ describe('GET /api/peers', function () { var params = 'limit=' + limit; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value 101 is greater than maximum 100'); done(); }); @@ -446,7 +446,7 @@ describe('GET /api/peers', function () { var params = 'offset=' + offset; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Expected type integer but found type string'); done(); }); @@ -457,7 +457,7 @@ describe('GET /api/peers', function () { var params = 'offset=' + offset; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Value -1 is less than minimum 0'); done(); }); @@ -468,7 +468,7 @@ describe('GET /api/peers', function () { var params = 'offset=' + offset; node.get('/api/peers?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -486,7 +486,7 @@ describe('GET /api/peers/get', function () { it('using known ip address with no port should fail', function (done) { node.get('/api/peers/get?ip=127.0.0.1', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Missing required property: port'); done(); }); @@ -494,7 +494,7 @@ describe('GET /api/peers/get', function () { it('using valid port with no ip address should fail', function (done) { node.get('/api/peers/get?port=' + validParams.port, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Missing required property: ip'); done(); }); @@ -502,7 +502,7 @@ describe('GET /api/peers/get', function () { // it('using ip address and port of frozen peer should be ok', function (done) { // node.get('/api/peers/get?ip=127.0.0.1&port=' + frozenPeerPort, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; + // node.expect(res.body).to.have.property('success').to.be.true; // node.expect(res.body).to.have.property('peer').to.be.an('object'); // done(); // }); @@ -510,7 +510,7 @@ describe('GET /api/peers/get', function () { it('using unknown ip address and port should fail', function (done) { node.get('/api/peers/get?ip=0.0.0.0&port=' + validParams.port, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('Peer not found'); done(); }); @@ -520,7 +520,7 @@ describe('GET /api/peers/get', function () { describe('GET /api/peers/unknown', function () { it('should not to do anything', function (done) { node.get('/api/peers/unknown', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.equal('API endpoint not found'); done(); }); diff --git a/test/api/signatures.js b/test/api/signatures.js index 36bc7205..def68d09 100644 --- a/test/api/signatures.js +++ b/test/api/signatures.js @@ -27,7 +27,7 @@ function sendADM (account, done) { amount: randomADM, recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(err, res); }); } @@ -64,7 +64,7 @@ before(function (done) { delete validParams.secondSecret; putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -74,7 +74,7 @@ before(function (done) { delete validParams.secret; putTransaction(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -102,7 +102,7 @@ describe('PUT /api/signatures', function () { validParams.secondSecret = account3.password; putSignature(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: 0/); done(); }); @@ -112,7 +112,7 @@ describe('PUT /api/signatures', function () { validParams.secret = 'invalid'; putSignature(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/API error: Mnemonic string is invalid: invalid/); done(); }); @@ -122,7 +122,7 @@ describe('PUT /api/signatures', function () { delete validParams.secondSecret; putSignature(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Missing required property: secondSecret/); done(); }); @@ -130,7 +130,7 @@ describe('PUT /api/signatures', function () { it('using valid parameters should be ok', function (done) { putSignature(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction).to.have.property('type').to.equal(node.txTypes.SIGNATURE); node.expect(res.body.transaction).to.have.property('senderPublicKey').to.equal(account.publicKeyHex); @@ -157,7 +157,7 @@ describe('PUT /api/delegates from account with second signature enabled', functi delete validParams.secondSecret; putDelegate(validParams, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); diff --git a/test/api/transactions.js b/test/api/transactions.js index dc71324a..9aff64a9 100644 --- a/test/api/transactions.js +++ b/test/api/transactions.js @@ -47,7 +47,7 @@ function sendADM (account, amount, done) { amount: amount, recipientId: account.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; transactionList.push({ 'sender': node.iAccount.address, @@ -138,7 +138,7 @@ describe('GET /api/transactions (cache)', function () { ]; node.get(url + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); var response = res.body; cache.getJsonForKey(url + params.join('&'), function (err, res) { @@ -157,11 +157,11 @@ describe('GET /api/transactions (cache)', function () { ]; node.get(url + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); cache.getJsonForKey(url + params, function (err, res) { node.expect(err).to.not.exist; - node.expect(res).to.eql(null); + node.expect(res).to.be.null; done(err, res); }); }); @@ -188,7 +188,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(transactionList.length, limit); for (var i = 0; i < res.body.transactions.length; i++) { @@ -215,7 +215,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(transactionList.length, limit); for (var i = 0; i < res.body.transactions.length; i++) { @@ -243,7 +243,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(2, limit); node.expect(res.body.transactions[0].amount).to.be.equal(minAmount); @@ -273,7 +273,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(2, limit); node.expect(res.body.transactions[0].fee).to.be.equal(minFee); @@ -306,7 +306,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(transactionList.length, limit); for (var i = 0; i < res.body.transactions.length; i++) { @@ -335,7 +335,7 @@ describe('GET /api/transactions', function () { ]; node.get(encodeURI('/api/transactions?' + params.join('&')), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body.transactions).to.have.length.within(transactionList.length, limit); for (var i = 0; i < res.body.transactions.length; i++) { @@ -362,7 +362,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -374,7 +374,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -386,7 +386,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -398,7 +398,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -409,7 +409,7 @@ describe('GET /api/transactions', function () { var params = 'type=' + type; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); for (var i = 0; i < res.body.transactions.length; i++) { if (res.body.transactions[i]) { @@ -425,7 +425,7 @@ describe('GET /api/transactions', function () { const params = 'types=' + types.join(','); node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); for (var i = 0; i < res.body.transactions.length; i++) { if (res.body.transactions[i]) { @@ -438,14 +438,14 @@ describe('GET /api/transactions', function () { it('using noClutter param should be ok', function (done) { node.get('/api/transactions?noClutter=1', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); for (var i = 0; i < res.body.transactions.length; i++) { if (res.body.transactions[i]) { try { - node.expect(res.body.transactions[i].type).to.be.not.equal(8); + node.expect(res.body.transactions[i].type).not.to.be.equal(8); } catch (e) { - node.expect(res.body.transactions[i].amount).to.be.not.equal(0); + node.expect(res.body.transactions[i].amount).not.to.be.equal(0); } } } @@ -455,7 +455,7 @@ describe('GET /api/transactions', function () { it('using no params should be ok', function (done) { node.get('/api/transactions', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); const transactions = res.body.transactions.sort((x, y) => y.amount - x.amount); for (var i = 0; i < transactions.length; i++) { @@ -471,7 +471,7 @@ describe('GET /api/transactions', function () { var params = 'fromUnixTime=1464109199'; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -481,7 +481,7 @@ describe('GET /api/transactions', function () { var params = 'toUnixTime=1464109200'; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -492,7 +492,7 @@ describe('GET /api/transactions', function () { var params = 'limit=' + limit; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -503,7 +503,7 @@ describe('GET /api/transactions', function () { var params = 'orderBy=' + orderBy; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); var flag = 0; @@ -526,7 +526,7 @@ describe('GET /api/transactions', function () { // var params = 'offset=' + offset; // // node.get('/api/transactions?' + params, function (err, res) { - // node.expect(res.body).to.have.property('success').to.be.ok; + // node.expect(res.body).to.have.property('success').to.be.true; // node.expect(res.body).to.have.property('transactions').that.is.an('array'); // if (res.body.transactions.length > 0) { // const transactions = res.body.transactions; @@ -541,7 +541,7 @@ describe('GET /api/transactions', function () { var params = 'offset=' + offset; node.get('/api/transactions?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -558,7 +558,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -575,7 +575,7 @@ describe('GET /api/transactions', function () { ]; node.get('/api/transactions?' + params.join('&'), function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -584,7 +584,7 @@ describe('GET /api/transactions', function () { it('using orderBy with any of sort fields should not place NULLs first', function (done) { node.async.each(transactionSortFields, function (sortField, cb) { node.get('/api/transactions?orderBy=' + sortField, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); var dividedIndices = res.body.transactions.reduce(function (memo, peer, index) { @@ -614,7 +614,7 @@ describe('GET /api/transactions/get?id=', function () { var params = 'id=' + transactionInCheck.txId; node.get('/api/transactions/get?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.id).to.equal(transactionInCheck.txId); node.expect(res.body.transaction.amount / node.normalizer).to.equal(transactionInCheck.netSent); @@ -630,7 +630,7 @@ describe('GET /api/transactions/get?id=', function () { var params = 'id=invalid'; node.get('/api/transactions/get?' + params, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -640,7 +640,7 @@ describe('GET /api/transactions/get?id=', function () { describe('GET /api/transactions/count', function () { it('should be ok', function (done) { node.get('/api/transactions/count', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('confirmed').that.is.an('number'); node.expect(res.body).to.have.property('queued').that.is.an('number'); node.expect(res.body).to.have.property('multisignature').that.is.an('number'); @@ -665,7 +665,7 @@ describe('GET /api/transactions/queued/get?id=', function () { describe('GET /api/transactions/queued', function () { it('should be ok', function (done) { node.get('/api/transactions/queued', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body).to.have.property('count').that.is.an('number'); done(); @@ -688,7 +688,7 @@ describe('GET /api/transactions/multisignatures/get?id=', function () { describe('GET /api/transactions/multisignatures', function () { it('should be ok', function (done) { node.get('/api/transactions/multisignatures', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body).to.have.property('count').that.is.an('number'); done(); @@ -716,7 +716,7 @@ describe('GET /api/transactions/unconfirmed/get?id=', function () { describe('GET /api/transactions/unconfirmed', function () { it('should be ok', function (done) { node.get('/api/transactions/unconfirmed', function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactions').that.is.an('array'); node.expect(res.body).to.have.property('count').that.is.an('number'); done(); @@ -734,7 +734,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; transactionList.push({ 'sender': account.address, @@ -757,7 +757,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -771,7 +771,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -788,7 +788,7 @@ describe('PUT /api/transactions', function () { amount: Math.floor(account.balance), recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error').to.match(/Account does not have enough ADM: U[0-9]+ balance: [0-9.]+/); done(); }); @@ -801,7 +801,7 @@ describe('PUT /api/transactions', function () { amount: 0, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -813,7 +813,7 @@ describe('PUT /api/transactions', function () { amount: 1298231812939123812939123912939123912931823912931823912903182309123912830123981283012931283910231203, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -825,7 +825,7 @@ describe('PUT /api/transactions', function () { amount: -1298231812939123812939123912939123912931823912931823912903182309123912830123981283012931283910231203, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -837,7 +837,7 @@ describe('PUT /api/transactions', function () { amount: 1, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); done(); }); @@ -850,7 +850,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -863,7 +863,7 @@ describe('PUT /api/transactions', function () { secret: account.password, amount: amountToSend }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.not.ok; + node.expect(res.body).to.have.property('success').to.be.false; node.expect(res.body).to.have.property('error'); done(); }); @@ -880,7 +880,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: recipientId }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -899,7 +899,7 @@ describe('PUT /api/transactions', function () { amount: amountToSend, recipientId: account2.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; done(); }); }); @@ -933,9 +933,9 @@ describe('POST /api/transactions', function () { amount: 500000000000, recipientId: account4.address }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); - node.expect(res.body.transactionId).to.be.not.empty; + node.expect(res.body.transactionId).not.to.be.empty; }); async.auto({ rounds: function (cb) { @@ -975,7 +975,7 @@ describe('POST /api/transactions', function () { recipientId: account2.address, type: node.txTypes.SEND }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId').that.is.not.empty; transactionList.push({ 'sender': account.address, @@ -996,7 +996,7 @@ describe('POST /api/transactions', function () { delegates: ['+' + node.eAccount.publicKey], type: node.txTypes.VOTE }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.type).to.equal(node.txTypes.VOTE); node.expect(res.body.transaction.amount).to.equal(0); @@ -1010,7 +1010,7 @@ describe('POST /api/transactions', function () { account4.username = node.randomDelegateName(); postTransaction({ username: account4.username, secret: account4.password, type: node.txTypes.DELEGATE }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transaction').that.is.an('object'); node.expect(res.body.transaction.fee).to.equal(node.fees.delegateRegistrationFee); node.expect(res.body.transaction).to.have.property('asset').that.is.an('object'); @@ -1042,7 +1042,7 @@ describe('POST /api/transactions', function () { trs.signature = transaction.sign(account4.keypair, trs); postTransaction({ transaction: trs }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); done(); }); @@ -1067,7 +1067,7 @@ describe('POST /api/transactions', function () { }; trs.signature = transaction.sign(account4.keypair, trs); postTransaction({ transaction: trs }, function (err, res) { - node.expect(res.body).to.have.property('success').to.be.ok; + node.expect(res.body).to.have.property('success').to.be.true; node.expect(res.body).to.have.property('transactionId'); done(); }); diff --git a/test/common/assert.js b/test/common/assert.js new file mode 100644 index 00000000..65311bfa --- /dev/null +++ b/test/common/assert.js @@ -0,0 +1 @@ +exports.isHex = (str) => Buffer.from(str, 'hex').length !== 0; diff --git a/test/common/globalAfter.js b/test/common/globalAfter.js new file mode 100644 index 00000000..e24dcab4 --- /dev/null +++ b/test/common/globalAfter.js @@ -0,0 +1,13 @@ +const jobsQueue = require('../../helpers/jobsQueue.js'); + +function removeQueuedJob(names) { + names.forEach((name) => { + const timeout = jobsQueue.jobs[name]; + clearTimeout(timeout); + delete jobsQueue.jobs[name]; + }); +} + +module.exports = { + removeQueuedJob, +}; diff --git a/test/common/initModule.js b/test/common/initModule.js index 9da51cd3..0cf5a42f 100644 --- a/test/common/initModule.js +++ b/test/common/initModule.js @@ -6,7 +6,7 @@ var randomString = require('randomstring'); var _ = require('lodash'); -var async = require('../node').async; +var async = require('async'); var dirname = path.join(__dirname, '..', '..'); var config = require(path.join(dirname, 'test/config.json')); // use Testnet config var packageJson = require(path.join(dirname, '/package.json')); @@ -20,6 +20,8 @@ var ed = require('../../helpers/ed'); var Transaction = require('../../logic/transaction.js'); var Account = require('../../logic/account.js'); var accounts = require('../../helpers/accounts'); +var Sequence = require('../../helpers/sequence.js'); +const { removeQueuedJob } = require('../common/globalAfter.js'); var modulesLoader = new function () { this.db = null; @@ -29,6 +31,7 @@ var modulesLoader = new function () { packageJson: packageJson, genesisblock: { block: genesisblock }, logger: this.logger, + balancesSequence: new Sequence(), network: { app: express() }, @@ -80,6 +83,15 @@ var modulesLoader = new function () { case 'Peers': new Logic(scope.logger, cb); break; + case 'State': + async.series({ + account: function (cb) { + new Account(scope.db, scope.schema, scope.logger, cb); + } + }, function (err, result) { + new Logic(scope.db, scope.ed, scope.schema, result.account, scope.logger, cb); + }); + break; default: console.log('no Logic case initLogic'); } @@ -120,7 +132,7 @@ var modulesLoader = new function () { }.bind(this), waterCb); }.bind(this), function (logic, waterCb) { - scope = _.merge(this.scope, { logic: logic }, scope); + scope = _.merge(this.scope, { logic: { ...logic, ...scope.logic } }, scope); async.reduce(modules, {}, function (memo, moduleObj, mapCb) { var name = _.keys(moduleObj)[0]; return this.initModule(moduleObj[name], scope, function (err, module) { @@ -165,7 +177,6 @@ var modulesLoader = new function () { { sql: require('../../modules/sql') }, { system: require('../../modules/system') }, { transactions: require('../../modules/transactions') }, - { transport: require('../../modules/transport') } ], [ { 'transaction': require('../../logic/transaction') }, { 'account': require('../../logic/account') }, @@ -250,6 +261,10 @@ var modulesLoader = new function () { }; }; +afterEach(() => { + removeQueuedJob(['transactionPoolNextBundle', 'transactionPoolNextExpiry', 'broadcasterNextRelease']) +}) + module.exports = { modulesLoader: modulesLoader }; diff --git a/test/common/objectStubs.js b/test/common/objectStubs.js index 419c8954..0da04b04 100644 --- a/test/common/objectStubs.js +++ b/test/common/objectStubs.js @@ -1,18 +1,6 @@ 'use strict'; -var sinon = require('sinon'); - -var randomPeer = { - 'broadhash': '198f2b61a8eb95fbeed58b8216780b68f697f26b849acf00c8c93bb9b24f783d', - 'dappid': null, - 'height': 1, - 'ip': '40.40.40.40', - 'os': 'unknown', - 'port': 4000, - 'state': 2, - 'version': '0.0.0' -}; - module.exports = { - randomPeer: randomPeer + dummyBlock, + randomPeer, }; diff --git a/test/common/stubs/account.js b/test/common/stubs/account.js new file mode 100644 index 00000000..9bfbf2f6 --- /dev/null +++ b/test/common/stubs/account.js @@ -0,0 +1,81 @@ +const accounts = require('../../../helpers/accounts.js') + +// Account, holding 19.6 mln ADM, received from Genesis +const iAccount = { + address: 'U5338684603617333081', + publicKey: '9184c87b846dec0dc4010def579fecf5dad592a59b37a013c7e6975597681f58', + password: 'floor myself rather hidden pepper make isolate vintage review flight century label', + balance: '1960000000000000' +}; + +const nonExistingAccount = { + address: 'U123456789012345678', + publicKey: 'a1234567bcde8f9abcd01e2345fa67bcd8e901f2345a6bc7d89e0123f45abc67' +} + +const validAccount = { + address: 'U777355171330060015', + unconfirmedBalance: '4509718944753', + balance: '4509718944753', + publicKey: 'a9407418dafb3c8aeee28f3263fd55bae0f528a5697a9df0e77e6568b19dfe34', + unconfirmedSignature: 0, + secondSignature: 0, + secondPublicKey: null, +}; + +const testAccount = { + username: 'market', + address: 'U810656636599221322', + publicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + secret: + 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon', +}; + +const testAccountHash = accounts.createPassPhraseHash(testAccount.secret); +const testAccountKeypair = accounts.makeKeypair(testAccountHash); + +const genesisAccount = { + secret: + 'neck want coast appear army smile palm major crumble upper void warm', + publicKey: 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + address: 'U15365455923155964650', +}; + +const genesisHash = accounts.createPassPhraseHash(genesisAccount.secret); +const genesisKeypair = accounts.makeKeypair(genesisHash); + +const delegateAccount = { + address: 'U12559234133690317086', + publicKey: 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', + secret: 'weather play vibrant large edge clean notable april fire smoke drift hidden', + u_balance: 10000000000000, + balance: 100000000000000 +} + +const delegateAccountHash = accounts.createPassPhraseHash(delegateAccount.secret); +const delegateAccountKeypair = accounts.makeKeypair(delegateAccountHash); + +const nonExistingAddress = 'U1234567890'; +const notAMnemonicPassphrase = 'not a mnemonic passphrase'; + +const invalidPublicKey = 'bd330166898377fb'; +const invalidAddress = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080'; + +module.exports = { + iAccount, + delegateAccount, + delegateAccountHash, + delegateAccountKeypair, + nonExistingAccount, + nonExistingAddress, + genesisAccount, + genesisHash, + genesisKeypair, + testAccount, + testAccountHash, + testAccountKeypair, + validAccount, + notAMnemonicPassphrase, + invalidPublicKey, + invalidAddress, +}; diff --git a/test/common/stubs/blocks.js b/test/common/stubs/blocks.js new file mode 100644 index 00000000..de592c5f --- /dev/null +++ b/test/common/stubs/blocks.js @@ -0,0 +1,173 @@ +const dummyBlock = { + id: '9314232245035524467', + height: 1, + timestamp: 0, +}; + +const validBlock = { + id: '2970021393187988089', + version: 0, + timestamp: 224138470, + height: 74916, + previousBlock: '1859555445278782254', + numberOfTransactions: 4, + totalAmount: 10000000000, + totalFee: 100200000, + reward: 0, + payloadLength: 569, + payloadHash: + '2fcb011cb7540594ada9bb88e40c602257c21477c701f1b729573f5171165a74', + generatorPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + generatorId: 'U7821895274052553465', + blockSignature: + '2efc3964ff1bfe5913ccdac97aefa88514091557011760d29de28abb36a8345533dfbe28f407fd8d2a5f75af87d2bd342f913ef527bacb9537c0a4714fe0b30b', + confirmations: 13, + totalForged: '100200000', +}; + +const firstTransfer = { + id: '11011291491598217343', + height: 74916, + blockId: '1343081691583438166', + type: 0, + block_timestamp: 224138470, + timestamp: 224138454, + senderPublicKey: + 'b0b4d346382aa07b23c0b733d040424532201b9eb22004b66a79d4b44e9d1449', + senderId: 'U9781760580710719871', + recipientId: 'U3189897341701072645', + recipientPublicKey: + '5da4a51dc0cdf2908b2bd63ef788604205f87531697cd978407fd15a6c358bff', + amount: 100000000, + fee: 50000000, + signature: + '1e21c8a786b802794e137fd964a72b17618a720e85e7df98244bfee854950ece5e3c9fe8bdf23b2ef27cbf1ed3ecaa7e7829a6cfd8b3a4d51e45ecdc5c716905', + signatures: [], + confirmations: 61, + asset: {}, +}; + +const secondTransfer = { + id: '6518067615780126', + height: 74916, + blockId: '1343081691583438166', + type: 0, + block_timestamp: 224138470, + timestamp: 224138455, + senderPublicKey: + 'b0b4d346382aa07b23c0b733d040424532201b9eb22004b66a79d4b44e9d1449', + senderId: 'U9781760580710719871', + recipientId: 'U3189897341701072645', + recipientPublicKey: + '5da4a51dc0cdf2908b2bd63ef788604205f87531697cd978407fd15a6c358bff', + amount: 9900000000, + fee: 50000000, + signature: + 'd4d9ae872ae30a35ef5f0c0fc5cb0b9098dcc71b15b287d7e890c9d9c9d5493348dfaf3ad14f7ccae25214dc987e5a0f5440ebdfb0e2e93b6798b2aedc0f8a04', + signatures: [], + confirmations: 61, + asset: {}, +}; + +const firstMessage = { + id: '449774133478944478', + height: 74916, + blockId: '1343081691583438166', + type: 8, + block_timestamp: 224138470, + timestamp: 224138456, + senderPublicKey: + 'b0b4d346382aa07b23c0b733d040424532201b9eb22004b66a79d4b44e9d1449', + senderId: 'U9781760580710719871', + recipientId: 'U3189897341701072645', + recipientPublicKey: + '5da4a51dc0cdf2908b2bd63ef788604205f87531697cd978407fd15a6c358bff', + amount: 0, + fee: 100000, + signature: + 'f9f17e8e8935464c50ffa2a619321c25f3a7913a01ff547c54d419ff45a11d2466ed0dc6109dcc482051e3be410cdb68a169d44c42dc16ed62a4ff81393fd30f', + signatures: [], + confirmations: 61, + asset: { + chat: { + message: 'fd38e525f10ff6980cab97d7edb8a78f6b12b445480f', + own_message: '44738b0599ff450d0d3d4ac86aa6c0f859fb033a8a74fb4a', + type: 1, + }, + }, +}; + +const secondMessage = { + id: '8266147080308035705', + height: 74916, + blockId: '1343081691583438166', + type: 8, + block_timestamp: 224138470, + timestamp: 224138458, + senderPublicKey: + 'b0b4d346382aa07b23c0b733d040424532201b9eb22004b66a79d4b44e9d1449', + senderId: 'U9781760580710719871', + recipientId: 'U3189897341701072645', + recipientPublicKey: + '5da4a51dc0cdf2908b2bd63ef788604205f87531697cd978407fd15a6c358bff', + amount: 0, + fee: 100000, + signature: + '13ab79bdc259f1fa2d1d0a73ccf7ca53abb603d2f56c96a1fe9dc46303acce10158ad88b79c5872a952d3bbf661e97393258356c1c0968427762203e27ac820e', + signatures: [], + confirmations: 61, + asset: { + chat: { + message: 'b5e490e0e284cd779e8e86e638a0d9497fcd396abe934a', + own_message: '2f58bb7bcbe7cc5f6c1e1d9a7c7b81fdc5513f96cc8c1a0f', + type: 1, + }, + }, +}; + +const validBlockTransactions = [ + firstTransfer, + secondTransfer, + firstMessage, + secondMessage, +]; + +const validPreviousBlock = { + id: '1859555445278782254', + version: 0, + timestamp: 224138465, + height: 74915, + previousBlock: '15739298621941223523', + numberOfTransactions: 0, + totalAmount: 0, + totalFee: 0, + reward: 0, + payloadLength: 0, + payloadHash: + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + generatorPublicKey: + '2e6331291833dee33649f2e0b1c864f9bd8d2618faa144d36e9b4bec65209f6a', + generatorId: 'U123464595396329758', + blockSignature: + 'f8c1e2b69c78fa3aa242879db25c40b19f70393f3a3408a78de4db986c157646df6ab5d9a4beeac8d184036254684b7cffbc22f470c3733324f9375b33787301', + confirmations: 169, + totalForged: '0', +}; + +const validPreviousBlockTransactions = []; + +const genesisBlockId = '6438017970172540087'; + +module.exports = { + dummyBlock, + validBlock, + validBlockTransactions, + validPreviousBlock, + validPreviousBlockTransactions, + firstTransfer, + secondTransfer, + firstMessage, + secondMessage, + genesisBlockId, +}; diff --git a/test/common/stubs/delegate.js b/test/common/stubs/delegate.js new file mode 100644 index 00000000..d6649454 --- /dev/null +++ b/test/common/stubs/delegate.js @@ -0,0 +1,12 @@ +const ed = require('../../../helpers/ed.js'); + +// 'market' delegate +const delegatePassphrase = 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon'; +const delegateHash = ed.createPassPhraseHash(delegatePassphrase); +const delegateKeyPair = ed.makeKeypair(delegateHash); + +module.exports = { + delegatePassphrase, + delegateHash, + delegateKeyPair +}; diff --git a/test/common/stubs/peers.js b/test/common/stubs/peers.js new file mode 100644 index 00000000..948d8b6d --- /dev/null +++ b/test/common/stubs/peers.js @@ -0,0 +1,14 @@ +const validPeer = { + broadhash: '198f2b61a8eb95fbeed58b8216780b68f697f26b849acf00c8c93bb9b24f783d', + dappid: null, + height: 1, + ip: '40.40.40.40', + os: 'unknown', + port: 4000, + state: 2, + version: '0.0.0', +}; + +module.exports = { + validPeer, +}; diff --git a/test/common/stubs/transactions.js b/test/common/stubs/transactions.js new file mode 100644 index 00000000..1da9c4db --- /dev/null +++ b/test/common/stubs/transactions.js @@ -0,0 +1,51 @@ +const existingTransaction = { + type: 2, + amount: 0, + fee: 0, + recipientId: null, + timestamp: 0, + senderId: 'U810656636599221322', + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + signature: + '1a4e3167185346f2cba0be57119670a0c737d63ca9e02ce3ff2a9a9e9dad0cccc53e4ced8c2b8a8fa32ce2e95c08c5e95f68a67b4040e75e339dfda6ed554b0a', + id: '8786873494391552220', +}; + +const existingTransactionWithAsset = { + ...existingTransaction, + asset: { + delegate: { + address: 'U810656636599221322', + publicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + username: 'market', + }, + }, +}; + +const unconfirmedTransaction = { + type: 0, + timestamp: 228144202, + amount: 50000000, + fee: 50000000, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + senderId: 'U810656636599221322', + asset: {}, + recipientId: 'U12559234133690317086', + signature: + 'd1f77e6d44b1b25138647aac3e1868b79df103d87ae272fa02f0e519dabf7714588ca9b4971da322cde4f0d717800b7a1a34bb42f2311c2977e22976c2c52808', +}; + +const unconfirmedTransactionId = '15096340494692671309'; + +const nonExistingTransactionId = '11111111111111111111'; + +module.exports = { + nonExistingTransactionId, + existingTransaction, + existingTransactionWithAsset, + unconfirmedTransaction, + unconfirmedTransactionId, +}; diff --git a/test/common/stubs/transactions/chat.js b/test/common/stubs/transactions/chat.js new file mode 100644 index 00000000..3f425ae1 --- /dev/null +++ b/test/common/stubs/transactions/chat.js @@ -0,0 +1,81 @@ +const rawValidTransaction = { + srt: 'U15365455923155964650U5338684603617333081', + t_id: '2459326385388619210', + t_senderPublicKey: + '9184c87b846dec0dc4010def579fecf5dad592a59b37a013c7e6975597681f58', + m_recipientPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + t_senderId: 'U5338684603617333081', + t_recipientId: 'U15365455923155964650', + t_timestamp: 226474809, + timestamp: 226474809, + block_timestamp: 226474815, + t_amount: '0', + t_fee: '100000', + c_message: '1451787721dd28b69ec768825b2f9e5473b580347f42', + c_own_message: '543ee6e48b4348439b2d839d5cab876938c7e 42b6f8d9587', + c_type: 1, + t_type: 8, + b_height: 541701, + confirmations: 18, + b_id: '17768103885289794518', +}; + +const validTransactionData = { + message_type: 1, + recipientId: 'U2707535059340134112', + message: + '9ae819297240f00bdc3627133c2e41efd27b022fcd0d011dfdda0941ba08399697f3e3bb5c46a43aff714ae1bac616b84617ce446d808523a14f278e5d88909837848e7aa69d9d4f9a95baae56df6ad4c274248d3d01a2cfccae51367dfab265a055d5ce991af654ee418839f94885876638863d172226b0369cd488c5727e6b1a42ba46fed014c1bf586dd2cab3afe7f10cb54864c099a680d5963778c9c4052df305497edc43082a7d60193650c331c6db9c9d9c0c8bbc004e53ac56586331453164b984c57a495810d709c9b984e4f367888d8a8ce1b26f528c1abdec08747e', + own_message: '6802a9e744aa3ba570d7e48fce5fe0f49184d0ce38ea40f7', +}; + +const validTransaction = { + id: '9175562912139726777', + height: 10288885, + blockId: '10475460465898092643', + type: 8, + block_timestamp: 58773245, + timestamp: 58773228, + senderPublicKey: + '2ac5eef60303003c90f662d89e60570d8661c8ba569e667296f5c7c97a0413ee', + senderId: 'U8916295525136600565', + recipientPublicKey: + '5a3c1da429ae925422892e69dc4f0ab6d7ac00cef229d2d992242dcfeca27b91', + recipientId: 'U2707535059340134112', + fee: 100000, + signature: + '287dc2554025d8074d674d50ec785d530588e2b828f2d3f29687a4f05c8afc623e185896abc739ea2af8db199ec6e31c57426937343ff5ec154341cee8f72f0a', + signatures: [], + confirmations: 32801518, + asset: {}, +}; + +const validUnconfirmedTransaction = { + type: 8, + amount: 0, + senderId: 'U7771441689362721578', + senderPublicKey: + 'e16e624fd0a5123294b448c21f30a07a0435533c693b146b14e66830e4e20404', + asset: { + chat: { + message: '75582d940f2c4093929c99a6c1911b4753', + own_message: '58dceaa227b3fb1dd1c7d3fbf3eb5db6aeb6a03cb7e2ec91', + type: 1, + }, + }, + recipientId: 'U810656636599221322', + timestamp: 63137661, + signature: + 'e25f1aba994c7f07c03099edcbe0ada19df371ddf1a829dae8dee36ab809ce8a438111bf65056c813e9dc832a890a081ba1cd295d37e509f62f042149e62e30d', + id: '8958126469643732641', + fee: 100000, + relays: 1, + receivedAt: '2019-09-03T11:14:22.638Z', +}; + +module.exports = { + rawValidTransaction, + validTransactionData, + validTransaction, + validUnconfirmedTransaction, +}; diff --git a/test/common/stubs/transactions/common.js b/test/common/stubs/transactions/common.js new file mode 100644 index 00000000..2df4b120 --- /dev/null +++ b/test/common/stubs/transactions/common.js @@ -0,0 +1,33 @@ +const validSender = { + balance: 8067474861277, + u_balance: 8067474861277, + password: + 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon', + username: 'market', + publicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + multimin: 0, + address: 'U810656636599221322', +}; + +const senderDefault = { + username: null, + isDelegate: 0, + secondSignature: 0, + secondPublicKey: null, + vote: 0, + multisignatures: null, + multimin: 0, + multilifetime: 0, + nameexist: 0, + producedblocks: 0, + missedblocks: 0, + fees: 0, + rewards: 0, + virgin: 0, + balance: 0 +}; + +module.exports = { + validSender, + senderDefault +}; diff --git a/test/common/stubs/transactions/delegate.js b/test/common/stubs/transactions/delegate.js new file mode 100644 index 00000000..747c26a9 --- /dev/null +++ b/test/common/stubs/transactions/delegate.js @@ -0,0 +1,57 @@ +const { validSender } = require('./common.js'); + +const validTransactionData = { + username: 'system', + sender: validSender, +}; + +const validTransaction = { + type: 2, + amount: 0, + fee: 0, + recipientId: null, + timestamp: 0, + asset: {}, + senderId: 'U14384059672307251353', + senderPublicKey: + 'cd67fb7bc27d727636b6fc725aa4a03a4dfcd68990f5aa10c98b8c97dd9ceeae', + signature: + 'b8961823346bb9049536fbb3a5ce36b3e937fdcb80e75b0ae82a26d941663f802139c1991c9c259ff88abe33779400f7580d3564c938684dc38d6d43cd375f0c', + id: '8869103705291559476', +}; + +const validUnconfirmedTransaction = { + type: 2, + timestamp: 0, + amount: 0, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + senderId: 'U810656636599221322', + asset: { + delegate: { + username: 'market', + publicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + }, + }, + signature: + '1a4e3167185346f2cba0be57119670a0c737d63ca9e02ce3ff2a9a9e9dad0cccc53e4ced8c2b8a8fa32ce2e95c08c5e95f68a67b4040e75e339dfda6ed554b0a', + id: '8786873494391552220', + fee: 300000000000, + relays: 1, + receivedAt: '2022-12-16T07:45:53.717Z', +}; + +const rawValidTransaction = { + d_username: 'market', + t_senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + t_senderId: 'U810656636599221322', +}; + +module.exports = { + validTransaction, + validTransactionData, + validUnconfirmedTransaction, + rawValidTransaction, +}; diff --git a/test/common/stubs/transactions/state.js b/test/common/stubs/transactions/state.js new file mode 100644 index 00000000..99fa035e --- /dev/null +++ b/test/common/stubs/transactions/state.js @@ -0,0 +1,42 @@ + +const validTransactionData = { + value: '0x84609a38fedbcd02b657233340e6a8cb09db61a8', + key: 'eth:address', + state_type: 0, +}; + +const validTransaction = { + type: 9, + timestamp: 226647468, + amount: 0, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + senderId: 'U810656636599221322', + asset: {}, + recipientId: null, + signature: + 'e3d569ec587dd0a47ff3c7fffa85506f98f5dd3ce56deb1e1108db3ac6c3c77c404f399cb8d1d712cbceb82e83fe8c9c818e76e3e2734d1f821b78496af91904', + height: 6361977, + blockId: '14557933175886918347', + block_timestamp: 39015790, + timestamp: 39015780, + requesterPublicKey: null, + recipientPublicKey: null, + fee: 100000, + signSignature: null, + signatures: [], + confirmations: null, + asset: {}, +}; + +const rawValidTransaction = { + st_stored_value: '0x84609a38fedbcd02b657233340e6a8cb09db61a8', + st_stored_key: 'eth:address', + st_type: 0, +}; + +module.exports = { + validTransactionData, + validTransaction, + rawValidTransaction +} diff --git a/test/common/stubs/transactions/transfer.js b/test/common/stubs/transactions/transfer.js new file mode 100644 index 00000000..9a034e1d --- /dev/null +++ b/test/common/stubs/transactions/transfer.js @@ -0,0 +1,67 @@ +const { delegateAccountKeypair, delegateAccount } = require('../account'); + +const validTransactionData = { + type: 0, + amount: 8067474861277, + keypair: delegateAccountKeypair, + sender: delegateAccount, + senderId: delegateAccount.address, + senderPublicKey: delegateAccount.publicKey, + recipientId: 'U7771441689362721578', + fee: 50000000, + timestamp: 1000, +}; + +const validTransaction = { + id: '17190511997607511181', + blockId: '6438017970172540087', + type: 0, + block_timestamp: null, + timestamp: 0, + senderPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + senderId: 'U15365455923155964650', + recipientId: 'U9781760580710719871', + amount: 490000000000000, + fee: 0, + signature: + '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', + signatures: [], + asset: {}, +}; + +const rawValidTransaction = { + t_id: '17190511997607511181', + b_height: 981, + t_blockId: '6438017970172540087', + t_type: 0, + t_timestamp: 33363661, + t_senderPublicKey: + 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', + m_recipientPublicKey: null, + t_senderId: 'U810656636599221322', + t_recipientId: 'U7771441689362721578', + t_amount: 490000000000000, + t_fee: 0, + t_signature: + '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', + confirmations: 8343, +}; + +const validUnconfirmedTransaction = { + type: 0, + amount: 100, + senderId: delegateAccount.address, + senderPublicKey: delegateAccount.publicKey, + recipientId: 'U7771441689362721578', + fee: 50000000, + timestamp: 1000, + asset: {} +}; + +module.exports = { + validUnconfirmedTransaction, + rawValidTransaction, + validTransaction, + validTransactionData, +}; diff --git a/test/common/stubs/transactions/vote.js b/test/common/stubs/transactions/vote.js new file mode 100644 index 00000000..c6ea7ba4 --- /dev/null +++ b/test/common/stubs/transactions/vote.js @@ -0,0 +1,50 @@ +const { testAccount, testAccountKeypair } = require('../account.js'); + +const transactionVotes = [ + '-9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f', +]; + +const validTransactionData = { + type: 3, + amount: 8067474861277, + sender: testAccount, + senderId: 'U810656636599221322', + fee: 10000000, + keypair: testAccountKeypair, + publicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + votes: transactionVotes, +}; + +const validTransaction = { + type: 3, + amount: 0, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + requesterPublicKey: null, + timestamp: 34253582, + asset: { + votes: [ + '-9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f', + ], + }, + data: undefined, + recipientId: 'U810656636599221322', + signature: + 'de668e2722fbc2fd02bac1bb66ff1238d75354f64ca0adc5b1967f5f4e67038336cee6a85af43ed9fa5f3a091890738de14c857bd7b1f9bade7ff1da1c395a0e', + id: '5962289265698105102', + fee: 100000000, + senderId: 'U810656636599221322', +}; + +const existedDelegateKey = + '81dd616f47bda681c929b9035aa1cbc9c41ba9d4af91f04744d1325e1b1af099'; +const invalidDelegateKey = + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30fg'; + +module.exports = { + transactionVotes, + validTransactionData, + validTransaction, + existedDelegateKey, + invalidDelegateKey, +}; diff --git a/test/common/utils.js b/test/common/utils.js new file mode 100644 index 00000000..7356b8db --- /dev/null +++ b/test/common/utils.js @@ -0,0 +1,19 @@ +const Mnemonic = require('bitcore-mnemonic'); +const accounts = require('../../helpers/accounts.js'); + +exports.randomAccount = function () { + const account = { + balance: '1000' + }; + + const passphrase = new Mnemonic(Mnemonic.Words.ENGLISH).toString() + const keypair = accounts.makeKeypair(accounts.createPassPhraseHash(account.password)); + + account.password = passphrase; + account.publicKey = keypair.publicKey; + account.publicKeyHex = keypair.publicKey.toString('hex'); + account.address = accounts.getAddressByPublicKey(account.publicKey); + account.keypair = keypair; + + return account; +}; diff --git a/test/node.js b/test/node.js index 477ba05b..a8be16be 100644 --- a/test/node.js +++ b/test/node.js @@ -553,7 +553,7 @@ node.waitForNewBlock = function (height, blocksToWait, cb) { }); }, function (testCb) { - return testCb(null, actualHeight === height); + return testCb(null, target > height); }, function (err) { if (err) { @@ -677,7 +677,7 @@ node.randomAccount = function () { const keypair = node.accounts.makeKeypair(node.accounts.createPassPhraseHash(account.password)); account.publicKey = keypair.publicKey; // node.lisk.crypto.getKeys(account.password).publicKey; account.publicKeyHex = keypair.publicKey.toString('hex'); - account.address = node.accounts.getAddressByPublicKey(account.publicKey); // node.lisk.crypto.getAddress(account.publicKey); + account.address = node.accounts.getAddressByPublicKey(account.publicKey.toString('hex')); // node.lisk.crypto.getAddress(account.publicKey); account.keypair = keypair; return account; }; @@ -738,6 +738,10 @@ function abstractRequest (options, done) { if (done) { request.end(function (err, res) { + if (!res) { + console.log(err, res) + } + node.debug('> Response:'.grey, JSON.stringify(res.body)); done(err, res); }); diff --git a/test/unit/helpers/RoundChanges.js b/test/unit/helpers/RoundChanges.js index 14cf5fd7..2fc19e52 100644 --- a/test/unit/helpers/RoundChanges.js +++ b/test/unit/helpers/RoundChanges.js @@ -1,97 +1,93 @@ 'use strict'; -var chai = require('chai'); -var express = require('express'); -var ip = require('neoip'); -var _ = require('lodash'); -var node = require('../../node.js'); -var RoundChanges = require('../../../helpers/RoundChanges.js'); +const { expect } = require('chai'); +const _ = require('lodash'); -describe('RoundChanges', function () { - var validScope; +const RoundChanges = require('../../../helpers/RoundChanges.js'); - beforeEach(function () { +describe('RoundChanges', () => { + let validScope; + + beforeEach(() => { validScope = { round: 1, roundFees: 500, - roundRewards: [0, 0, 100, 10] + roundRewards: [0, 0, 100, 10], }; }); - describe('constructor', function () { - it('should accept valid scope', function () { - var roundChanges = new RoundChanges(validScope); + describe('constructor()', () => { + it('should accept valid scope', () => { + const roundChanges = new RoundChanges(validScope); - node.expect(roundChanges.roundFees).equal(validScope.roundFees); - node.expect(_.isEqual(roundChanges.roundRewards, validScope.roundRewards)).to.be.ok; + expect(roundChanges.roundFees).to.equal(validScope.roundFees); + expect(_.isEqual(roundChanges.roundRewards, validScope.roundRewards)).to + .be.true; }); - it('should floor fees value', function () { + it('should floor fees value', () => { validScope.roundFees = 50.9999999999999; // Float - var roundChanges = new RoundChanges(validScope); - - node.expect(roundChanges.roundFees).equal(50); + const roundChanges = new RoundChanges(validScope); + expect(roundChanges.roundFees).to.equal(50); }); - it('should round up fees after exceeding precision', function () { + it('should round up fees after exceeding precision', () => { validScope.roundFees = 50.999999999999999; // Exceeded precision - var roundChanges = new RoundChanges(validScope); - - node.expect(roundChanges.roundFees).equal(51); + const roundChanges = new RoundChanges(validScope); + expect(roundChanges.roundFees).to.equal(51); }); - it('should accept Infinite fees as expected', function () { - validScope.roundFees = Number.MAX_VALUE * 2; // Infinity - - var roundChanges = new RoundChanges(validScope); + it('should accept `Infinity` fees as expected', () => { + validScope.roundFees = Infinity; - node.expect(roundChanges.roundFees).equal(Infinity); + const roundChanges = new RoundChanges(validScope); + expect(roundChanges.roundFees).to.equal(Infinity); }); }); - describe('at', function () { - it('should calculate round changes from valid scope', function () { - var roundChanges = new RoundChanges(validScope); - var rewardsAt = 2; - var res = roundChanges.at(rewardsAt); + describe('at()', () => { + it('should calculate round changes from valid scope', () => { + const roundChanges = new RoundChanges(validScope); + const rewardsAt = 2; + const response = roundChanges.at(rewardsAt); - node.expect(res.fees).equal(4); - node.expect(res.feesRemaining).equal(96); - node.expect(res.rewards).equal(validScope.roundRewards[rewardsAt]); // 100 - node.expect(res.balance).equal(104); + expect(response.fees).to.equal(4); + expect(response.feesRemaining).to.equal(96); + expect(response.rewards).to.equal(validScope.roundRewards[rewardsAt]); // 100 + expect(response.balance).to.equal(104); }); - it('should calculate round changes from Infinite fees', function () { + it('should calculate round changes from `Infinity` fees', () => { validScope.roundFees = Infinity; - var roundChanges = new RoundChanges(validScope); - var rewardsAt = 2; - var res = roundChanges.at(rewardsAt); + const roundChanges = new RoundChanges(validScope); + const rewardsAt = 2; + const response = roundChanges.at(rewardsAt); - node.expect(res.fees).equal(Infinity); - node.expect(res.feesRemaining).to.be.NaN; - node.expect(res.rewards).equal(validScope.roundRewards[rewardsAt]); // 100 - node.expect(res.balance).equal(Infinity); + expect(response.fees).to.equal(Infinity); + expect(response.feesRemaining).to.be.NaN; + expect(response.rewards).to.equal(validScope.roundRewards[rewardsAt]); // 100 + expect(response.balance).to.equal(Infinity); }); - it('should calculate round changes from Number.MAX_VALUE fees', function () { + it('should calculate round changes from `Number.MAX_VALUE` fees', () => { validScope.roundFees = Number.MAX_VALUE; // 1.7976931348623157e+308 - var roundChanges = new RoundChanges(validScope); - var rewardsAt = 2; - var res = roundChanges.at(rewardsAt); + const roundChanges = new RoundChanges(validScope); + const rewardsAt = 2; + const response = roundChanges.at(rewardsAt); /* eslint-disable max-len */ - var expectedFees = 1779894192932990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099; // 1.7976931348623157e+308 / 101 (delegates num) + const expectedFees = 1779894192932990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099; // 1.7976931348623157e+308 / 101 (delegates num) - node.expect(res.fees).equal(expectedFees); - node.expect(res.rewards).equal(validScope.roundRewards[rewardsAt]); // 100 - node.expect(res.feesRemaining).equal(1); + expect(response.fees).to.equal(expectedFees); + expect(response.rewards).to.equal(validScope.roundRewards[rewardsAt]); // 100 + expect(response.feesRemaining).to.equal(1); - var expectedBalance = 1779894192932990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990199; // 1.7976931348623157e+308 / 101 (delegates num) + 100 - node.expect(res.balance).equal(expectedBalance); + const expectedBalance = 1779894192932990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990099009900990199; // 1.7976931348623157e+308 / 101 (delegates num) + 100 + expect(response.balance).to.equal(expectedBalance); }); }); }); diff --git a/test/unit/helpers/request-limiter.js b/test/unit/helpers/request-limiter.js index 8d4a53ce..53d5dab5 100644 --- a/test/unit/helpers/request-limiter.js +++ b/test/unit/helpers/request-limiter.js @@ -1,112 +1,143 @@ 'use strict'; -var chai = require('chai'); -var expect = require('chai').expect; -var express = require('express'); +const { expect } = require('chai'); +const express = require('express'); -var RequestLimiter = require('../../../helpers/request-limiter.js'); +const RequestLimiter = require('../../../helpers/request-limiter.js'); -describe('RequestLimiter', function () { - var app; +describe('RequestLimiter', () => { + /** + * @type {express.Express} + */ + let app; - beforeEach(function () { + beforeEach(() => { app = express(); }); - describe('when config.trustProxy is undefined', function () { - it('should not enable trust proxy', function () { + describe('when config.trustProxy is `undefined`', () => { + it('should not enable trust proxy', () => { RequestLimiter(app, {}); expect(app.enabled('trust proxy')).to.be.false; }); }); - describe('when config.trustProxy is == false', function () { - it('should not enable trust proxy', function () { + describe('when config.trustProxy set to `false`', () => { + it('should not enable trust proxy', () => { RequestLimiter(app, { trustProxy: false }); expect(app.enabled('trust proxy')).to.be.false; }); }); - describe('when config.trustProxy is == true', function () { - it('should enable trust proxy', function () { + describe('when config.trustProxy set to `true`', () => { + it('should enable trust proxy', () => { RequestLimiter(app, { trustProxy: true }); expect(app.enabled('trust proxy')).to.be.true; }); }); - describe('when limits are undefined', function () { - var limiter; + describe('when limits are `undefined`', () => { + let limiter; - beforeEach(function () { + beforeEach(() => { limiter = RequestLimiter(app, {}); }); - it('should return the default client limits', function () { - expect(limiter).to.be.a('object').that.has.property('client').that.is.a('object'); - expect(limiter.client).to.have.property('delayAfter').to.eql(0); - expect(limiter.client).to.have.property('delayAfter').to.eql(0); - expect(limiter.client).to.have.property('delayMs').to.eql(0); - expect(limiter.client).to.have.property('max').to.eql(0); - expect(limiter.client).to.have.property('windowMs').to.eql(60000); + it('should return the default client limits', () => { + expect(limiter) + .to.be.an('object') + .that.has.property('client') + .that.is.an('object'); + expect(limiter.client).to.have.property('delayAfter').to.equal(0); + expect(limiter.client).to.have.property('delayMs').that.is.a('function'); + expect(limiter.client).to.have.property('skip').that.is.a('function'); + expect(limiter.client).to.have.property('windowMs').to.equal(60000); + expect(limiter.client.delayMs(100)).to.equal(0); }); - it('should return the default peer limits', function () { - expect(limiter).to.be.a('object').that.has.property('peer').that.is.a('object'); - expect(limiter.peer).to.have.property('delayAfter').to.eql(0); - expect(limiter.peer).to.have.property('delayAfter').to.eql(0); - expect(limiter.peer).to.have.property('delayMs').to.eql(0); - expect(limiter.peer).to.have.property('max').to.eql(0); - expect(limiter.peer).to.have.property('windowMs').to.eql(60000); + it('should return the default peer limits', () => { + expect(limiter) + .to.be.an('object') + .that.has.property('peer') + .that.is.an('object'); + expect(limiter.peer).to.have.property('delayAfter').to.equal(0); + expect(limiter.peer).to.have.property('delayMs').that.is.a('function'); + expect(limiter.peer).to.have.property('skip').that.is.a('function'); + expect(limiter.peer).to.have.property('windowMs').to.equal(60000); + expect(limiter.peer.delayMs(100)).to.equal(0); }); - it('should enable the client middleware', function () { - expect(limiter).to.be.a('object').that.has.property('middleware').that.is.a('object'); - expect(limiter.middleware).to.have.property('client').that.is.a('function'); + it('should enable the client middleware', () => { + expect(limiter) + .to.be.an('object') + .that.has.property('middleware') + .that.is.an('object'); + expect(limiter.middleware) + .to.have.property('client') + .that.is.a('function'); }); - it('should enable the peer middleware', function () { - expect(limiter).to.be.a('object').that.has.property('middleware').that.is.a('object'); + it('should enable the peer middleware', () => { + expect(limiter) + .to.be.an('object') + .that.has.property('middleware') + .that.is.an('object'); expect(limiter.middleware).to.have.property('peer').that.is.a('function'); }); }); - describe('when limits are defined', function () { - var limits, options, limiter; + describe('when limits are defined', () => { + let limits; + let options; + let limiter; - beforeEach(function () { + beforeEach(() => { limits = { - max: 1, delayMs: 2, delayAfter: 3, - windowMs: 4 + windowMs: 4, }; options = { options: { limits: limits } }; limiter = RequestLimiter(app, { api: options, peers: options }); }); - it('should return the defined client limits', function () { - expect(limiter).to.be.a('object').that.has.property('client').that.is.a('object'); - expect(limiter.client).to.have.property('max').to.eql(1); - expect(limiter.client).to.have.property('delayMs').to.eql(2); - expect(limiter.client).to.have.property('delayAfter').to.eql(3); - expect(limiter.client).to.have.property('windowMs').to.eql(4); + it('should return the defined client limits', () => { + expect(limiter) + .to.be.an('object') + .that.has.property('client') + .that.is.an('object'); + expect(limiter.client).to.have.property('delayMs').that.is.a('function'); + expect(limiter.client).to.have.property('delayAfter').to.equal(3); + expect(limiter.client).to.have.property('windowMs').to.equal(4); + expect(limiter.client.delayMs(4)).to.equal(2); }); it('should return the defined peer limits', function () { - expect(limiter).to.be.a('object').that.has.property('peer').that.is.a('object'); - expect(limiter.peer).to.have.property('max').to.eql(1); - expect(limiter.peer).to.have.property('delayMs').to.eql(2); - expect(limiter.peer).to.have.property('delayAfter').to.eql(3); - expect(limiter.peer).to.have.property('windowMs').to.eql(4); + expect(limiter) + .to.be.an('object') + .that.has.property('peer') + .that.is.an('object'); + expect(limiter.peer).to.have.property('delayMs').that.is.a('function'); + expect(limiter.peer).to.have.property('delayAfter').to.equal(3); + expect(limiter.peer).to.have.property('windowMs').to.equal(4); + expect(limiter.peer.delayMs(4)).to.equal(2); }); it('should enable the client middleware', function () { - expect(limiter).to.be.a('object').that.has.property('middleware').that.is.a('object'); - expect(limiter.middleware).to.have.property('client').that.is.a('function'); + expect(limiter) + .to.be.an('object') + .that.has.property('middleware') + .that.is.an('object'); + expect(limiter.middleware) + .to.have.property('client') + .that.is.a('function'); }); it('should enable the peer middleware', function () { - expect(limiter).to.be.a('object').that.has.property('middleware').that.is.a('object'); + expect(limiter) + .to.be.an('object') + .that.has.property('middleware') + .that.is.an('object'); expect(limiter.middleware).to.have.property('peer').that.is.a('function'); }); }); diff --git a/test/unit/helpers/sequence.js b/test/unit/helpers/sequence.js new file mode 100644 index 00000000..c07de53d --- /dev/null +++ b/test/unit/helpers/sequence.js @@ -0,0 +1,157 @@ +const { expect } = require('chai'); +const sinon = require('sinon'); + +const Sequence = require('../../../helpers/sequence'); + +describe('Sequence', () => { + /** + * @type {Sequence} + */ + let sequence; + + beforeEach(() => { + sequence = new Sequence({ + warningLimit: 3, + onWarning: sinon.spy() + }); + }); + + describe('add()', () => { + it('should add a task to the sequence', () => { + const worker = () => {}; + sequence.add(worker); + expect(sequence.count()).to.equal(1); + }); + + it('should add a task with arguments', () => { + const worker = () => {}; + const args = [1, 2, 3]; + sequence.add(worker, args); + expect(sequence.sequence[0].args).to.deep.equal(args); + }); + + it('should add a task with a done callback', () => { + const worker = () => {}; + const done = () => {}; + sequence.add(worker, [], done); + expect(sequence.sequence[0].done).to.equal(done); + }); + + it('should start ticking if not already ticking', (done) => { + expect(sequence.isTicking).to.be.false; + + const worker = (callback) => callback(); + sequence.add(worker, [], () => { + expect(sequence.isTicking).to.be.true; + done(); + }); + }); + }); + + describe('__tick()', () => { + it('should process the next task in the sequence without blocking event loop', (done) => { + const spy = sinon.spy(); + const worker = (callback) => { + spy(); + callback(); + }; + + sequence.add(worker, [], () => { + expect(spy.calledOnce).to.be.true; + done(); + }); + expect(sequence.isTicking).to.be.true; + }); + + it('should start ticking on the next tick after last task callback', (done) => { + const worker = (callback) => callback(); + + sequence.add(worker, [], () => { + expect(sequence.isTicking).to.be.true; + sequence.nextSequenceTick(); + expect(sequence.isTicking).to.be.false; + done(); + }); + }); + + it('should start the sequence again on a new task after stopping', (done) => { + const worker = (callback) => callback(); + + sequence.add(worker, [], () => { + expect(sequence.isTicking).to.be.true; + sequence.nextSequenceTick(); + expect(sequence.isTicking).to.be.false; + + sequence.add(worker, [], () => { + done(); + }) + expect(sequence.isTicking).to.be.true; + }); + }); + + it('should process the task added while running the sequence', (done) => { + const spy = sinon.spy(); + const worker = (callback) => { + spy(); + callback(); + }; + + expect(sequence.isTicking).to.be.false; + + sequence.add(worker, [], () => { + expect(spy.calledOnce).to.be.true; + expect(sequence.isTicking).to.be.true; + + const secondSpy = sinon.spy(); + const anotherWorker = (callback) => { + secondSpy(); + callback(); + }; + sequence.add(anotherWorker, [], () => { + expect(sequence.isTicking).to.be.true; + expect(secondSpy.calledOnce).to.be.true + }) + + done(); + }); + }); + + it('should call task.done with results', (done) => { + const worker = (callback) => callback(null, 'result'); + const doneCallback = (err, res) => { + expect(err).to.be.null; + expect(res).to.equal('result'); + done(); + }; + + sequence.add(worker, [], doneCallback); + }); + }); + + describe('count()', () => { + it('should return the number of pending tasks in the sequence', () => { + expect(sequence.count()).to.equal(0); + sequence.add(() => {}); + expect(sequence.count()).to.equal(1); + }); + }); + + describe('config.warningLimit', () => { + it('should call onWarning when sequence length equals warningLimit', (done) => { + const onWarningSpy = sinon.spy(); + sequence = new Sequence({ + warningLimit: 2, + onWarning: onWarningSpy + }); + + const worker = (callback) => callback(); + + sequence.add(worker); + sequence.add(worker, [], () => { + expect(onWarningSpy.calledOnce).to.be.true; + expect(onWarningSpy.firstCall.args).to.deep.equal([2, 2]); + done(); + }); + }); + }); +}); diff --git a/test/unit/logic/account.js b/test/unit/logic/account.js new file mode 100644 index 00000000..8fd2dab8 --- /dev/null +++ b/test/unit/logic/account.js @@ -0,0 +1,389 @@ +'use strict'; + +const { expect } = require('chai'); +const sinon = require('sinon'); + +const Account = require('../../../logic/account.js'); + +const { modulesLoader } = require('../../common/initModule.js'); +const { validAccount, nonExistingAccount } = require('../../common/stubs/account.js'); +const { validBlock } = require('../../common/stubs/blocks.js'); + +describe('account', () => { + /** + * @type {Account} + */ + let account; + let db; + + beforeEach((done) => { + db = { + none: sinon.fake.returns(Promise.resolve()), + query: sinon.fake.returns(Promise.resolve()), + }; + + modulesLoader.initLogic( + Account, + { + db, + schema: modulesLoader.scope.schema, + logger: modulesLoader.scope.logger, + }, + (error, instance) => { + if (error) { + return done(error); + } + + account = instance; + done(); + } + ); + }); + + describe('merge()', () => { + const { address } = nonExistingAccount; + + const delegate1 = 'system'; + const delegate2 = 'minecraft'; + + let diff; + let round = 1; + + beforeEach(() => { + diff = { + round, + }; + diff.publicKey = nonExistingAccount.publicKey; + diff.blockId = validBlock.id + + round += 1; + }) + + it('should update the account with a positive balance', () => { + diff.balance = 150; + + const { address } = nonExistingAccount; + const result = account.merge(address, diff); + + expect(result).to.equal( + `update "mem_accounts" set "balance" = "balance" + ${diff.balance}, "blockId" = '${diff.blockId}' where "address" = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (${diff.balance})::bigint, "dependentId", '${diff.blockId}', 1 FROM mem_accounts2delegates WHERE "accountId" = '${address}';` + ); + }); + + it('should update the account with a negative balance', () => { + diff.balance = -50; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `update "mem_accounts" set "balance" = "balance" - ${Math.abs(diff.balance)}, "blockId" = '${diff.blockId}' where "address" = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (${diff.balance})::bigint, "dependentId", '${diff.blockId}', 2 FROM mem_accounts2delegates WHERE "accountId" = '${address}';` + ); + }); + + it('should insert new delegates to the account', () => { + diff.delegates = [`+${delegate1}`, `+${delegate2}`]; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `insert into "mem_accounts2delegates" ("accountId", "dependentId") values ('${address}', '${delegate1}');insert into "mem_accounts2delegates" ("accountId", "dependentId") values ('${address}', '${delegate2}');update "mem_accounts" set "blockId" = '${diff.blockId}' where "address" = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (balance)::bigint, '${delegate1}', '${diff.blockId}', 3 FROM mem_accounts WHERE address = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (balance)::bigint, '${delegate2}', '${diff.blockId}', 3 FROM mem_accounts WHERE address = '${address}';` + ); + }); + + it('should remove delegates from the account', () => { + diff.delegates = [`-${delegate1}`, `-${delegate2}`]; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `delete from "mem_accounts2delegates" where "dependentId" in ('${delegate1}', '${delegate2}') and "accountId" = '${address}';update "mem_accounts" set "blockId" = '${diff.blockId}' where "address" = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (-balance)::bigint, '${delegate1}', '${diff.blockId}', 4 FROM mem_accounts WHERE address = '${address}';INSERT INTO mem_round ("address", "amount", "delegate", "blockId", "round") SELECT '${address}', (-balance)::bigint, '${delegate2}', '${diff.blockId}', 4 FROM mem_accounts WHERE address = '${address}';` + ); + }); + + it('should handle an unsafe number for balance', (done) => { + diff.balance = NaN; + + account.merge(address, diff, (error) => { + expect(error).to.equal('Encountered unsafe number: NaN'); + done(); + }); + }); + + it('should insert multiple complex objects', () => { + diff.delegates = [ + { action: '+', value: delegate1 }, + { action: '+', value: delegate2 }, + ]; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `insert into "mem_accounts2delegates" ("value") values ('${delegate1}'), ('${delegate2}');insert into "mem_accounts2delegates" ("value") values ('${delegate1}'), ('${delegate2}');update "mem_accounts" set "blockId" = '${diff.blockId}' where "address" = '${address}';` + ); + }); + + it('should remove multiple complex objects', () => { + diff.delegates = [ + { action: '-', value: delegate1 }, + { action: '-', value: delegate2 }, + ]; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `delete from "mem_accounts2delegates" where "value" = '${delegate1}' and "value" = '${delegate2}';update "mem_accounts" set "blockId" = '${diff.blockId}' where "address" = '${address}';` + ); + }); + + it('should remove and insert complex objects', () => { + diff.delegates = [ + { action: '-', value: delegate1 }, + { action: '+', value: delegate2 }, + ]; + delete diff.blockId; + + const result = account.merge(address, diff); + + expect(result).to.equal( + `delete from "mem_accounts2delegates" where "value" = '${delegate1}';insert into "mem_accounts2delegates" ("value") values ('${delegate2}');` + ); + }); + }); + + describe('createTables()', () => { + it('should read sql/memoryTables.sql file and execute the queries without errors', () => { + account.createTables(() => { + const called = db.query.calledWithMatch( + sinon.match({ error: sinon.match.typeOf('undefined') }) + ); + + expect(called).to.be.true; + }); + }); + }); + + describe('removeTables()', () => { + it('should execute the sql query to remove the tables', () => { + account.removeTables(() => { + const called = db.query.calledWithMatch( + 'delete from "mem_accounts";delete from "mem_round";delete from "mem_accounts2delegates";delete from "mem_accounts2u_delegates";delete from "mem_accounts2multisignatures";delete from "mem_accounts2u_multisignatures";' + ); + + expect(called).to.be.true; + }); + }); + }); + + describe('verifyPublicKey()', () => { + it('should ignore if `publicKey` was not provided', () => { + expect(account.verifyPublicKey).to.not.throw(); + }); + + it('should not throw an error for a valid public key', () => { + expect(() => + account.verifyPublicKey(validAccount.publicKey) + ).to.not.throw(); + }); + + it('should throw an error for buffer public key', () => { + expect(() => + account.verifyPublicKey(Buffer.from(validAccount.publicKey, 'hex')) + ).to.throw('must be a string'); + }); + + it('should throw an error for number instead of string', () => { + expect(() => account.verifyPublicKey(0)).to.throw('must be a string'); + }); + + it('should throw an error for null', () => { + expect(() => account.verifyPublicKey(null)).to.throw('must be a string'); + }); + + it('should throw an error for object', () => { + expect(() => account.verifyPublicKey({})).to.throw('must be a string'); + }); + + it('should throw an error for NaN', () => { + expect(() => account.verifyPublicKey(NaN)).to.throw('must be a string'); + }); + + it('should throw an error when a too short string has been passed', () => { + expect(() => account.verifyPublicKey('a9407418dafb3c8ae')).to.throw( + 'must be 64 characters long' + ); + }); + + it('should throw an error when the provided public key is not a hex string', () => { + expect(() => + account.verifyPublicKey( + 'g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2u2g3h4i5j6k7' + ) + ).to.throw('must be a hex string'); + }); + + it('should throw an error when the provided public key can be trimmed to a zero length string', () => { + expect(() => account.verifyPublicKey(' '.repeat(64))).to.throw( + 'must be a hex string' + ); + }); + }); + + describe('toDB()', () => { + const keys = [ + 'raw', + 'values' + ]; + + it('should convert public key to buffer', () => { + const normalizedAccount = account.toDB({ + publicKey: validAccount.publicKey, + secondPublicKey: null, + address: validAccount.address, + }); + + expect(normalizedAccount).to.have.all.keys(keys); + + const { raw, values } = normalizedAccount; + + expect(raw.publicKey).to.have.property('sql').that.equals('$(publicKey)'); + expect(values.publicKey).to.be.an.instanceof(Buffer) + expect(raw.secondPublicKey).to.equal(null); + expect(raw.address).to.equal(validAccount.address); + }); + + it('should convert address to upper case', () => { + const normalizedAccount = account.toDB({ + address: nonExistingAccount.address.toLowerCase(), + }); + + expect(normalizedAccount).to.have.all.keys(keys); + + const { raw } = normalizedAccount; + expect(raw).to.have.property('address').that.equals(nonExistingAccount.address); + }); + }); + + describe('getAll()', () => { + it('should apply limit filter', (done) => { + account.getAll({ limit: 1 }, ['username'], () => { + const matched = db.query.calledWithMatch(sinon.match(/limit 1/)); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should apply offset', (done) => { + account.getAll({ offset: 100 }, ['username'], () => { + const matched = db.query.calledWithMatch(sinon.match(/offset 100/)); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should apply desc sorting by balance', (done) => { + account.getAll({ sort: { balance: -1 } }, ['username'], () => { + const matched = db.query.calledWithMatch( + sinon.match(/order by "balance" desc/) + ); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should apply asc sorting by balance', (done) => { + account.getAll({ sort: { balance: 1 } }, ['username'], () => { + const matched = db.query.calledWithMatch( + sinon.match(/order by "balance" asc/) + ); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should search by address in uppercase', (done) => { + account.getAll({ address: validAccount.address }, ['username'], () => { + const matched = db.query.calledWithMatch( + sinon.match(/upper\("address"\) = '/) + ); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should filter out non existing fields', (done) => { + const nonExistingFields = [ + 'reward', + 'totalFee', + 'confirmations', + 'blockSignature', + ]; + const actualFields = [ + 'username', + 'isDelegate', + 'address', + 'publicKey', + 'balance', + 'virgin', + ]; + const fields = [...nonExistingFields, ...actualFields]; + + account.getAll({ address: validAccount.address }, fields, () => { + const matched = db.query.calledWithMatch( + `select "username", "isDelegate", UPPER("address") as "address", ENCODE("publicKey", \'hex\') as "publicKey", ("balance")::bigint as "balance", "virgin" from "mem_accounts" as "a" where upper("address") = '${validAccount.address}';` + ); + + expect(matched).to.be.true; + done(); + }); + }); + + it('should make query with both filters and fields', (done) => { + account.getAll( + { + limit: 1, + offset: -23, + sort: { virgin: 1 }, + address: validAccount.address, + }, + ['username', 'nonexistingfield'], + () => { + const matched = db.query.calledWithMatch( + `select "username" from "mem_accounts" as "a" where upper("address") = '${validAccount.address}' order by "virgin" asc limit 1;` + ); + + expect(matched).to.be.true; + done(); + } + ); + }); + }); + + describe('set()', () => { + it('should set balance to 100000', (done) => { + account.set(validAccount.address, { balance: 100000 }, () => { + const matched = db.none.calledWithMatch(/"balance" = 100000/); + + expect(matched).to.be.true; + done(); + }); + }); + }); + + describe('remove()', () => { + it('should remove the account based on address', (done) => { + account.remove(validAccount.address, () => { + const matched = db.none.calledWithMatch( + /^delete from "mem_accounts" where "address" = / + ); + + expect(matched).to.be.true; + done(); + }); + }); + }); +}); diff --git a/test/unit/logic/block.js b/test/unit/logic/block.js new file mode 100644 index 00000000..e559624f --- /dev/null +++ b/test/unit/logic/block.js @@ -0,0 +1,457 @@ +'use strict'; + +const { expect } = require('chai'); + +const Block = require('../../../logic/block.js'); +const Transfer = require('../../../logic/transfer.js'); +const Chat = require('../../../logic/chat.js'); + +const { modulesLoader } = require('../../common/initModule.js'); + +const ed = require('../../../helpers/ed.js'); +const transactionTypes = require('../../../helpers/transactionTypes.js'); + +const { + validBlock, + validPreviousBlock, + firstTransfer, + secondTransfer, + firstMessage, + secondMessage, +} = require('../../common/stubs/blocks.js'); +const { delegateKeyPair } = require('../../common/stubs/delegate.js'); + +describe('Block', () => { + let block; + + beforeEach((done) => { + modulesLoader.initLogic( + Block, + { + db: {}, + ed: ed, + logger: modulesLoader.scope.logger, + schema: modulesLoader.scope.schema, + genesisBlock: {}, + }, + (error, result) => { + if (error) { + return done(error); + } + + block = result; + + const { transaction } = block.scope; + const transfer = new Transfer(); + const chat = new Chat(); + transaction.attachAssetType(transactionTypes.SEND, transfer); + transaction.attachAssetType(transactionTypes.CHAT_MESSAGE, chat); + + done(); + } + ); + }); + + describe('create()', () => { + it('should create a new block with sorted transactions', () => { + const newBlock = block.create({ + transactions: [ + firstMessage, + secondTransfer, + firstTransfer, + secondMessage, + ], + previousBlock: validPreviousBlock, + timestamp: validBlock.timestamp, + keypair: delegateKeyPair, + }); + + const propertiesToCheck = [ + 'numberOfTransactions', + 'totalAmount', + 'totalFee', + 'payloadLength', + 'previousBlock', + 'generatorPublicKey', + 'blockSignature', + ]; + + propertiesToCheck.forEach((property) => { + expect(newBlock).to.have.property(property, validBlock[property]); + }); + + expect(newBlock.transactions).to.deep.equal([ + firstTransfer, + secondTransfer, + firstMessage, + secondMessage, + ]); + }); + + it('should create a new block with no transactions', () => { + const newBlock = block.create({ + transactions: [], + previousBlock: validPreviousBlock, + timestamp: validBlock.timestamp, + keypair: delegateKeyPair, + }); + + expect(newBlock.numberOfTransactions).to.equal(0); + expect(newBlock.totalAmount).to.equal(0); + expect(newBlock.totalFee).to.equal(0); + expect(newBlock.previousBlock).to.equal(validPreviousBlock.id); + expect(newBlock.payloadLength).to.equal(0); + expect(newBlock.generatorPublicKey).to.equal( + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0' + ); + expect(newBlock.blockSignature).to.equal( + 'd4ba6d52a3ff583eae43fdff1e1e8f34603f84a1385fe765c1ebd89158560a4df1bd82f3de17ff09841c16651b8afafb1c8fa99b7c1f9e4bd2a61b6780ea6200' + ); + expect(newBlock.transactions).to.deep.equal([]); + }); + }); + + describe('verifySignature()', () => { + it('should return true for a valid block with reward and total fee', () => { + const validBlock = { + id: '11114690216332606721', + version: 0, + timestamp: 61741820, + height: 10873829, + previousBlock: '11483763337863654141', + numberOfTransactions: 1, + totalAmount: 10000000, + totalFee: 50000000, + reward: 45000000, + payloadLength: 117, + payloadHash: + 'f7c0fa338a3a848119cad999d8035ab3fcb3d274a4555e141ebeb86205e41345', + generatorPublicKey: + '134a5de88c7da1ec71e75b5250d24168c6c6e3965ff16bd71497bd015d40ea6a', + generatorId: 'U3238410389688281135', + blockSignature: + '18607b15417a6b0a56b4c74cacd713ad7a10df16ec3ab45a697fa72b6f811f9213d895b7e0fbca71cf74323d60148d0991668e5368386408f4d841496ed2280d', + confirmations: 1093, + totalForged: '95000000', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.true; + }); + + it('should return true for a valid block with many transactions', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 9800000000000000, + totalFee: 0, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.true; + }); + + it('should return true for a valid block with 0 transactions', () => { + const validBlock = { + id: '12886437182438275909', + version: 0, + timestamp: 223763900, + height: 2, + previousBlock: '6438017970172540087', + numberOfTransactions: 0, + totalAmount: 0, + totalFee: 0, + reward: 0, + payloadLength: 0, + payloadHash: + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + generatorPublicKey: + '1936631c26631ccc22b93238c387058fc2be6b915234aa4a035c069803e9a15a', + generatorId: 'U5090748236497587482', + blockSignature: + '3f4feaf57fb297d97ebf2ba0dcf3c91b1ebd42e2d8b370c5b11a7b6cb5b798f930e8445056e2b67f173340a55db65b97a6cd953e11ffda93c7009fdd0f076902', + confirmations: 75212, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.true; + }); + + it('should return false for a block with false amount of transactions', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 5, + totalAmount: 9800000000000000, + totalFee: 0, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong signature', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 9800000000000000, + totalFee: 0, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '3f4feaf57fb297d97ebf2ba0dcf3c91b1ebd42e2d8b370c5b11a7b6cb5b798f930e8445056e2b67f173340a55db65b97a6cd953e11ffda93c7009fdd0f076902', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong generatorPublicKey', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 9800000000000000, + totalFee: 0, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + '1936631c26631ccc22b93238c387058fc2be6b915234aa4a035c069803e9a15a', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong timestamp', () => { + const validBlock = { + id: '12886437182438275909', + version: 0, + timestamp: 23000000, + height: 2, + previousBlock: '6438017970172540087', + numberOfTransactions: 0, + totalAmount: 0, + totalFee: 0, + reward: 0, + payloadLength: 0, + payloadHash: + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + generatorPublicKey: + '1936631c26631ccc22b93238c387058fc2be6b915234aa4a035c069803e9a15a', + generatorId: 'U5090748236497587482', + blockSignature: + '3f4feaf57fb297d97ebf2ba0dcf3c91b1ebd42e2d8b370c5b11a7b6cb5b798f930e8445056e2b67f173340a55db65b97a6cd953e11ffda93c7009fdd0f076902', + confirmations: 75212, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong total amount', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 0, + totalFee: 0, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong total fee', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 9800000000000000, + totalFee: 10, + reward: 0, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + + it('should return false for a block with wrong reward amount', () => { + const validBlock = { + id: '6438017970172540087', + version: 0, + timestamp: 0, + height: 1, + previousBlock: null, + numberOfTransactions: 205, + totalAmount: 9800000000000000, + totalFee: 0, + reward: 100, + payloadLength: 687606, + payloadHash: + '38f153a81332dea86751451fd992df26a9249f0834f72f58f84ac31cceb70f43', + generatorPublicKey: + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', + generatorId: 'U15365455923155964650', + blockSignature: + '108db6fed83519acf9f8ea3521d73b0b1496317bd9e9f00bc21ddf3a7338f1941bd20a60118e90f407a1b955d5ff36a81252645cd76d77466f52bd0d1434fe0a', + confirmations: 75213, + totalForged: '0', + }; + const hasValidSignature = block.verifySignature(validBlock); + expect(hasValidSignature).to.be.false; + }); + }); + + describe('objectNormalize()', () => { + it('should remove values with null and undefined properties', () => { + const normalizedBlock = block.objectNormalize({ + ...validBlock, + transactions: [], + amount: null, + confirmations: undefined, + }); + expect(Object.keys(normalizedBlock)).to.not.include([ + 'amount', + 'confirmations', + ]); + }); + + it('should throw error on invalid block', () => { + const transaction = firstTransfer; + expect(() => block.objectNormalize(transaction)).to.throw( + 'Failed to validate block' + ); + }); + + it('should throw error on invalid transactions', () => { + const blockWithInvalidTransactions = { + ...validBlock, + transactions: [ + { + ...firstTransfer, + amount: 'Invalid value', + }, + ], + }; + + expect(() => + block.objectNormalize(blockWithInvalidTransactions) + ).to.throw('Failed to validate transaction'); + }); + }); + + describe('getId()', () => { + it('should throw an error with no param', () => { + expect(block.getId).to.throw(); + }); + + it('should generate the id of the valid block', () => { + expect(block.getId(validBlock)) + .to.be.a('string') + .which.is.equal(validBlock.id); + }); + + it('should update id if a field in block value changes', () => { + expect( + block.getId({ ...validBlock, totalAmount: validBlock.totalAmount + 1 }) + ).to.not.equal(validBlock.id); + }); + }); + + describe('sign()', () => { + it('should throw an error with no param', () => { + expect(block.sign).to.throw(); + }); + + it('should generate the signature of the valid block', () => { + expect( + block.sign( + { ...validBlock, blockSignature: undefined }, + delegateKeyPair + ) + ) + .to.be.a('string') + .which.is.equal(validBlock.blockSignature); + }); + + it('should update signature if a field in block value changes', () => { + expect( + block.sign( + { ...validBlock, totalAmount: validBlock.totalAmount + 1 }, + delegateKeyPair + ) + ).to.not.equal(validBlock.blockSignature); + }); + }); +}); diff --git a/test/unit/logic/blockReward.js b/test/unit/logic/blockReward.js index 7d6eaea6..25a75140 100644 --- a/test/unit/logic/blockReward.js +++ b/test/unit/logic/blockReward.js @@ -1,10 +1,9 @@ 'use strict'; -var chai = require('chai'); -var expect = require('chai').expect; +const { expect } = require('chai'); -var BlockReward = require('../../../logic/blockReward.js'); -var constants = require('../../../helpers/constants.js'); +const BlockReward = require('../../../logic/blockReward.js'); +const constants = require('../../../helpers/constants.js'); function milestoneHeight (milestoneNum) { return constants.rewards.distance * milestoneNum + constants.rewards.offset; @@ -14,397 +13,397 @@ function milestoneSupply (milestoneNum, step) { return constants.totalAmount + constants.rewards.milestones[milestoneNum] * step; } -describe('BlockReward', function () { - var blockReward = new BlockReward(); +describe('BlockReward', () => { + const blockReward = new BlockReward(); - describe('returning calcMilestone', function () { - it('when height is undefined should throw an error', function () { + describe('calcMilestone()', () => { + it('when height is undefined should throw an error', () => { expect(blockReward.calcMilestone).to.throw(/Invalid block height/); }); - it('when height == 0 should return 0', function () { + it('when height == 0 should return 0', () => { expect(blockReward.calcMilestone(0)).to.equal(0); }); - it('when height == 1 should return 0', function () { + it('when height == 1 should return 0', () => { expect(blockReward.calcMilestone(1)).to.equal(0); }); - it('when height == (offset - 1) should return 0', function () { + it('when height == (offset - 1) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.offset - 1)).to.equal(0); }); - it('when height == (offset) should return 0', function () { + it('when height == (offset) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.offset)).to.equal(0); }); - it('when height == (offset + 1) should return 0', function () { + it('when height == (offset + 1) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.offset + 1)).to.equal(0); }); - it('when height == (offset + 2) should return 0', function () { + it('when height == (offset + 2) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.offset + 2)).to.equal(0); }); - it('when height == (distance) should return 0', function () { + it('when height == (distance) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.distance)).to.equal(0); }); - it('when height == (distance + 1) should return 0', function () { + it('when height == (distance + 1) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.distance + 1)).to.equal(0); }); - it('when height == (distance + 2) should return 0', function () { + it('when height == (distance + 2) should return 0', () => { expect(blockReward.calcMilestone(constants.rewards.distance + 2)).to.equal(0); }); - it('when height == (milestoneOne - 1) should return 0', function () { + it('when height == (milestoneOne - 1) should return 0', () => { expect(blockReward.calcMilestone(milestoneHeight(1) - 1)).to.equal(0); }); - it('when height == (milestoneOne) should return 1', function () { + it('when height == (milestoneOne) should return 1', () => { expect(blockReward.calcMilestone(milestoneHeight(1))).to.equal(1); }); - it('when height == (milestoneOne + 1) should return 1', function () { + it('when height == (milestoneOne + 1) should return 1', () => { expect(blockReward.calcMilestone(milestoneHeight(1) + 1)).to.equal(1); }); - it('when height == (milestoneTwo - 1) should return 1', function () { + it('when height == (milestoneTwo - 1) should return 1', () => { expect(blockReward.calcMilestone(milestoneHeight(2) - 1)).to.equal(1); }); - it('when height == (milestoneTwo) should return 2', function () { + it('when height == (milestoneTwo) should return 2', () => { expect(blockReward.calcMilestone(milestoneHeight(2))).to.equal(2); }); - it('when height == (milestoneTwo + 1) should return 2', function () { + it('when height == (milestoneTwo + 1) should return 2', () => { expect(blockReward.calcMilestone(milestoneHeight(2) + 1)).to.equal(2); }); - it('when height == (milestoneThree - 1) should return 2', function () { + it('when height == (milestoneThree - 1) should return 2', () => { expect(blockReward.calcMilestone(milestoneHeight(3) - 1)).to.equal(2); }); - it('when height == (milestoneThree) should return 3', function () { + it('when height == (milestoneThree) should return 3', () => { expect(blockReward.calcMilestone(milestoneHeight(3))).to.equal(3); }); - it('when height == (milestoneThree + 1) should return 3', function () { + it('when height == (milestoneThree + 1) should return 3', () => { expect(blockReward.calcMilestone(milestoneHeight(3) + 1)).to.equal(3); }); - it('when height == (milestoneFour - 1) should return 3', function () { + it('when height == (milestoneFour - 1) should return 3', () => { expect(blockReward.calcMilestone(milestoneHeight(4) - 1)).to.equal(3); }); - it('when height == (milestoneFour) should return 4', function () { + it('when height == (milestoneFour) should return 4', () => { expect(blockReward.calcMilestone(milestoneHeight(4))).to.equal(4); }); - it('when height == (milestoneFour + 1) should return 4', function () { + it('when height == (milestoneFour + 1) should return 4', () => { expect(blockReward.calcMilestone(milestoneHeight(4) + 1)).to.equal(4); }); - it('when height == (milestoneFive - 1) should return 4', function () { + it('when height == (milestoneFive - 1) should return 4', () => { expect(blockReward.calcMilestone(milestoneHeight(5) - 1)).to.equal(4); }); - it('when height == (milestoneFive) should return 5', function () { + it('when height == (milestoneFive) should return 5', () => { expect(blockReward.calcMilestone(milestoneHeight(5))).to.equal(5); }); - it('when height == (milestoneFive + 1) should return 5', function () { + it('when height == (milestoneFive + 1) should return 5', () => { expect(blockReward.calcMilestone(milestoneHeight(5) + 1)).to.equal(5); }); - it('when height == (milestoneSix - 1) should return 5', function () { + it('when height == (milestoneSix - 1) should return 5', () => { expect(blockReward.calcMilestone(milestoneHeight(6) - 1)).to.equal(5); }); - it('when height == (milestoneSix) should return 6', function () { + it('when height == (milestoneSix) should return 6', () => { expect(blockReward.calcMilestone(milestoneHeight(6))).to.equal(6); }); - it('when height == (milestoneSix + 1) should return 6', function () { + it('when height == (milestoneSix + 1) should return 6', () => { expect(blockReward.calcMilestone(milestoneHeight(6) + 1)).to.equal(6); }); - it('when height == (milestoneSeven - 1) should return 6', function () { + it('when height == (milestoneSeven - 1) should return 6', () => { expect(blockReward.calcMilestone(milestoneHeight(7) - 1)).to.equal(6); }); - it('when height == (milestoneSeven) should return 7', function () { + it('when height == (milestoneSeven) should return 7', () => { expect(blockReward.calcMilestone(milestoneHeight(7))).to.equal(7); }); - it('when height == (milestoneSeven + 1) should return 7', function () { + it('when height == (milestoneSeven + 1) should return 7', () => { expect(blockReward.calcMilestone(milestoneHeight(7) + 1)).to.equal(7); }); - it('when height == (milestoneEight - 1) should return 7', function () { + it('when height == (milestoneEight - 1) should return 7', () => { expect(blockReward.calcMilestone(milestoneHeight(8) - 1)).to.equal(7); }); - it('when height == (milestoneEight) should return 8', function () { + it('when height == (milestoneEight) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8))).to.equal(8); }); - it('when height == (milestoneEight + 1) should return 8', function () { + it('when height == (milestoneEight + 1) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) + 1)).to.equal(8); }); - it('when height == (milestoneEight * 2) should return 8', function () { + it('when height == (milestoneEight * 2) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 2)).to.equal(8); }); - it('when height == (milestoneEight * 10) should return 8', function () { + it('when height == (milestoneEight * 10) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 10)).to.equal(8); }); - it('when height == (milestoneEight * 100) should return 8', function () { + it('when height == (milestoneEight * 100) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 100)).to.equal(8); }); - it('when height == (milestoneEight * 1000) should return 8', function () { + it('when height == (milestoneEight * 1000) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 1000)).to.equal(8); }); - it('when height == (milestoneEight * 10000) should return 8', function () { + it('when height == (milestoneEight * 10000) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 10000)).to.equal(8); }); - it('when height == (milestoneEight * 100000) should return 8', function () { + it('when height == (milestoneEight * 100000) should return 8', () => { expect(blockReward.calcMilestone(milestoneHeight(8) * 100000)).to.equal(8); }); }); - describe('returning calcReward', function () { - it('when height is undefined should throw an error', function () { + describe('calcReward()', () => { + it('when height is undefined should throw an error', () => { expect(blockReward.calcReward).to.throw(/Invalid block height/); }); - it('when height == 0 should return 0', function () { + it('when height == 0 should return 0', () => { expect(blockReward.calcReward(0)).to.equal(0); }); - it('when height == 1 should return 0', function () { + it('when height == 1 should return 0', () => { expect(blockReward.calcReward(1)).to.equal(0); }); - it('when height == (offset - 1) should return 0', function () { + it('when height == (offset - 1) should return 0', () => { expect(blockReward.calcReward(constants.rewards.offset - 1)).to.equal(0); }); - it(`when height == (offset) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (offset) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.offset)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (offset + 1) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (offset + 1) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.offset + 1)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (offset + 2) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (offset + 2) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.offset + 2)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (distance) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (distance) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.distance)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (distance + 1) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (distance + 1) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.distance + 1)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (distance + 2) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (distance + 2) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(constants.rewards.distance + 2)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (milestoneOne - 1) should return ${constants.rewards.milestones[0]}`, function () { + it(`when height == (milestoneOne - 1) should return ${constants.rewards.milestones[0]}`, () => { expect(blockReward.calcReward(milestoneHeight(1) - 1)).to.equal(constants.rewards.milestones[0]); }); - it(`when height == (milestoneOne) should return ${constants.rewards.milestones[1]}`, function () { + it(`when height == (milestoneOne) should return ${constants.rewards.milestones[1]}`, () => { expect(blockReward.calcReward(milestoneHeight(1))).to.equal(constants.rewards.milestones[1]); }); - it(`when height == (milestoneOne + 1) should return ${constants.rewards.milestones[1]}`, function () { + it(`when height == (milestoneOne + 1) should return ${constants.rewards.milestones[1]}`, () => { expect(blockReward.calcReward(milestoneHeight(1) + 1)).to.equal(constants.rewards.milestones[1]); }); - it(`when height == (milestoneTwo - 1) should return ${constants.rewards.milestones[1]}`, function () { + it(`when height == (milestoneTwo - 1) should return ${constants.rewards.milestones[1]}`, () => { expect(blockReward.calcReward(milestoneHeight(2) - 1)).to.equal(constants.rewards.milestones[1]); }); - it(`when height == (milestoneTwo) should return ${constants.rewards.milestones[2]}`, function () { + it(`when height == (milestoneTwo) should return ${constants.rewards.milestones[2]}`, () => { expect(blockReward.calcReward(milestoneHeight(2))).to.equal(constants.rewards.milestones[2]); }); - it(`when height == (milestoneTwo + 1) should return ${constants.rewards.milestones[2]}`, function () { + it(`when height == (milestoneTwo + 1) should return ${constants.rewards.milestones[2]}`, () => { expect(blockReward.calcReward(milestoneHeight(2) + 1)).to.equal(constants.rewards.milestones[2]); }); - it(`when height == (milestoneThree - 1) should return ${constants.rewards.milestones[2]}`, function () { + it(`when height == (milestoneThree - 1) should return ${constants.rewards.milestones[2]}`, () => { expect(blockReward.calcReward(milestoneHeight(3) - 1)).to.equal(constants.rewards.milestones[2]); }); - it(`when height == (milestoneThree) should return ${constants.rewards.milestones[3]}`, function () { + it(`when height == (milestoneThree) should return ${constants.rewards.milestones[3]}`, () => { expect(blockReward.calcReward(milestoneHeight(3))).to.equal(constants.rewards.milestones[3]); }); - it(`when height == (milestoneThree + 1) should return ${constants.rewards.milestones[3]}`, function () { + it(`when height == (milestoneThree + 1) should return ${constants.rewards.milestones[3]}`, () => { expect(blockReward.calcReward(milestoneHeight(3) + 1)).to.equal(constants.rewards.milestones[3]); }); - it(`when height == (milestoneFour - 1) should return ${constants.rewards.milestones[3]}`, function () { + it(`when height == (milestoneFour - 1) should return ${constants.rewards.milestones[3]}`, () => { expect(blockReward.calcReward(milestoneHeight(4) - 1)).to.equal(constants.rewards.milestones[3]); }); - it(`when height == (milestoneFour) should return ${constants.rewards.milestones[4]}`, function () { + it(`when height == (milestoneFour) should return ${constants.rewards.milestones[4]}`, () => { expect(blockReward.calcReward(milestoneHeight(4))).to.equal(constants.rewards.milestones[4]); }); - it(`when height == (milestoneFour + 1) should return ${constants.rewards.milestones[4]}`, function () { + it(`when height == (milestoneFour + 1) should return ${constants.rewards.milestones[4]}`, () => { expect(blockReward.calcReward(milestoneHeight(4) + 1)).to.equal(constants.rewards.milestones[4]); }); - it(`when height == (milestoneFive - 1) should return ${constants.rewards.milestones[4]}`, function () { + it(`when height == (milestoneFive - 1) should return ${constants.rewards.milestones[4]}`, () => { expect(blockReward.calcReward(milestoneHeight(5) - 1)).to.equal(constants.rewards.milestones[4]); }); - it(`when height == (milestoneFive) should return ${constants.rewards.milestones[5]}`, function () { + it(`when height == (milestoneFive) should return ${constants.rewards.milestones[5]}`, () => { expect(blockReward.calcReward(milestoneHeight(5))).to.equal(constants.rewards.milestones[5]); }); - it(`when height == (milestoneFive + 1) should return ${constants.rewards.milestones[5]}`, function () { + it(`when height == (milestoneFive + 1) should return ${constants.rewards.milestones[5]}`, () => { expect(blockReward.calcReward(milestoneHeight(5) + 1)).to.equal(constants.rewards.milestones[5]); }); - it(`when height == (milestoneSix - 1) should return ${constants.rewards.milestones[5]}`, function () { + it(`when height == (milestoneSix - 1) should return ${constants.rewards.milestones[5]}`, () => { expect(blockReward.calcReward(milestoneHeight(6) - 1)).to.equal(constants.rewards.milestones[5]); }); - it(`when height == (milestoneSix) should return ${constants.rewards.milestones[6]}`, function () { + it(`when height == (milestoneSix) should return ${constants.rewards.milestones[6]}`, () => { expect(blockReward.calcReward(milestoneHeight(6))).to.equal(constants.rewards.milestones[6]); }); - it(`when height == (milestoneSix + 1) should return ${constants.rewards.milestones[6]}`, function () { + it(`when height == (milestoneSix + 1) should return ${constants.rewards.milestones[6]}`, () => { expect(blockReward.calcReward(milestoneHeight(6) + 1)).to.equal(constants.rewards.milestones[6]); }); - it(`when height == (milestoneSeven - 1) should return ${constants.rewards.milestones[6]}`, function () { + it(`when height == (milestoneSeven - 1) should return ${constants.rewards.milestones[6]}`, () => { expect(blockReward.calcReward(milestoneHeight(7) - 1)).to.equal(constants.rewards.milestones[6]); }); - it(`when height == (milestoneSeven) should return ${constants.rewards.milestones[7]}`, function () { + it(`when height == (milestoneSeven) should return ${constants.rewards.milestones[7]}`, () => { expect(blockReward.calcReward(milestoneHeight(7))).to.equal(constants.rewards.milestones[7]); }); - it(`when height == (milestoneSeven + 1) should return ${constants.rewards.milestones[7]}`, function () { + it(`when height == (milestoneSeven + 1) should return ${constants.rewards.milestones[7]}`, () => { expect(blockReward.calcReward(milestoneHeight(7) + 1)).to.equal(constants.rewards.milestones[7]); }); - it(`when height == (milestoneEight - 1) should return ${constants.rewards.milestones[7]}`, function () { + it(`when height == (milestoneEight - 1) should return ${constants.rewards.milestones[7]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) - 1)).to.equal(constants.rewards.milestones[7]); }); - it(`when height == (milestoneEight) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8))).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight + 1) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight + 1) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) + 1)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 2) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 2) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 2)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 10) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 10) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 10)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 100) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 100) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 100)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 1000) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 1000) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 1000)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 10000) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 10000) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 10000)).to.equal(constants.rewards.milestones[8]); }); - it(`when height == (milestoneEight * 100000) should return ${constants.rewards.milestones[8]}`, function () { + it(`when height == (milestoneEight * 100000) should return ${constants.rewards.milestones[8]}`, () => { expect(blockReward.calcReward(milestoneHeight(8) * 100000)).to.equal(constants.rewards.milestones[8]); }); }); - describe('returning calcSupply', function () { - it('when height is undefined should throw an error', function () { + describe('calcSupply()', () => { + it('when height is undefined should throw an error', () => { expect(blockReward.calcSupply).to.throw(/Invalid block height/); }); - it(`when height == 0 should return ${constants.totalAmount}`, function () { + it(`when height == 0 should return ${constants.totalAmount}`, () => { expect(blockReward.calcSupply(0)).to.equal(constants.totalAmount); }); - it(`when height == 1 should return ${constants.totalAmount}`, function () { + it(`when height == 1 should return ${constants.totalAmount}`, () => { expect(blockReward.calcSupply(1)).to.equal(constants.totalAmount); }); - it(`when height == (offset - 1) should return ${constants.totalAmount}`, function () { + it(`when height == (offset - 1) should return ${constants.totalAmount}`, () => { expect(blockReward.calcSupply(constants.rewards.offset - 1)).to.equal(constants.totalAmount); }); - it(`when height == (offset) should return ${milestoneSupply(0, 1)}`, function () { + it(`when height == (offset) should return ${milestoneSupply(0, 1)}`, () => { expect(blockReward.calcSupply(constants.rewards.offset)).to.equal(milestoneSupply(0, 1)); }); - it(`when height == (offset + 1) should return ${milestoneSupply(0, 2)}`, function () { + it(`when height == (offset + 1) should return ${milestoneSupply(0, 2)}`, () => { expect(blockReward.calcSupply(constants.rewards.offset + 1)).to.equal(milestoneSupply(0, 2)); }); - it(`when height == (offset + 2) should return ${milestoneSupply(0, 3)}`, function () { + it(`when height == (offset + 2) should return ${milestoneSupply(0, 3)}`, () => { expect(blockReward.calcSupply(constants.rewards.offset + 2)).to.equal(milestoneSupply(0, 3)); }); - it(`when height == (distance) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1)}`, function () { + it(`when height == (distance) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1)}`, () => { expect(blockReward.calcSupply(constants.rewards.distance)).to .equal(milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1)); }); - it(`when height == (distance + 1) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1 + 1)}`, function () { + it(`when height == (distance + 1) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1 + 1)}`, () => { expect(blockReward.calcSupply(constants.rewards.distance + 1)).to .equal(milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 1 + 1)); }); - it(`when height == (distance + 2) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 3)}`, function () { + it(`when height == (distance + 2) should return ${milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 3)}`, () => { expect(blockReward.calcSupply(constants.rewards.distance + 2)).to.equal(milestoneSupply(0, constants.rewards.distance - constants.rewards.offset + 3)); }); - it(`when height == (milestoneOne - 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset)}`, function () { + it(`when height == (milestoneOne - 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset)}`, () => { expect(blockReward.calcSupply(milestoneHeight(1) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset)); }); it(`when height == (milestoneOne) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + constants.rewards.milestones[1]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(1))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + constants.rewards.milestones[1]); } ); it(`when height == (milestoneOne + 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + constants.rewards.milestones[1] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(1) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + constants.rewards.milestones[1] * 2); } ); it(`when height == (milestoneTwo - 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(2) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) - 1); } @@ -413,7 +412,7 @@ describe('BlockReward', function () { it(`when height == (milestoneTwo) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + constants.rewards.milestones[2]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(2))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -424,7 +423,7 @@ describe('BlockReward', function () { it(`when height == (milestoneTwo + 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + constants.rewards.milestones[2] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(2) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -435,7 +434,7 @@ describe('BlockReward', function () { it(`when height == (milestoneThree - 1) should return ${milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + (constants.rewards.milestones[2] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(3) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -447,7 +446,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[1] * constants.rewards.distance) + (constants.rewards.milestones[2] * constants.rewards.distance) + constants.rewards.milestones[3]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(3))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -460,7 +459,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[1] * constants.rewards.distance) + (constants.rewards.milestones[2] * constants.rewards.distance) + constants.rewards.milestones[3]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(3) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -473,7 +472,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[1] * constants.rewards.distance) + (constants.rewards.milestones[2] * constants.rewards.distance) + (constants.rewards.milestones[3] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(4) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -487,7 +486,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[2] * constants.rewards.distance) + (constants.rewards.milestones[3] * constants.rewards.distance) + constants.rewards.milestones[4]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(4))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -502,7 +501,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[2] * constants.rewards.distance) + (constants.rewards.milestones[3] * constants.rewards.distance) + constants.rewards.milestones[4] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(4) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -517,7 +516,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[2] * constants.rewards.distance) + (constants.rewards.milestones[3] * constants.rewards.distance) + (constants.rewards.milestones[4] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(5) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -533,7 +532,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[3] * constants.rewards.distance) + (constants.rewards.milestones[4] * constants.rewards.distance) + constants.rewards.milestones[5]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(5))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -550,7 +549,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[3] * constants.rewards.distance) + (constants.rewards.milestones[4] * constants.rewards.distance) + constants.rewards.milestones[5] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(5) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -567,7 +566,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[3] * constants.rewards.distance) + (constants.rewards.milestones[4] * constants.rewards.distance) + (constants.rewards.milestones[5] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(6) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -585,7 +584,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[4] * constants.rewards.distance) + (constants.rewards.milestones[5] * constants.rewards.distance) + constants.rewards.milestones[6]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(6))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -604,7 +603,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[4] * constants.rewards.distance) + (constants.rewards.milestones[5] * constants.rewards.distance) + constants.rewards.milestones[6] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(6) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -623,7 +622,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[4] * constants.rewards.distance) + (constants.rewards.milestones[5] * constants.rewards.distance) + (constants.rewards.milestones[6] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(7) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -643,7 +642,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[5] * constants.rewards.distance) + (constants.rewards.milestones[6] * constants.rewards.distance) + constants.rewards.milestones[7]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(7))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -664,7 +663,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[5] * constants.rewards.distance) + (constants.rewards.milestones[6] * constants.rewards.distance) + constants.rewards.milestones[7] * 2}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(7) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -686,7 +685,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[5] * constants.rewards.distance) + (constants.rewards.milestones[6] * constants.rewards.distance) + (constants.rewards.milestones[7] * constants.rewards.distance) - 1}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) - 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -708,7 +707,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[6] * constants.rewards.distance) + (constants.rewards.milestones[7] * constants.rewards.distance) + (constants.rewards.milestones[8])}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8))).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -731,7 +730,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[6] * constants.rewards.distance) + (constants.rewards.milestones[7] * constants.rewards.distance) + (constants.rewards.milestones[8] * 2)}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) + 1)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -755,7 +754,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 2)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -780,7 +779,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) * 9 + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 10)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -805,7 +804,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) * 99 + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 100)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -830,7 +829,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) * 999 + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 1000)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -855,7 +854,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) * 9999 + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 10000)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -880,7 +879,7 @@ describe('BlockReward', function () { (constants.rewards.milestones[7] * constants.rewards.distance) + constants.rewards.milestones[8] * milestoneHeight(8) * 99999 + constants.rewards.milestones[8]}`, - function () { + () => { expect(blockReward.calcSupply(milestoneHeight(8) * 100000)).to .equal(milestoneSupply(0, milestoneHeight(1) - constants.rewards.offset) + (constants.rewards.milestones[1] * constants.rewards.distance) + @@ -895,9 +894,9 @@ describe('BlockReward', function () { } ); - describe('completely', function () { - describe('before reward offset', function () { - it('should be ok', function () { + describe('completely', () => { + describe('before reward offset', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(1); var prev = supply; @@ -909,8 +908,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 0', function () { - it('should be ok', function () { + describe('for milestone 0', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset - 1); var prev = supply; @@ -922,8 +921,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 1', function () { - it('should be ok', function () { + describe('for milestone 1', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance - 1); var prev = supply; @@ -935,8 +934,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 2', function () { - it('should be ok', function () { + describe('for milestone 2', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 2 - 1); var prev = supply; @@ -948,8 +947,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 3', function () { - it('should be ok', function () { + describe('for milestone 3', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 3 - 1); var prev = supply; @@ -961,8 +960,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 4', function () { - it('should be ok', function () { + describe('for milestone 4', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 4 - 1); var prev = supply; @@ -975,8 +974,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 5', function () { - it('should be ok', function () { + describe('for milestone 5', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 5 - 1); var prev = supply; @@ -989,8 +988,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 6', function () { - it('should be ok', function () { + describe('for milestone 6', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 6 - 1); var prev = supply; @@ -1003,8 +1002,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 7', function () { - it('should be ok', function () { + describe('for milestone 7', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 7 - 1); var prev = supply; @@ -1017,8 +1016,8 @@ describe('BlockReward', function () { }); }); - describe('for milestone 8 and beyond', function () { - it('should be ok', function () { + describe('for milestone 8 and beyond', () => { + it('should be ok', () => { var supply = blockReward.calcSupply(constants.rewards.offset + constants.rewards.distance * 8 - 1); var prev = supply; diff --git a/test/unit/logic/chat.js b/test/unit/logic/chat.js new file mode 100644 index 00000000..d95c4790 --- /dev/null +++ b/test/unit/logic/chat.js @@ -0,0 +1,505 @@ +'use strict'; + +const async = require('async'); + +const { expect } = require('chai'); +const _ = require('lodash'); + +const TransactionLogic = require('../../../logic/transaction.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const AccountModule = require('../../../modules/accounts.js'); +const Chat = require('../../../logic/chat.js'); + +const { modulesLoader } = require('../../common/initModule.js'); + +const constants = require('../../../helpers/constants.js'); +const bignum = require('../../../helpers/bignum.js'); + +const { validSender } = require('../../common/stubs/transactions/common.js'); +const { + validTransaction, + validTransactionData, + rawValidTransaction, + validUnconfirmedTransaction, +} = require('../../common/stubs/transactions/chat.js'); + +describe('Chat', () => { + let chatBindings; + /** + * @type {Chat} + */ + let chat; + let accountsModule; + + before((done) => { + async.auto( + { + rounds(cb) { + modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + }, + accountLogic(cb) { + modulesLoader.initLogicWithDb(AccountLogic, cb, {}); + }, + transactionLogic: [ + 'rounds', + 'accountLogic', + (result, cb) => { + modulesLoader.initLogicWithDb( + TransactionLogic, + (err, __transaction) => { + __transaction.bindModules(result); + cb(err, __transaction); + }, + { + ed: modulesLoader.scope.ed, + account: result.account, + } + ); + }, + ], + accountModule: [ + 'accountLogic', + 'transactionLogic', + (result, cb) => { + modulesLoader.initModuleWithDb(AccountModule, cb, { + logic: { + account: result.accountLogic, + transaction: result.transactionLogic, + }, + }); + }, + ], + }, + (error, result) => { + if (error) { + return done(error); + } + chat = new Chat( + modulesLoader.db, + modulesLoader.scope.ed, + modulesLoader.scope.schema, + modulesLoader.scope.logger + ); + chatBindings = { + rounds: result.rounds, + accounts: result.accountModule, + }; + chat.bind(chatBindings.accounts, chatBindings.rounds); + accountsModule = result.accountModule; + done(); + } + ); + }); + + describe('bind()', () => { + it('should be okay with correct params', () => { + expect(() => { + chat.bind(chatBindings.accounts, chatBindings.rounds); + }).to.not.throw(); + }); + + after(() => { + chat.bind(chatBindings.accounts, chatBindings.rounds); + }); + }); + + describe('create()', () => { + it('should throw with empty parameters', () => { + expect(() => { + chat.create(); + }).to.throw(); + }); + + it('should be okay with valid parameters', () => { + expect(chat.create(validTransactionData, validTransaction)).to.be.an( + 'object' + ); + }); + }); + + describe('calculateFee()', () => { + it('should set higher fees for very long messages', () => { + const shortMessage = { + id: '438452752317142988', + height: 10224582, + blockId: '5808058151912629759', + type: 8, + block_timestamp: 58449060, + timestamp: 58449055, + senderPublicKey: + '12d6b3f80221a2b0b6d2ef07ae33fce28204c1906ec1bba1d15be693d3353ec4', + senderId: 'U839357947177758191', + recipientId: 'U18018989827016540480', + recipientPublicKey: + 'ec48de9b438ae9f12e271ba28d56eb0b3f3bba7b120df7685eddda97c9f79160', + amount: 0, + fee: 100000, + signatures: [], + confirmations: null, + asset: { + chat: { + message: '3e5314dfc9a1095eb874d76cd878ea5a8420ab2a', + own_message: 'e26b9454b0927c904863e44bca30aa4d05bf3ee3f9084976', + type: 1, + }, + }, + }; + const longMessage = { + id: '11526778501097815775', + height: 43309687, + blockId: '4836663956106296575', + type: 8, + block_timestamp: 226029230, + timestamp: 226029223, + senderPublicKey: + '1ed651ec1c686c23249dadb2cb656edd5f8e7d35076815d8a81c395c3eed1a85', + senderId: 'U3716604363012166999', + recipientId: 'U15348108860160945984', + recipientPublicKey: + '37916bde1d49df4041fdc5869cb47f2836df11be48a0a88aafa6152d86f217b2', + amount: 0, + fee: 1700000, + signature: + 'ddf895f70c9ff5c513c0acafc77789d01f9a31032d51c6a85fd629983ee63c03dae5312f990fc3ad41fc1d64d593b359618f424b62e6532cc529a06dc8de3c05', + signatures: [], + confirmations: 1, + asset: { + chat: { + message: + '3b993b1d6d0fc6d97cff9ac72abc65faa46f554acf799095b32a0cd3b7dca693634b89b9e4e3d600ef72ede2ca69ca7024631d55e74af938035b0c6a6db22e0be1dba549b8afe1e67db3440263c5ffba55115caf1d6a8e51bb80b61cee2fe4a31d8a9b22ce5030967aabd74c985e3c8eaae15db3700daad84eb8271d48cf62e04f33b65df6ad2f098631627c5ea5f43611e631fa1aef832b560d533a12b2ea26a59b020430f7b281f6a149a6d37fc6c838b0dd5ebcf60b95c770c6a89ac78a3a21528f2131360560d1edf43bb93b106978de5b691fdc2699dd40d129a2e124c101cafef2c05eef99422b55a158001cab4528117ffa16b740acf3169c73256bf8b55a6d1003f1e9a3368ded8bef1426385164e6af86d3d7fe73e0e63e62bda514eadfb4993ff406be26a69fd90102cd76e0d419a800144f7a88ff880eb09e56fc28cfa1234d19a1f7902cbdf82609ce5ddbdf2798a6f64b4af7cb8164f83992af2f599a9e63ec848a3027bfbe14b9c9ef37863a1b835b800679a358f6a6058051efc734bfe6470b103e72df1aa250be3cfa197236255f7f40379a4791d4b581fb5bb58fbbbcddf2634e652c2c72745e7d43bde3302214e1688a79b94bb068b9be9a12db27a4c529e66c86e1e574fd06a0484c8d798ac5d53617fb1a522a6d94602ed5a27e7eaf3070360ea20d84ac0089085f99672254a70a234dab9bffb10d6897080ed123dbf473f006d53d5e122fb47398a0a6fb322a1c63f271a01e0f7407901603e8a29d9ab91d3ac460065a80b4fda5ae4b335b819286d7dfadce9b2b3b7817874ddda62bf515445e02e57ee9dc7efa09f6df2b1c838beed73ddd6fd24cd5fd8e7a5e0d6be735ae57b8eba056981647b9c4213842903e3e3368d4b62ebe702886e5185c45d3440559939e90babad2d487a734602aed154083219c90e3ddf2abc7d7b3eb314b386ef593d2f7a8b87e23f836556b36350c4ef3e400e9433e1f6cf4af6ad8ae0823b525fdf999c6fb0875f4aec0f56cf37ccb83d229e39994df22ac7a27bf85d96a9684358f61c0278321c84c4cc6df3b58c20d4d858e323be57f02b32c847ad085985031b5c3872f8858655689881f7fc1984993d931c3e76139e50d6ae39129c957ec1f1c40730c0243d17753449051b18829226756e3c875fa9a09a4c238c3d5ba64c362dd3ef3e17f00e8cafc9e6bb723c73101868d9ae839bb4feec81b27b5b2974ce290d1609350bf7d8cb2dbb3d18f0cce99815b50deda814aec7727fe1097e12357d729cd62e31552a05e8223d3236ec345a0366832f196874ed04abe7d5c44d195f5c5759037e6a538d391c1b542d04a4382b13e2b5fcb740a3483ae57e250e377840f9bf0a103ecddd5c55afc3e4f8f182d3f4ec7bf28909a23c26eda3a2b8bc5e9bdb628f977380341f3a4d1468298b638720b6c6e03fa5f6c0d4863514e7a8af3dc8b03e31626c9d499dcd9879eb6f44c03346fb72255f20ab9d52dc9aa7975b014f0e66ef1747d275368fba85762fe09c53d0b2a5a8964bf008825635af5ee7d804a93e75f62a8f035b6c7d13957fcb9c6f78ed0e077386d23ce4280ed346423a495e0c801633af207451e210b10b9813773295abc77f6b24d3a6ec6907f83e5d3f0123c680338b07a071c7713849692eb2949307926b41968dad3a4a8606efd3dae645576b27c82c21bd865eaa7a17734f9e9b1b4f67c32bf035f25cf091f4fa55a46c6f54de8bef6abff0d666a51762ededfe89cdf86f4a32316e9494ba4526a86c75c39e9fe789825857a145a8d978928268eeaad401227eb0ddc48f70966b947f51ece662b8704747f05a9a36788e50a5603959ee19d09db3c3f0499201d2c7a9e2b14c7eb8cbff0e82a3729645e5330d63f72f1e928c29b8e150e18fe2936427245573b73ec5b25e33a04c88b5b7b143b5d87d97fbdc131d907046a20be820986b6b28cb2f99cb0c495dab6ce2bdeff9d86ee692de3dc41605b40a9c52f0ffef9e454ec4f89cbad3b9137ee3321b8ebd19747793cd304d093bab8818718627b000cae796017645bf9bfbfbf40684737edb621ecbd302b53d3c7e7407fed35c813e7d227c40b273532af65a5c16f723fecbc8967b62dbfb9987e1e08f1b45e80abfb1409c6cc60000a344a88b8076af309bfbd08a154aea8ce1c25d1e10c33d1c1e4cdf2a0748f682415d3fe2179e7a133e94c133244dc6b032e68164f57fc68ae7528aca37866063e1dd0c06d38e546a0f76ad7291faf8b78645d063ffb35525c0c28ab640acb19bd2fe9fbd8da2517511d413faf9d7e9e1f3d057d474c428ab58a9851653f00bc33a82e6beda6dc467a0024351dbb477f4ce12f171d4c975ec7e9149026e450aaeadab7f84d5032934d2fcba8e8e21867da9b4e47ef02c8b3c0580b53115230ba7e0854cdc566c71468a8e2668ac576afa6064a7471d9e0a23c5ffbf55cfdd51b79b2f5cfeacc9d95c20f1114726257bc90c7b14e1d67b4c6ff5b924b6f907b224e946a1cc640e93bd0fe5473b2af05454695a0896f6a4d971b5bfca064d42f81ee258004258fd1a8b93316fb8a1f94d83569d6f5125dc54ee3e97d997ae1c365acb40ba545edb5dff0dee9f0bb48724ed51a8ec2dbce2748de5a98a5e85fc876c33bd2d6aa2478224ec98cbeb20fd34e7c463361adeb9ea006d6386a2f53098652d5748a832234d5c82ea94dc7043dc788e01a8905c39c39b5e808ad7bd788696f67b0187e3793454670b5ec5c05b3017640d0c289d9ace3a5bc90cd63f694be34bc0964581bb2e0f4bd2996b05de1d83d31c51db2ce03a9b16c980bc2952d6430de277f1aa209c19589d2bf8a45f98f145314a5cb9058263afa544d60018f12fa5db7635faed7eca02148e7f89022d3b8daedd48b8078e529e3d6c4f53b3191345b79ef0492862f06cc6f9a36b87f4902706d8760dc7042afe7f0b1d78c48a06dd6192429071fae27b5a9db8199c18f0b59c35ef29a104e236b86acbeae4bacfc2fe8e8a575bd7b465d3f71f37c33d621dcf7acc3f84a84dc9be77dd60cc2b3e67e4fbaa76f320f2bee6272fa2af8b5748e4bf59951f5cba8a6d6fd6dc7ab5a903c2d6a73b28c14dc0073564905a9df195df0132181fc651bbdf1a6e27ebb22bcd60eb24b6985442c38192542dd6b6f4682ef611843ae02dcd39ae11e10c8d53d59c8efd52b406ae29f30eaa0031e2cf53f42ceb6342c85571f10dc7c15c6a9276eec8a724595d54ea9c675a898a2f2ba9562963ac465b3d14272cb162e1475b05f7c2e77350dcdfb4a289d7e65bc580af4a51ed0bb92ba5f7100ec0a66a178f50727f8cb1db553f3e9f17d631da606caed958f6465c1d0274a7d965efc409efdf1c637eea4075f02b0ee3cd67fb1897a6296f8adbb88b53ab9e4536973795e618cac66a8cff07f5ccaca9fe83cba990039c5dd3307cfae49fbb3c29d45b30996e0883c909c2ab75ab72aaebf19ec3b040a4a52ce88c62ab00d70a5fb0f569d5ddef3572d4d6a2f7104bcfc2d89b2330db7252ed9628463fbae76113754e17b46728afa77481feef0ed4e496a3136c7a1ff728c411012ed12521bca984052247535ab68340b08c659ae2c6c4247f56f3248bebff8557640ff6233ab94ed1d9ea6097b67ee62a0a3c7d528e27cf3e1e1180ce58364fa616108910fde43d866d4d479f81048396252c6c9725c8c26eaeb03e2b7cca824aa005dbd9970828f77922d0fb4fe905f8b68c6872db3d699a8dac13ad84bc3dd40538cbcfc069be6e79b318e353506be4bda8a2c802a232a1750547c1a7e61a1ad0a29c135de66c79472b87151610a82e3d7ff3ba2ce46a3bd009f35c902fc1bc68da772dc860b6ab1462b4774455eece1b80cfcccd0ca1c9e4bb9751fd601c5dabc76bb3ce43be3993678f9f365073a63054aa4127ee424a422079d1b172c610a172249ec62ea6f1b91fbba0c420fc62fa010a7008361dcd4ea167d5bca3b3c4577673a7fe8e80c5f19ee41353792aa0c0afda58c3518d20dbfe5ac81e8da00b287e5d11ffe9b9d5c8b37d387d156baee3a7b88d7865553ef744b5ea17640d373910aaa0014e079a366f253a354a6325092c4de9bf37c1465d33155ce391b24dbbe83ed8521fe942c2a3bdea28e10057079fff79e5523665cfc01675f268aab7730636384788d4b19a2420dc7e1f72ce6cf62f0710dd9081f457d64795e1556038f69dfe25fff8976dc092fa8b9ba1cce2960595f32f9a555dddf6f120c9bc89bc3e473346504f14ae3c4624d18ac3f33f09599c2170d86127456ab03faf55587a54671cd03a4b57e92be822c46348c14c068c07d7912e00668b73dddb44c1fd96b3993b6df13c6888fe1d7fde037785716fc6550cc81738a122f21c79ada4c5c2c999690c93c7b8fcc78f56364db136aa2e671994f29756c20b73c399914085e819332b4bc243960a98f04605451005b008d82a76eef5c5058764fa8af569ab720fca84174d0fad1acad498abb13a25b8394e71b2f499c926b9e60a0aa8c9815ae3cf1177d19c5e12b02cac7737247dacf44c69e796f6f552212def4baac7ab7566b981275ad05422dd97cf0997761d03b4f07b7d38fbaca81ce2a86d1c669013e1d8ce1d37fc69f8bdf7bbf3ea17cad300a40c10b1dcda025f006deb8e8b99d91eea6ea117b58c4e0fe858686379aeabf0c06736bba33cc4b52af573056be4c947756eb61255c2a8bf240e402f2bfd0b5243299b91a8a23f0f288e7d0d7764399dd2f17e55c4d513daa06115afa941327add61e4aa48f9d9bf8738f4c1dd197d92e35d3a9ec392525aac0bd49c614d5e376b7b9a0b1a39ed3e2ca88201379c18b9050f94ae7afc7083aec43248cbb9009f86826565ff530a575b6ba81a5d19251889c8d3b356d5fe57c3afe52cb6872eac5715bd52b5ff9659ae1f01bdd9919776ce38f40ee758af2cf3bde0009485f9ccf4667afc7e8f830e5969e8e1f0fcf6e01bec99e9309965ca11a70ed844adf427f8421d33adfa358417d8b7491e56e82d0607a48cb7738771c957cd4146076ee0ab1d3b919bf3b46fbdb2e9fea2db25c19198ee628fea550f8d6b9a57131464651470bc97384535973eb5926be344714f7f2d773dc66fc8f5d12f4a1fa1a95003380bac6f8cd52bdd0bf0217ea03478e94c22023856e6a4988ccf81c036229e69d882aaa900a19466a1234093c7a3315190847beb94f8ef525c50e6c830f9e22a9e1c431649050c5bad7e77e38c457d7dd780d6521218af80b1cf2df51e01e35b2c01db3c74b8ff9d0d6943f897f48824198d076ab44579aabc62ded89e8f81c194c0a371007e9540aa4a0ec930cbcdf4dd6e3c28306dca5a25a01d207823c46820c35420014c11b68e8ebac730b1daa98b884db141044e2dd03b0ed4c214bd821ee5410597014dd7083f2fe3831c5932f3514537e0b4d0853680d02f2190a5582a75bfb75173053c0ced7553d4d24363accb52651056b802f0df48d8264f0c0cb9cb7b0967730049f291033a93e3bd4fe632414d5989e5b0771653198ad2922e2f3ab441b9c14fcf4f3a7b828a16bcfc0d714cce533ccda1c27bc3e48ebdef2aacc121e5113ad28a141560b69b9bff890970065b11bea62e6e4b1b21477fdde6eaf94393e27932ac2fe6ce871cf42a6ed6f8b0ae1ff5a79e0ca49ae80d1b6c246bbfadc47119011658899744662a22d4ea71892747759d475ae4e6f7a045dc3fdcd6866aed762babc6ccf182c5df3038700cd755cb2178ca1a5b29d1258e61ea909056b78b645632a0ef15bdc0ea84a9668852f53f9472a5bb6505cc3bdba2993e394959c1d63c61ba0367d39fe3fce035bcc3c752d15048fafe51ea71075b6f0dc9e5e313306247e1e39164c42b1eaf56660909a34bbdbafb90c82529bc951ca31afe853d4074db7557d7ec15b3fd92141848b8b428ac805b75a0bf4bd9371bf78b97ea102348a2c39c8f7b756b16b5c68d5dcc530473145bb5ef7e0b7c868b2b7ab7e40c0d1a40a8c53a17eb0ba3e42ecc883c362e6beceb57529f676c7c19210e38dca4adaa74b0e53729f21b9d0a60d4ff124d2293db5f498efb1525e63696412e5c43cfbc9b310873ad0823ee374dce3d50db028ea73dd7619d6c1e7a92469cbd17661fadddfc93ae92e286459b8feec83405611c5998f62d7e82800ffcbbd4f35251c0d63fcb76e707af99f38812188c754342a8dfda20ca7177b9565de1d6127ac5ff69099f6160ef50ed31b8b452f8b523c6954993adfbf337e5108ba88f045d2f8ad79853e5ddfae57d2cc9ee51e1b87273948fd61b417d7e1e25aea262cb4604c6bf57a52193a24198ac1ccba957ba0d63b97306ff9d49abf485f0852ec1f9a68f4d88ba0969ab053dc331cfb0e4f3dd8e898a926f4d90639a9dcc673b4a95633d3c55b750f737464d70aefd75f5cf23a0c4d60f5d2612d9b8581b360ac59ae2b989aae5ab2e2619aa3b1d4a7f7893461d1ddf25e41fd5cc2f62d2f55193ac2db9d0a433eaf42d597fe2d2a4ce6553acc2c74e7e64b9c64de0289f6fc4c879f42db66c7e37fd52f790bfc1ed8fa813167cc311acef240c5e436a7c90d1e1ff073243d89c4e35329c8b8516508879ff77108c8ae1b9e307dfece5641824b454f2a2376cbad476c1b865f8cb196f8605bb8d679788a35b385eab82bd1d375afb8363c633ebe2985cc9b7e8af3068f6d5c684cd2538999352410410328c4936c8fbffc97da00078c35d7c5d60e9f94421709c4145b35d1e05ac10ff4834d49c8e624ee07482d9f97682c8ddcaf6ce6c3660f410015893e33566db47efc3c0e6c2d85dc0ca0a9f94908bb83bd0a96b5a5f97a6c9266879d86667b433de197558f54cafbc2a21b0014241693f7dcbb9c78f797b52d9996fdb714190429435d0e40b641e9ccfbeb6c6dfd8a424f337fa2d52de5ec333658327132c557fe1edff84be887c23f9ffa93b49854deede86a1cbc0426deb46f019889eea08b3df053a5cb89c831eb2aa77360abdd8af5000bbc0f656235751b3cd5a1ddbf12874a87a98fc2e45f0b45002b2b88810c99a7b0edc8e503db2f316f417f5af2c9940ec7710c3003e1088bd82f47ec45a8b7c3c7addeb4d19c8ab4e5109f8cc7283dad9b73dee9e1741fb1a7b8946808b4749b8f1706a7ff65552c69da5e81625141c37961436b3ca9cc0c25f088245a5c33bdb449859b4ba55e014429faf3ed60bc8cf60f6b106e5f8ad68af5e224e86910794a94d89528b19ad0e83a9c445b5219b2478a76b0119f525ffb2dde0efe05a107b9d268f49dc3de7a3c3c88f2abfedb241e9ed7560e8e60c2088592ef0c3f56c923f2758601711e3015b9d703de8bb2ebaa900236be29540e4f1761eed2da9c9c1efaa5f7be51d1a6d9dcce136e675b335d8b3d5fdb6e546265b0293c74836c5643b65425ff8fe32d1aba644a26fa8890af8794aacd580508f2e01e0ec9a614fa68dab64b191fcd703780eef2e6626329a597a29f4f5918c3f9e18be2ed01de8e8518bcf61eb1e08588a3d42665aaebba7fd166c409ed06a410e29416680d811c56eefae9f20b4723783496812acc51fda2f5c8f6bfddeccc142d2ed6e062666c00122dcb47b2766c3f5188017934c3ee2da82e02783743f09b7a9891a7b47d2a43190613e5aa08216df71ef57ee895eda76777d3973783e42f37fe7ff1abd2f98d36ac873b1e8e15ee17f17c0f3eafd74db5f908594c9cf96e040b9deb0b546ffe12f0c329833cf630c799f174434cb3fa89c2d9cf4a5cbbf423defa7a1714b601928c41d3cc79cfe958b71dfb0cc64ab5d43a688de5513b6e28c234f2b9614e5e80bce9f557b10d0118793d954cd827d0df9f43bbb8342b40c053e3f16353c2f2f8369a2b091ba6d1fff79af45577cd0ea02547230f268b0e784944e7084aaf9969d51672b4ae4a6ae32ce5a7e3afd356e51318c601e2d18bc3d118cd23c9f832adc8572a250dcfbaff28068fa9c8950de7db7d540c53b7b84d9cac0800652e6b93f50779aaf665287a90b39776bcd49775a754e696510ecf6a71098227c4980afc8090441d983720c55a78f9f96078cab9993ecd7966cd5a2ca1878c43705261e2f42e6d43086ae76ab575c3a955001ad58b018439490b9597e22ff7aebd3c19f4ec187b3dd7b95c26e4b197742677cf5a1d6072a0fe12004161dddf20feba199e8f8bbb1bc50bce316902a197d3ef1e09c86b536c76f07c21a9b64c13c9aec737b52b508c2eb18c9ab28853f7ffc52baec57be37ffbf52be79d4c0c201fdd07737c624ee1d79d5cabdbce9eb1f350c33ed81fbed9829358d80cb9a854f52e7be8d6bb17343a2215e4068dd485a34afaa8790b9661c046874f30dde4bc8213ab3c9a192114f31132de778cfeaf4d9cffa574cc4827074535cf4319727500d721193df7ba80f5b46a6ccf085f044172386cdf30ae4d77b28b2fffdeba38f840699d1458bd089f8fb577434e3e960f38bbd4adffed4a64d5339db80019c0a16e7cfc031f4ef1f5872131e43aa0951916bd9b4bbd13817b56f13df2a04e9feecc95fe6f8357c4452ad9de393033a35765b7571f1d87694af76e6008b0c316501c0feb6434c827854bc11377f7eb230ee4fca44eb6098d63b6df70a8d78e7cea23d725cfbe98e9fc9cf662e310846e137c1149b1e92b089549071c94c87bbe2e32a83bc3ecc8a24f1f6c966d65665883a41313d58f65aa3ff97e9f64cdcc87fbeb7ed6f856b1838eb0fcc1027e1b00b97188f8910a5b2bffa2a309919b4406002758008aa11060dc881ea03232c8323e1fb34c2725558ca82ee7caf17fb5f0ec94d5bd57d0e1d36ba0ede3ba9bde5bc8bb639ca0e6b65d1d3793a765bd9a1322cd258eb64404aec9f2a497fc7dce8db8ed3c6fa5c1fd6dd145c655cb8adca26d2b9785c55e676c55ce2475e1001b8ca5a9b72757e119a8586f08deb2d99d281436d9d4d5742556790e1db0ef594a7e557b413d61e3e2a6409481b560534be53b5e12f24d5b3adaa72a41d30872bc5c4efee405721a67b9200659ba575756824d5b7483e2d179b335f061b182f31e4a62b1fb83cf88b8c0997b0414357a0cf49b6f144743dd535405d90e1901ef82056ce2342c0f15aa9cb25f7e2a7aa693a2c37cd21e4602f1e41cbdb774eae7d9df1676d5b552d6e90f50cddb53ac6fac76418385a9390dfbabba9c882033e190af233c6283b090787e42d5431cd2d2d80d873a232d327a005cffd4e493a1df31d057d05ae503b46629d1a11bb6677e1456d4ba425143c6e500f7752d100d43206f15d92708dde88f3e84daa5e129b9b9037c0c148473cc40297d19c3c11a793305a6755a966285909d0c27b9b021f7f13716b11269de89fc1fbed4a8c56c3a7fe351287d373e18293a3bdf46492387b254cd1118f1868dc7cc80069744f82161068753e0ac', + own_message: '5664be2b474a48f65e094f1df448e0f11866da00f3d227c6', + type: 1, + }, + }, + }; + + const shortMessageFee = chat.calculateFee(shortMessage); + const longMessageFee = chat.calculateFee(longMessage); + + expect(longMessageFee).greaterThan(shortMessageFee); + }); + + it('should use transfer fees if it is a message with a transfer', () => { + const transaction = { + id: '11917958650570868382', + height: 43320192, + blockId: '15216271678937402799', + type: 8, + block_timestamp: 226081760, + timestamp: 226081753, + senderPublicKey: + '1ed651ec1c686c23249dadb2cb656edd5f8e7d35076815d8a81c395c3eed1a85', + senderId: 'U3716604363012166999', + recipientId: 'U15348108860160945984', + recipientPublicKey: + '37916bde1d49df4041fdc5869cb47f2836df11be48a0a88aafa6152d86f217b2', + amount: 100000000, + fee: 50000000, + signature: + '7a974d575eed40b6dcc8266f08c83b594bf926e35f59f7dd4c15c084a09ca5f3ca8dda612103552ff438e66f71a4b14b9612c5c6a04b666bfee9e85c03abc903', + signatures: [], + confirmations: 3, + asset: { + chat: { + message: + '7a82b8c052ccb0a95aa100de7fa3853295d3b6bad2e1a7ce2696d7df2e82394fa14db51051e0a07132ec', + own_message: '2634f6916736952d395afc8399699cb938232d1e6a9631e2', + type: 1, + }, + }, + }; + + const fee = chat.calculateFee(transaction); + + expect(fee).to.equal(constants.fees.send); + }); + }); + + describe('verify()', () => { + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + delete trs.recipientId; + chat.verify(trs, validSender, (error) => { + expect(error).to.equal('Invalid recipient'); + done(); + }); + }); + + it('should return error if asset chat is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + delete trs.asset.chat; + + chat.verify(trs, validSender, (error) => { + expect(error).to.equal('Invalid transaction asset'); + done(); + }); + }); + + it('should return error if asset chat type is invalid', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.chat.type = 72; + + chat.verify(trs, validSender, (error) => { + expect(error).to.equal('Invalid message type'); + done(); + }); + }); + + it('should return error if message is empty', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.chat.message = ' '.repeat(256); + + chat.verify(trs, validSender, (error) => { + expect(error).to.equal('Message must not be blank'); + done(); + }); + }); + + it('should return error if message is too long', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.chat.message = 'f'.repeat(20481); + + chat.verify(trs, validSender, (error) => { + expect(error).to.equal( + 'Message is too long. Maximum is 20480 characters' + ); + done(); + }); + }); + + it('should verify for a valid transaction', (done) => { + chat.verify(validTransaction, validSender, done); + }); + }); + + describe('process()', () => { + it('should be okay', (done) => { + chat.process(validTransaction, validSender, done); + }); + }); + + describe('getBytes()', () => { + it('should throw an error with no param', () => { + expect(chat.getBytes).to.throw(); + }); + + it('should return same result when called multiple times', () => { + const firstCalculation = chat.getBytes(validTransaction); + const secondCalculation = chat.getBytes(validTransaction); + expect(firstCalculation.equals(secondCalculation)).to.be.true; + }); + + it('should return the valid buffer', () => { + expect(chat.getBytes(validTransaction)).to.eql( + Buffer.from( + '9ae819297240f00bdc3627133c2e41efd27b022fcd0d011dfdda0941ba08399697f3e3bb5c46a43aff714ae1bac616b84617ce446d808523a14f278e5d88909837848e7aa69d9d4f9a95baae56df6ad4c274248d3d01a2cfccae51367dfab265a055d5ce991af654ee418839f94885876638863d172226b0369cd488c5727e6b1a42ba46fed014c1bf586dd2cab3afe7f10cb54864c099a680d5963778c9c4052df305497edc43082a7d60193650c331c6db9c9d9c0c8bbc004e53ac56586331453164b984c57a495810d709c9b984e4f367888d8a8ce1b26f528c1abdec08747e6802a9e744aa3ba570d7e48fce5fe0f49184d0ce38ea40f701000000', + 'hex' + ) + ); + }); + }); + + describe('apply()', () => { + const dummyBlock = { + id: '9314232245035524467', + height: 1, + }; + + function undoTransaction(trs, sender, done) { + chat.undo.call(null, trs, dummyBlock, sender, done); + } + + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.amount = 1000; + delete trs.recipientId; + chat.apply.call(null, trs, dummyBlock, validSender, (error) => { + expect(error).to.equal('Missing address or public key'); + done(); + }); + }); + + it('should be okay for a valid transaction', (done) => { + accountsModule.getAccount( + { address: validUnconfirmedTransaction.recipientId }, + (error, accountBefore) => { + expect(error).not.to.exist; + expect(accountBefore).to.exist; + + const amount = new bignum( + validUnconfirmedTransaction.amount.toString() + ); + const balanceBefore = new bignum(accountBefore.balance.toString()); + + chat.apply.call( + null, + validUnconfirmedTransaction, + dummyBlock, + validSender, + (error) => { + expect(error).to.not.exist; + + accountsModule.getAccount( + { address: validUnconfirmedTransaction.recipientId }, + (error, accountAfter) => { + expect(error).to.not.exist; + expect(accountAfter).to.exist; + + const balanceAfter = new bignum( + accountAfter.balance.toString() + ); + expect(balanceBefore.plus(amount).toString()).to.equal( + balanceAfter.toString() + ); + undoTransaction( + validUnconfirmedTransaction, + validSender, + done + ); + } + ); + } + ); + } + ); + }); + }); + + describe('undo()', () => { + const dummyBlock = { + id: '9314232245035524467', + height: 1, + }; + + function applyTransaction(trs, sender, done) { + chat.apply.call(null, trs, dummyBlock, sender, done); + } + + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.amount = 1000; + delete trs.recipientId; + chat.undo.call(null, trs, dummyBlock, validSender, (error) => { + expect(error).to.equal('Missing address or public key'); + done(); + }); + }); + + it('should be okay for a valid transaction', (done) => { + accountsModule.getAccount( + { address: validUnconfirmedTransaction.recipientId }, + (error, accountBefore) => { + expect(error).to.not.exist; + + const amount = new bignum( + validUnconfirmedTransaction.amount.toString() + ); + const balanceBefore = new bignum(accountBefore.balance.toString()); + + chat.undo.call( + null, + validUnconfirmedTransaction, + dummyBlock, + validSender, + (error) => { + expect(error).to.not.exist; + + accountsModule.getAccount( + { address: validUnconfirmedTransaction.recipientId }, + (error, accountAfter) => { + expect(error).to.not.exist; + + const balanceAfter = new bignum( + accountAfter.balance.toString() + ); + expect(balanceAfter.plus(amount).toString()).to.equal( + balanceBefore.toString() + ); + applyTransaction( + validUnconfirmedTransaction, + validSender, + done + ); + } + ); + } + ); + } + ); + }); + }); + + describe('applyUnconfirmed()', () => { + it('should be okay with valid params', (done) => { + chat.applyUnconfirmed.call(null, validTransaction, validSender, done); + }); + }); + + describe('undoUnconfirmed()', () => { + it('should be okay with valid params', (done) => { + chat.applyUnconfirmed.call(null, validTransaction, validSender, done); + }); + }); + + describe('objectNormalize()', () => { + it('should remove null and undefined dapp from trs', () => { + const trs = _.cloneDeep(validTransaction); + + trs.asset.chat.preview = null; + trs.asset.chat.count = undefined; + + const normalized = chat.objectNormalize(trs); + expect(normalized.asset.chat).to.not.have.key('preview'); + expect(normalized.asset.chat).to.not.have.key('count'); + }); + }); + + describe('dbRead()', () => { + it('should throw an error with no param', () => { + expect(chat.dbRead).to.throw(); + }); + + it('should return null if c_message field is not present', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + delete rawTrs.c_message; + const trs = chat.dbRead(rawTrs); + expect(trs).to.be.null; + }); + + it('should return chat object with correct fields', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + const trs = chat.dbRead(rawTrs); + const expectedKeys = ['message', 'own_message', 'type']; + expect(trs.chat).to.be.an('object'); + expect(trs.chat).to.have.keys(expectedKeys); + }); + }); + + describe('dbSave()', () => { + it('should throw an error with no param', () => { + expect(chat.dbSave).to.throw(); + }); + + it('should return promise object for valid parameters', () => { + const saveQuery = chat.dbSave(validTransaction); + const keys = ['table', 'fields', 'values']; + const valuesKeys = ['message', 'own_message', 'type', 'transactionId']; + expect(saveQuery).to.be.an('object'); + expect(saveQuery).to.have.keys(keys); + expect(saveQuery.values).to.have.keys(valuesKeys); + }); + }); + + describe('afterSave()', () => { + it('should be okay', (done) => { + chat.afterSave(validTransaction, done); + }); + }); + + describe('ready()', () => { + it('should return true when sender does not have multisignatures', () => { + expect(chat.ready(validTransaction, validSender)).to.be.true; + }); + }); +}); diff --git a/test/unit/logic/delegate.js b/test/unit/logic/delegate.js new file mode 100644 index 00000000..0509e145 --- /dev/null +++ b/test/unit/logic/delegate.js @@ -0,0 +1,387 @@ +'use strict'; + +const async = require('async'); + +const { expect } = require('chai'); +const _ = require('lodash'); + +const TransactionLogic = require('../../../logic/transaction.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const AccountModule = require('../../../modules/accounts.js'); +const Delegate = require('../../../logic/delegate.js'); + +const { modulesLoader } = require('../../common/initModule.js'); + +const constants = require('../../../helpers/constants.js'); +const transactionTypes = require('../../../helpers/transactionTypes.js'); + +const { validSender } = require('../../common/stubs/transactions/common.js') +const { + validTransaction, + validTransactionData, + validUnconfirmedTransaction, + rawValidTransaction, +} = require('../../common/stubs/transactions/delegate.js') + +describe('Delegate', () => { + let delegateBindings; + /** + * @type {Delegate} + */ + let delegate; + let transaction; + let accountsModule; + + const dummyBlock = { + id: '9314232245035524467', + height: 1, + }; + + const dummySender = { + address: validUnconfirmedTransaction.senderId, + }; + + before((done) => { + async.auto( + { + rounds(cb) { + modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + }, + accountLogic(cb) { + modulesLoader.initLogicWithDb(AccountLogic, cb, {}); + }, + transactionLogic: [ + 'rounds', + 'accountLogic', + (result, cb) => { + modulesLoader.initLogicWithDb( + TransactionLogic, + (err, __transaction) => { + __transaction.bindModules(result); + cb(err, __transaction); + }, + { + ed: modulesLoader.scope.ed, + account: result.account, + } + ); + }, + ], + accountModule: [ + 'accountLogic', + 'transactionLogic', + (result, cb) => { + modulesLoader.initModuleWithDb(AccountModule, cb, { + logic: { + account: result.accountLogic, + transaction: result.transactionLogic, + }, + }); + }, + ], + }, + (err, result) => { + expect(err).to.not.exist; + delegate = new Delegate(modulesLoader.scope.schema); + delegateBindings = { + accounts: result.accountModule, + }; + delegate.bind(delegateBindings.accounts); + + transaction = result.transactionLogic; + transaction.attachAssetType(transactionTypes.DELEGATE, delegate); + + accountsModule = result.accountModule; + + done(); + } + ); + }); + + describe('bind()', () => { + it('should be okay with correct params', () => { + expect(() => { + delegate.bind(delegateBindings.accounts); + }).to.not.throw(); + }); + + after(() => { + delegate.bind(delegateBindings.accounts); + }); + }); + + describe('create()', () => { + it('should throw with empty parameters', () => { + expect(() => { + delegate.create(); + }).to.throw(); + }); + + it('should be okay with valid parameters', () => { + expect(delegate.create(validTransactionData, validTransaction)).to.be.an( + 'object' + ); + }); + }); + + describe('calculateFee()', () => { + it('should return the correct fee', () => { + expect(delegate.calculateFee()).to.equal(constants.fees.delegate); + }); + }); + + describe('verify()', () => { + it('should return error if recipientId is set', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.recipientId = trs.senderId; + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Invalid recipient'); + done(); + }); + }); + + it('should return error if amount is not zero', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.amount = 1; + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Invalid transaction amount'); + done(); + }); + }); + + it('should return error if account is a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + const sender = _.cloneDeep(validSender); + sender.isDelegate = true; + delegate.verify(trs, sender, (err) => { + expect(err).to.equal('Account is already a delegate'); + done(); + }); + }); + + it('should return error if asset delegate is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + delete trs.asset.delegate; + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Invalid transaction asset'); + done(); + }); + }); + + it('should return error if username is undefined', (done) => { + const trs = _.cloneDeep(validTransaction); + delete trs.asset.delegate.username; + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Username is undefined'); + done(); + }); + }); + + it('should return error if username is not in lower case', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.delegate.username = trs.asset.delegate.username.toUpperCase(); + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Username must be lowercase'); + done(); + }); + }); + + it('should return error if username is empty', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.delegate.username = ' '; + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Empty username'); + done(); + }); + }); + + it('should return error if username is too long', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.delegate.username = 'a'.repeat(21); + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal('Username is too long. Maximum is 20 characters'); + done(); + }); + }); + + // it('should return error if username looks like an address', (done) => { + // const trs = _.cloneDeep(validTransaction); + // trs.asset.delegate.username = 'u123456'; + + // delegate.verify(trs, validSender, (err) => { + // expect(err).to.equal('Username can not be a potential address'); + // done(); + // }); + // }); + + it('should return error if username contains invalid characters', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.delegate.username = 'system#'; + + delegate.verify(trs, validSender, (err) => { + expect(err).to.equal( + 'Username can only contain alphanumeric characters with the exception of !@$&_.' + ); + done(); + }); + }); + + it('should verify okay for valid transaction', (done) => { + delegate.verify(validTransaction, validSender, done); + }); + }); + + describe('process()', () => { + it('should be okay', (done) => { + delegate.process(validTransaction, validSender, done); + }); + }); + + describe('getBytes()', () => { + it('should throw an error with no param', () => { + expect(delegate.getBytes).to.throw(); + }); + + it('should return same result when called multiple times', () => { + const firstCalculation = delegate.getBytes(validTransaction); + const secondCalculation = delegate.getBytes(validTransaction); + expect(firstCalculation.equals(secondCalculation)).to.be.true; + }); + + it('should return the valid buffer', () => { + expect(delegate.getBytes(validTransaction)).to.eql( + Buffer.from('73797374656d', 'hex') + ); + }); + }); + + describe('apply()', () => { + it('should add delegate flag and username', (done) => { + const { username } = validUnconfirmedTransaction.asset.delegate; + + delegate.apply.call( + transaction, + validUnconfirmedTransaction, + dummyBlock, + dummySender, + (err) => { + expect(err).to.not.exist; + + accountsModule.getAccount( + { + username, + }, + (err, accountAfter) => { + expect(err).to.not.exist; + expect(accountAfter).to.exist; + expect(accountAfter.isDelegate).to.equal(1); + done(); + } + ); + } + ); + }); + }); + + describe('undo()', () => { + function applyTransaction(trs, sender, done) { + delegate.apply.call(transaction, trs, dummyBlock, sender, done); + } + + it('should remove delegate flag and username', (done) => { + const { username } = validUnconfirmedTransaction.asset.delegate; + accountsModule.getAccount({ username }, (err, accountBefore) => { + expect(err).to.not.exist; + expect(accountBefore).to.exist; + expect(accountBefore.isDelegate).to.equal(1); + + delegate.undo.call( + transaction, + validUnconfirmedTransaction, + dummyBlock, + dummySender, + (err) => { + expect(err).to.not.exist; + + accountsModule.getAccount( + { address: validSender.address }, + (err, accountAfter) => { + expect(err).to.not.exist; + + expect(accountAfter).to.exist; + expect(accountAfter.username).to.equal(null); + expect(accountAfter.isDelegate).to.equal(0); + + applyTransaction( + validUnconfirmedTransaction, + dummySender, + done + ); + } + ); + } + ); + }); + }); + }); + + describe('objectNormalize()', () => { + it('should throw an error with no param', () => { + expect(delegate.objectNormalize).to.throw(); + }); + + it('should be ok with a valid transaction', () => { + expect(delegate.objectNormalize(validTransaction)).to.equal( + validTransaction + ); + }); + }); + + describe('dbRead()', () => { + it('should throw an error with no param', () => { + expect(delegate.dbRead).to.throw(); + }); + + it('should return null if d_username field is not present', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + delete rawTrs.d_username; + const trs = delegate.dbRead(rawTrs); + expect(trs).to.be.null; + }); + + it('should return delegate object with correct fields', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + const trs = delegate.dbRead(rawTrs); + const expectedKeys = ['username', 'publicKey', 'address']; + expect(trs.delegate).to.be.an('object'); + expect(trs.delegate).to.have.keys(expectedKeys); + }); + }); + + describe('dbSave()', () => { + it('should throw an error with no param', () => { + expect(delegate.dbSave).to.throw(); + }); + + it('should return promise object for valid parameters', () => { + const saveQuery = delegate.dbSave(validTransaction); + const keys = ['table', 'fields', 'values']; + const valuesKeys = ['username', 'transactionId']; + expect(saveQuery).to.be.an('object'); + expect(saveQuery).to.have.keys(keys); + expect(saveQuery.values).to.have.keys(valuesKeys); + }); + }); + + describe('ready()', () => { + it('should return true when sender does not have multisignatures', () => { + expect(delegate.ready(validTransaction, validSender)).to.be.true; + }); + }); +}); diff --git a/test/unit/logic/peer.js b/test/unit/logic/peer.js index 02d88693..e408d92f 100644 --- a/test/unit/logic/peer.js +++ b/test/unit/logic/peer.js @@ -1,34 +1,33 @@ 'use strict'; -var chai = require('chai'); -var expect = require('chai').expect; +const { expect } = require('chai'); -var express = require('express'); -var ip = require('neoip'); -var _ = require('lodash'); -var sinon = require('sinon'); -var randomPeer = require('../../common/objectStubs').randomPeer; -var Peer = require('../../../logic/peer.js'); +const ip = require('neoip'); +const _ = require('lodash'); -describe('peer', function () { - var peer; +const Peer = require('../../../logic/peer.js'); - beforeEach(function () { +const { validPeer } = require('../../common/stubs/peers.js'); + +describe('peer', () => { + let peer; + + beforeEach(() => { peer = new Peer({}); }); - describe('accept', function () { - it('should accept valid peer', function () { - var peer = new Peer({}); - var __peer = peer.accept(randomPeer); - ['height', 'ip', 'port', 'state'].forEach(function (property) { - expect(__peer[property]).equals(randomPeer[property]); + describe('accept()', () => { + it('should accept valid peer', () => { + const peer = new Peer({}); + const __peer = peer.accept(validPeer); + ['height', 'ip', 'port', 'state'].forEach((property) => { + expect(__peer[property]).equals(validPeer[property]); }); - expect(__peer.string).equals(randomPeer.ip + ':' + randomPeer.port); + expect(__peer.string).equals(`${validPeer.ip}:${validPeer.port}`); }); - it('should accept empty peer and set default values', function () { - var __peer = peer.accept({}); + it('should accept empty peer and set default values', () => { + const __peer = peer.accept({}); expect(__peer.port).to.equal(0); expect(__peer.ip).to.be.undefined; expect(__peer.state).to.equal(1); @@ -36,88 +35,88 @@ describe('peer', function () { expect(__peer.string).to.be.undefined; }); - it('should accept peer with ip as long', function () { - var __peer = peer.accept({ ip: ip.toLong(randomPeer.ip) }); - expect(__peer.ip).to.equal(randomPeer.ip); + it('should accept peer with ip as long', () => { + const __peer = peer.accept({ ip: ip.toLong(validPeer.ip) }); + expect(__peer.ip).to.equal(validPeer.ip); }); - it('should convert dappid to array', function () { - var __peer = peer.accept({ dappid: 'random-dapp-id' }); + it('should convert dappid to array', () => { + const __peer = peer.accept({ dappid: 'random-dapp-id' }); expect(__peer.dappid).to.be.an('array'); - expect(_.isEqual(__peer.dappid, ['random-dapp-id'])).to.be.ok; + expect(_.isEqual(__peer.dappid, ['random-dapp-id'])).to.be.true; delete __peer.dappid; }); }); - describe('parseInt', function () { - it('should always return a number', function () { + describe('parseInt()', () => { + it('should always return a number', () => { expect(peer.parseInt('1')).to.equal(1); expect(peer.parseInt(1)).to.equal(1); }); - it('should return default value when NaN passed', function () { + it('should return default value when NaN is provided', () => { expect(peer.parseInt('not a number', 1)).to.equal(1); expect(peer.parseInt(undefined, 1)).to.equal(1); expect(peer.parseInt(null, 1)).to.equal(1); }); }); - describe('applyHeaders', function () { - it('should not apply random values to the peer scope', function () { + describe('applyHeaders()', () => { + it('should not apply random values to the peer scope', () => { peer.applyHeaders({ headerA: 'HeaderA' }); - expect(peer.headerA).to.not.exist; + expect(peer.headerA).not.to.exist; }); - it('should apply defined values as headers', function () { - peer.headers.forEach(function (header) { + it('should apply defined values as headers', () => { + peer.headers.forEach((header) => { delete peer[header]; - if (randomPeer[header]) { - var headers = {}; - headers[header] = randomPeer[header]; + if (validPeer[header]) { + const headers = {}; + headers[header] = validPeer[header]; peer.applyHeaders(headers); - expect(peer[header]).to.equal(randomPeer[header]); + expect(peer[header]).to.equal(validPeer[header]); } }); }); - it('should not apply nulls or undefined values as headers', function () { - peer.headers.forEach(function (header) { + it('should not apply nulls or undefined values as headers', () => { + peer.headers.forEach((header) => { delete peer[header]; - if (randomPeer[header] === null || randomPeer[header] === undefined) { - var headers = {}; - headers[header] = randomPeer[header]; + if (validPeer[header] === null || validPeer[header] === undefined) { + const headers = {}; + headers[header] = validPeer[header]; peer.applyHeaders(headers); - expect(peer[header]).to.not.exist; + expect(peer[header]).not.to.exist; } }); }); - it('should parse height and port', function () { - var appliedHeaders = peer.applyHeaders({ port: '4000', height: '1' }); + it('should parse height and port', () => { + const appliedHeaders = peer.applyHeaders({ port: '4000', height: '1' }); expect(appliedHeaders.port).to.equal(4000); expect(appliedHeaders.height).to.equal(1); }); }); - describe('update', function () { - it('should not apply random values to the peer scope', function () { + describe('update()', () => { + it('should not pass the unexpected values to the peer scope', () => { peer.update({ someProp: 'someValue' }); - expect(peer.someProp).to.not.exist; + expect(peer.someProp).not.to.exist; }); - it('should not apply undefined to the peer scope', function () { + it('should not apply undefined to the peer scope', () => { peer.update({ someProp: undefined }); - expect(peer.someProp).to.not.exist; + expect(peer.someProp).not.to.exist; }); - it('should not apply null to the peer scope', function () { + it('should not apply null to the peer scope', () => { peer.update({ someProp: null }); - expect(peer.someProp).to.not.exist; + expect(peer.someProp).not.to.exist; }); - it('should change state of banned peer', function () { - var initialState = peer.state; + it('should change state of banned peer', () => { + const initialState = peer.state; // Ban peer peer.state = 0; // Try to unban peer @@ -126,56 +125,61 @@ describe('peer', function () { peer.state = initialState; }); - it('should update defined values', function () { - var updateData = { + it('should update defined values', () => { + const updateData = { os: 'test os', version: '0.0.0', dappid: ['test dappid'], broadhash: 'test broadhash', height: 3, - nonce: 'ABCD123' + nonce: 'ABCD123', }; - expect(_.isEqual(_.keys(updateData), peer.headers)).to.be.ok; + expect(_.isEqual(_.keys(updateData), peer.headers)).to.be.true; peer.update(updateData); - peer.headers.forEach(function (header) { - expect(peer[header]).to.exist.and.equals(updateData[header]); + peer.headers.forEach((header) => { + expect(peer[header]).to.exist.and.equal(updateData[header]); }); }); - it('should not update immutable properties', function () { - var peerBeforeUpdate = _.clone(peer); - var updateImmutableData = { - ip: randomPeer.ip, - port: randomPeer.port, - string: randomPeer.ip + ':' + randomPeer.port + it('should not update immutable properties', () => { + const peerBeforeUpdate = _.clone(peer); + const updateImmutableData = { + ip: validPeer.ip, + port: validPeer.port, + string: validPeer.ip + ':' + validPeer.port, }; - expect(_.isEqual(_.keys(updateImmutableData), peer.immutable)).to.be.ok; + expect(_.isEqual(_.keys(updateImmutableData), peer.immutable)).to.be.true; peer.update(updateImmutableData); - peer.headers.forEach(function (header) { - expect(peer[header]).equals(peerBeforeUpdate[header]).and.not.equal(updateImmutableData); + peer.headers.forEach((header) => { + expect(peer[header]) + .to.equal(peerBeforeUpdate[header]) + .and.not.equal(updateImmutableData); }); }); }); - describe('object', function () { - it('should create proper copy of peer', function () { - var __peer = new Peer(randomPeer); - var peerCopy = __peer.object(); - _.keys(randomPeer).forEach(function (property) { + describe('object()', () => { + it('should create proper copy of peer', () => { + const __peer = new Peer(validPeer); + const peerCopy = __peer.object(); + _.keys(validPeer).forEach((property) => { if (__peer.properties.indexOf(property) !== -1) { - expect(peerCopy[property]).to.equal(randomPeer[property]); - if (__peer.nullable.indexOf(property) !== -1 && !randomPeer[property]) { + expect(peerCopy[property]).to.equal(validPeer[property]); + if ( + __peer.nullable.indexOf(property) !== -1 && + !validPeer[property] + ) { expect(peerCopy[property]).to.be.null; } } }); }); - it('should always return state', function () { - var initialState = peer.state; + it('should always return state', () => { + const initialState = peer.state; peer.update({ state: 'unreadable' }); - var peerCopy = peer.object(); + const peerCopy = peer.object(); expect(peerCopy.state).to.equal(1); peer.state = initialState; }); diff --git a/test/unit/logic/peers.js b/test/unit/logic/peers.js index 6f10e015..d3e5a4a6 100644 --- a/test/unit/logic/peers.js +++ b/test/unit/logic/peers.js @@ -1,47 +1,54 @@ 'use strict'; -var chai = require('chai'); -var expect = require('chai').expect; - -var express = require('express'); -var _ = require('lodash'); -var sinon = require('sinon'); -var modulesLoader = require('../../common/initModule').modulesLoader; -var randomPeer = require('../../common/objectStubs').randomPeer; -var Peers = require('../../../logic/peers.js'); -var Peer = require('../../../logic/peer.js'); - -describe('peers', function () { - var peers; - - before(function (done) { - modulesLoader.initAllModules(function (err, __modules) { +const { expect } = require('chai'); + +const _ = require('lodash'); + +const Peers = require('../../../logic/peers.js'); +const Peer = require('../../../logic/peer.js'); + +const { modulesLoader } = require('../../common/initModule'); +const { validPeer } = require('../../common/stubs/peers.js'); + +describe('peers', () => { + let peers; + + before((done) => { + modulesLoader.initAllModules((err, __modules) => { if (err) { return done(err); } __modules.peers.onBind(__modules); - modulesLoader.initLogic(Peers, modulesLoader.scope, function (err, __peers) { - peers = __peers; - peers.bindModules({ peers: __modules.peers }); - done(); - }); + modulesLoader.initLogic( + Peers, + modulesLoader.scope, + function (err, __peers) { + if (err) { + return done(err); + } + + peers = __peers; + peers.bindModules({ peers: __modules.peers }); + done(); + } + ); }); }); - function removeAll () { - peers.list().forEach(function (peer) { - peers.remove(peer); - }); + function removeAll() { + peers.list().forEach((peer) => peers.remove(peer)); - expect(peers.list()).that.is.an('array').and.to.be.empty; + expect(peers.list()).to.be.an('array').and.empty; } - function arePeersEqual (peerA, peerB) { - var allPeersProperties = function (peer) { - return _.keys(peer).every(function (property) { - return Peer.prototype.properties.concat(['string']).indexOf(property) !== -1; + function arePeersEqual(peerA, peerB) { + const allPeersProperties = (peer) => { + return _.keys(peer).every((property) => { + return ( + Peer.prototype.properties.concat(['string']).indexOf(property) !== -1 + ); }); }; @@ -53,196 +60,202 @@ describe('peers', function () { throw new Error('Not a peer: ', peerB); } - var commonProperties = _.intersection(_.keys(peerA), _.keys(peerB)); + const commonProperties = _.intersection(_.keys(peerA), _.keys(peerB)); - if (commonProperties.indexOf('ip') === -1 || commonProperties.indexOf('port') === -1) { - throw new Error('Insufficient data to compare the peers (no port or ip provided)'); + if ( + commonProperties.indexOf('ip') === -1 || + commonProperties.indexOf('port') === -1 + ) { + throw new Error( + 'Insufficient data to compare the peers (no port or ip provided)' + ); } - return commonProperties.every(function (property) { + return commonProperties.every((property) => { return peerA[property] === peerB[property]; }); } - describe('create', function () { - it('should always return Peer instance', function () { + describe('create()', () => { + it('should always return Peer instance', () => { expect(peers.create()).to.be.an.instanceof(Peer); - expect(peers.create(randomPeer)).to.be.an.instanceof(Peer); - expect(peers.create(new Peer(randomPeer))).to.be.an.instanceof(Peer); + expect(peers.create(validPeer)).to.be.an.instanceof(Peer); + expect(peers.create(new Peer(validPeer))).to.be.an.instanceof(Peer); }); }); - describe('list', function () { - it('should list peers as Peer instances', function () { + describe('list()', () => { + it('should list peers as Peer instances', () => { removeAll(); - peers.upsert(randomPeer); - peers.list().forEach(function (peer) { + peers.upsert(validPeer); + peers.list().forEach((peer) => { expect(peer).to.be.an.instanceof(Peer); }); removeAll(); }); - it('should list peers as objects when normalized', function () { + it('should list peers as objects when normalized', () => { removeAll(); - peers.upsert(randomPeer); - peers.list(true).forEach(function (peer) { + peers.upsert(validPeer); + peers.list(true).forEach((peer) => { expect(peer).to.be.an('object'); }); removeAll(); }); }); - describe('upsert', function () { - it('should insert new peers', function () { + describe('upsert', () => { + it('should insert new peers', () => { removeAll(); - peers.upsert(randomPeer); + peers.upsert(validPeer); expect(peers.list().length).equal(1); removeAll(); }); - it('should not insert new peer with adm-js-api os', function () { + it('should not insert new peer with adm-js-api os', () => { removeAll(); - var modifiedPeer = _.clone(randomPeer); + const modifiedPeer = _.clone(validPeer); modifiedPeer.os = 'adm-js-api'; peers.upsert(modifiedPeer); expect(peers.list().length).equal(0); removeAll(); }); - it('should update height of existing peer', function () { + it('should update height of existing peer', () => { removeAll(); - peers.upsert(randomPeer); - var list = peers.list(); - var inserted = list[0]; + peers.upsert(validPeer); + let list = peers.list(); + const inserted = list[0]; expect(list.length).equal(1); - expect(arePeersEqual(inserted, randomPeer)).to.be.ok; + expect(arePeersEqual(inserted, validPeer)).to.be.true; - var modifiedPeer = _.clone(randomPeer); + const modifiedPeer = _.clone(validPeer); modifiedPeer.height += 1; peers.upsert(modifiedPeer); list = peers.list(); - var updated = list[0]; + const updated = list[0]; expect(list.length).equal(1); - expect(arePeersEqual(updated, modifiedPeer)).to.be.ok; - expect(arePeersEqual(updated, randomPeer)).to.be.not.ok; + expect(arePeersEqual(updated, modifiedPeer)).to.be.true; + expect(arePeersEqual(updated, validPeer)).to.be.false; removeAll(); }); - it('should not update height with insertOnly param', function () { + it('should not update height with insertOnly param', () => { removeAll(); - peers.upsert(randomPeer); - var list = peers.list(); - var inserted = list[0]; + peers.upsert(validPeer); + let list = peers.list(); + const inserted = list[0]; expect(list.length).equal(1); - expect(arePeersEqual(inserted, randomPeer)).to.be.ok; + expect(arePeersEqual(inserted, validPeer)).to.be.true; - var modifiedPeer = _.clone(randomPeer); + const modifiedPeer = _.clone(validPeer); modifiedPeer.height += 1; peers.upsert(modifiedPeer, true); list = peers.list(); - var updated = list[0]; + const updated = list[0]; expect(list.length).equal(1); - expect(arePeersEqual(updated, modifiedPeer)).to.be.not.ok; - expect(arePeersEqual(updated, randomPeer)).to.be.ok; + expect(arePeersEqual(updated, modifiedPeer)).to.be.false; + expect(arePeersEqual(updated, validPeer)).to.be.true; removeAll(); }); - it('should insert peer with different ports', function () { + it('should insert peer with different ports', () => { removeAll(); - peers.upsert(randomPeer); + peers.upsert(validPeer); expect(peers.list().length).equal(1); - var differentPortPeer = _.clone(randomPeer); + const differentPortPeer = _.clone(validPeer); differentPortPeer.port += 1; peers.upsert(differentPortPeer); - var list = peers.list(); + const list = peers.list(); expect(list.length).equal(2); - var demandedPorts = _.map([randomPeer, differentPortPeer], 'port'); - var listPorts = _.map(list, 'port'); + const demandedPorts = _.map([validPeer, differentPortPeer], 'port'); + const listPorts = _.map(list, 'port'); - expect(_.isEqual(demandedPorts.sort(), listPorts.sort())).to.be.ok; + expect(_.isEqual(demandedPorts.sort(), listPorts.sort())).to.be.true; removeAll(); }); - it('should insert peer with different IPs', function () { + it('should insert peer with different IPs', () => { removeAll(); - peers.upsert(randomPeer); + peers.upsert(validPeer); expect(peers.list().length).equal(1); - var differentIpPeer = _.clone(randomPeer); + const differentIpPeer = _.clone(validPeer); differentIpPeer.ip = '40.40.40.41'; - expect(differentIpPeer.ip).to.not.equal(randomPeer); + expect(differentIpPeer.ip).to.not.equal(validPeer); peers.upsert(differentIpPeer); - var list = peers.list(); + + const list = peers.list(); expect(list.length).equal(2); - var demandedIps = _.map([randomPeer, differentIpPeer], 'ip'); - var listIps = _.map(list, 'ip'); + const demandedIps = _.map([validPeer, differentIpPeer], 'ip'); + const listIps = _.map(list, 'ip'); - expect(_.isEqual(demandedIps.sort(), listIps.sort())).to.be.ok; + expect(_.isEqual(demandedIps.sort(), listIps.sort())).to.be.true; removeAll(); }); }); - describe('exists', function () { - it('should return true if peer is on the list', function () { + describe('exists()', () => { + it('should return true if peer is on the list', () => { removeAll(); - peers.upsert(randomPeer); - var list = peers.list(true); + peers.upsert(validPeer); + const list = peers.list(true); expect(list.length).equal(1); - expect(peers.exists(randomPeer)).to.be.ok; + expect(peers.exists(validPeer)).to.be.true; - var differentPortPeer = _.clone(randomPeer); + const differentPortPeer = _.clone(validPeer); differentPortPeer.port += 1; - expect(peers.exists(differentPortPeer)).to.be.not.ok; + expect(peers.exists(differentPortPeer)).to.be.false; }); }); - describe('get', function () { - it('should return inserted peer', function () { + describe('get', () => { + it('should return inserted peer', () => { removeAll(); - peers.upsert(randomPeer); - var insertedPeer = peers.get(randomPeer); - expect(arePeersEqual(insertedPeer, randomPeer)).to.be.ok; + peers.upsert(validPeer); + const insertedPeer = peers.get(validPeer); + expect(arePeersEqual(insertedPeer, validPeer)).to.be.true; }); - it('should return inserted peer by address', function () { + it('should return inserted peer by address', () => { removeAll(); - peers.upsert(randomPeer); - var insertedPeer = peers.get(randomPeer.ip + ':' + randomPeer.port); - expect(arePeersEqual(insertedPeer, randomPeer)).to.be.ok; + peers.upsert(validPeer); + const insertedPeer = peers.get(`${validPeer.ip}:${validPeer.port}`); + expect(arePeersEqual(insertedPeer, validPeer)).to.be.true; }); - it('should return undefined if peer is not inserted', function () { + it('should return undefined if peer is not inserted', () => { removeAll(); - expect(peers.get(randomPeer)).to.be.undefined; + expect(peers.get(validPeer)).to.be.undefined; }); }); - describe('remove', function () { - it('should remove added peer', function () { + describe('remove()', () => { + it('should remove added peer', () => { removeAll(); - peers.upsert(randomPeer); + peers.upsert(validPeer); expect(peers.list().length).equal(1); - var result = peers.remove(randomPeer); - expect(result).to.be.ok; + const result = peers.remove(validPeer); + expect(result).to.be.true; expect(peers.list().length).equal(0); }); - it('should return false when trying to remove non inserted peer', function () { + it('should return false when trying to remove non inserted peer', () => { removeAll(); - var result = peers.remove(randomPeer); - expect(result).to.be.not.ok; + const result = peers.remove(validPeer); + expect(result).to.be.false; expect(peers.list().length).equal(0); }); }); diff --git a/test/unit/logic/state.js b/test/unit/logic/state.js new file mode 100644 index 00000000..0eab77b6 --- /dev/null +++ b/test/unit/logic/state.js @@ -0,0 +1,319 @@ +'use strict'; + +const async = require('async'); + +const { expect } = require('chai'); +const _ = require('lodash'); + +const TransactionLogic = require('../../../logic/transaction.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const State = require('../../../logic/state.js'); + +const transactionTypes = require('../../../helpers/transactionTypes.js'); + +const { modulesLoader } = require('../../common/initModule.js'); +const { validSender } = require('../../common/stubs/transactions/common.js'); +const { + validTransaction, + validTransactionData, + rawValidTransaction, +} = require('../../common/stubs/transactions/state.js'); +const { dummyBlock } = require('../../common/stubs/blocks.js'); + +describe('State', () => { + /** + * @type {State} + */ + let state; + let transaction; + + before((done) => { + async.auto( + { + rounds(cb) { + modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + }, + accountLogic(cb) { + modulesLoader.initLogicWithDb(AccountLogic, cb, {}); + }, + transactionLogic: [ + 'rounds', + 'accountLogic', + (result, cb) => { + modulesLoader.initLogicWithDb( + TransactionLogic, + (err, __transaction) => { + __transaction.bindModules(result); + cb(err, __transaction); + }, + { + ed: modulesLoader.scope.ed, + account: result.account, + } + ); + }, + ], + stateLogic: [ + 'accountLogic', + 'transactionLogic', + (result, cb) => { + modulesLoader.initLogicWithDb(State, cb, { + account: result.accountLogic, + }); + }, + ], + }, + (err, result) => { + expect(err).to.not.exist; + state = result.stateLogic; + + transaction = result.transactionLogic; + transaction.attachAssetType(transactionTypes.STATE, state); + + done(); + } + ); + }); + + describe('bind()', () => { + it('should be okay', () => { + expect(() => state.bind()).to.not.throw(); + }); + + after(() => { + state.bind(); + }); + }); + + describe('create()', () => { + it('should throw with empty parameters', () => { + expect(() => { + state.create(); + }).to.throw(); + }); + + it('should attach asset to a transaction with valid parameters', () => { + const trs = state.create(validTransactionData, validTransaction); + const keys = ['amount', 'recipientId', 'asset']; + const assetKeys = ['value', 'key', 'type']; + expect(trs).to.be.an('object'); + expect(trs).to.include.keys(keys); + expect(trs.asset.state).to.have.keys(assetKeys); + }); + }); + + describe('calculateFee()', () => { + it('should set higher fees for very long values', () => { + const longValueTransaction = { + id: '13031380580772800310', + type: 9, + timestamp: 226647183, + amount: 0, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + senderId: 'U810656636599221322', + asset: { + state: { + key: 'eth:address', + value: + '3b993b1d6d0fc6d97cff9ac72abc65faa46f554acf799095b32a0cd3b7dca693634b89b9e4e3d600ef72ede2ca69ca7024631d55e74af938035b0c6a6db22e0be1dba549b8afe1e67db3440263c5ffba55115caf1d6a8e51bb80b61cee2fe4a31d8a9b22ce5030967aabd74c985e3c8eaae15db3700daad84eb8271d48cf62e04f33b65df6ad2f098631627c5ea5f43611e631fa1aef832b560d533a12b2ea26a59b020430f7b281f6a149a6d37fc6c838b0dd5ebcf60b95c770c6a89ac78a3a21528f2131360560d1edf43bb93b106978de5b691fdc2699dd40d129a2e124c101cafef2c05eef99422b55a158001cab4528117ffa16b740acf3169c73256bf8b55a6d1003f1e9a3368ded8bef1426385164e6af86d3d7fe73e0e63e62bda514eadfb4993ff406be26a69fd90102cd76e0d419a800144f7a88ff880eb09e56fc28cfa1234d19a1f7902cbdf82609ce5ddbdf2798a6f64b4af7cb8164f83992af2f599a9e63ec848a3027bfbe14b9c9ef37863a1b835b800679a358f6a6058051efc734bfe6470b103e72df1aa250be3cfa197236255f7f40379a4791d4b581fb5bb58fbbbcddf2634e652c2c72745e7d43bde3302214e1688a79b94bb068b9be9a12db27a4c529e66c86e1e574fd06a0484c8d798ac5d53617fb1a522a6d94602ed5a27e7eaf3070360ea20d84ac0089085f99672254a70a234dab9bffb10d6897080ed123dbf473f006d53d5e122fb47398a0a6fb322a1c63f271a01e0f7407901603e8a29d9ab91d3ac460065a80b4fda5ae4b335b819286d7dfadce9b2b3b7817874ddda62bf515445e02e57ee9dc7efa09f6df2b1c838beed73ddd6fd24cd5fd8e7a5e0d6be735ae57b8eba056981647b9c4213842903e3e3368d4b62ebe702886e5185c45d3440559939e90babad2d487a734602aed154083219c90e3ddf2abc7d7b3eb314b386ef593d2f7a8b87e23f836556b36350c4ef3e400e9433e1f6cf4af6ad8ae0823b525fdf999c6fb0875f4aec0f56cf37ccb83d229e39994df22ac7a27bf85d96a9684358f61c0278321c84c4cc6df3b58c20d4d858e323be57f02b32c847ad085985031b5c3872f8858655689881f7fc1984993d931c3e76139e50d6ae39129c957ec1f1c40730c0243d17753449051b18829226756e3c875fa9a09a4c238c3d5ba64c362dd3ef3e17f00e8cafc9e6bb723c73101868d9ae839bb4feec81b27b5b2974ce290d1609350bf7d8cb2dbb3d18f0cce99815b50deda814aec7727fe1097e12357d729cd62e31552a05e8223d3236ec345a0366832f196874ed04abe7d5c44d195f5c5759037e6a538d391c1b542d04a4382b13e2b5fcb740a3483ae57e250e377840f9bf0a103ecddd5c55afc3e4f8f182d3f4ec7bf28909a23c26eda3a2b8bc5e9bdb628f977380341f3a4d1468298b638720b6c6e03fa5f6c0d4863514e7a8af3dc8b03e31626c9d499dcd9879eb6f44c03346fb72255f20ab9d52dc9aa7975b014f0e66ef1747d275368fba85762fe09c53d0b2a5a8964bf008825635af5ee7d804a93e75f62a8f035b6c7d13957fcb9c6f78ed0e077386d23ce4280ed346423a495e0c801633af207451e210b10b9813773295abc77f6b24d3a6ec6907f83e5d3f0123c680338b07a071c7713849692eb2949307926b41968dad3a4a8606efd3dae645576b27c82c21bd865eaa7a17734f9e9b1b4f67c32bf035f25cf091f4fa55a46c6f54de8bef6abff0d666a51762ededfe89cdf86f4a32316e9494ba4526a86c75c39e9fe789825857a145a8d978928268eeaad401227eb0ddc48f70966b947f51ece662b8704747f05a9a36788e50a5603959ee19d09db3c3f0499201d2c7a9e2b14c7eb8cbff0e82a3729645e5330d63f72f1e928c29b8e150e18fe2936427245573b73ec5b25e33a04c88b5b7b143b5d87d97fbdc131d907046a20be820986b6b28cb2f99cb0c495dab6ce2bdeff9d86ee692de3dc41605b40a9c52f0ffef9e454ec4f89cbad3b9137ee3321b8ebd19747793cd304d093bab8818718627b000cae796017645bf9bfbfbf40684737edb621ecbd302b53d3c7e7407fed35c813e7d227c40b273532af65a5c16f723fecbc8967b62dbfb9987e1e08f1b45e80abfb1409c6cc60000a344a88b8076af309bfbd08a154aea8ce1c25d1e10c33d1c1e4cdf2a0748f682415d3fe2179e7a133e94c133244dc6b032e68164f57fc68ae7528aca37866063e1dd0c06d38e546a0f76ad7291faf8b78645d063ffb35525c0c28ab640acb19bd2fe9fbd8da2517511d413faf9d7e9e1f3d057d474c428ab58a9851653f00bc33a82e6beda6dc467a0024351dbb477f4ce12f171d4c975ec7e9149026e450aaeadab7f84d5032934d2fcba8e8e21867da9b4e47ef02c8b3c0580b53115230ba7e0854cdc566c71468a8e2668ac576afa6064a7471d9e0a23c5ffbf55cfdd51b79b2f5cfeacc9d95c20f1114726257bc90c7b14e1d67b4c6ff5b924b6f907b224e946a1cc640e93bd0fe5473b2af05454695a0896f6a4d971b5bfca064d42f81ee258004258fd1a8b93316fb8a1f94d83569d6f5125dc54ee3e97d997ae1c365acb40ba545edb5dff0dee9f0bb48724ed51a8ec2dbce2748de5a98a5e85fc876c33bd2d6aa2478224ec98cbeb20fd34e7c463361adeb9ea006d6386a2f53098652d5748a832234d5c82ea94dc7043dc788e01a8905c39c39b5e808ad7bd788696f67b0187e3793454670b5ec5c05b3017640d0c289d9ace3a5bc90cd63f694be34bc0964581bb2e0f4bd2996b05de1d83d31c51db2ce03a9b16c980bc2952d6430de277f1aa209c19589d2bf8a45f98f145314a5cb9058263afa544d60018f12fa5db7635faed7eca02148e7f89022d3b8daedd48b8078e529e3d6c4f53b3191345b79ef0492862f06cc6f9a36b87f4902706d8760dc7042afe7f0b1d78c48a06dd6192429071fae27b5a9db8199c18f0b59c35ef29a104e236b86acbeae4bacfc2fe8e8a575bd7b465d3f71f37c33d621dcf7acc3f84a84dc9be77dd60cc2b3e67e4fbaa76f320f2bee6272fa2af8b5748e4bf59951f5cba8a6d6fd6dc7ab5a903c2d6a73b28c14dc0073564905a9df195df0132181fc651bbdf1a6e27ebb22bcd60eb24b6985442c38192542dd6b6f4682ef611843ae02dcd39ae11e10c8d53d59c8efd52b406ae29f30eaa0031e2cf53f42ceb6342c85571f10dc7c15c6a9276eec8a724595d54ea9c675a898a2f2ba9562963ac465b3d14272cb162e1475b05f7c2e77350dcdfb4a289d7e65bc580af4a51ed0bb92ba5f7100ec0a66a178f50727f8cb1db553f3e9f17d631da606caed958f6465c1d0274a7d965efc409efdf1c637eea4075f02b0ee3cd67fb1897a6296f8adbb88b53ab9e4536973795e618cac66a8cff07f5ccaca9fe83cba990039c5dd3307cfae49fbb3c29d45b30996e0883c909c2ab75ab72aaebf19ec3b040a4a52ce88c62ab00d70a5fb0f569d5ddef3572d4d6a2f7104bcfc2d89b2330db7252ed9628463fbae76113754e17b46728afa77481feef0ed4e496a3136c7a1ff728c411012ed12521bca984052247535ab68340b08c659ae2c6c4247f56f3248bebff8557640ff6233ab94ed1d9ea6097b67ee62a0a3c7d528e27cf3e1e1180ce58364fa616108910fde43d866d4d479f81048396252c6c9725c8c26eaeb03e2b7cca824aa005dbd9970828f77922d0fb4fe905f8b68c6872db3d699a8dac13ad84bc3dd40538cbcfc069be6e79b318e353506be4bda8a2c802a232a1750547c1a7e61a1ad0a29c135de66c79472b87151610a82e3d7ff3ba2ce46a3bd009f35c902fc1bc68da772dc860b6ab1462b4774455eece1b80cfcccd0ca1c9e4bb9751fd601c5dabc76bb3ce43be3993678f9f365073a63054aa4127ee424a422079d1b172c610a172249ec62ea6f1b91fbba0c420fc62fa010a7008361dcd4ea167d5bca3b3c4577673a7fe8e80c5f19ee41353792aa0c0afda58c3518d20dbfe5ac81e8da00b287e5d11ffe9b9d5c8b37d387d156baee3a7b88d7865553ef744b5ea17640d373910aaa0014e079a366f253a354a6325092c4de9bf37c1465d33155ce391b24dbbe83ed8521fe942c2a3bdea28e10057079fff79e5523665cfc01675f268aab7730636384788d4b19a2420dc7e1f72ce6cf62f0710dd9081f457d64795e1556038f69dfe25fff8976dc092fa8b9ba1cce2960595f32f9a555dddf6f120c9bc89bc3e473346504f14ae3c4624d18ac3f33f09599c2170d86127456ab03faf55587a54671cd03a4b57e92be822c46348c14c068c07d7912e00668b73dddb44c1fd96b3993b6df13c6888fe1d7fde037785716fc6550cc81738a122f21c79ada4c5c2c999690c93c7b8fcc78f56364db136aa2e671994f29756c20b73c399914085e819332b4bc243960a98f04605451005b008d82a76eef5c5058764fa8af569ab720fca84174d0fad1acad498abb13a25b8394e71b2f499c926b9e60a0aa8c9815ae3cf1177d19c5e12b02cac7737247dacf44c69e796f6f552212def4baac7ab7566b981275ad05422dd97cf0997761d03b4f07b7d38fbaca81ce2a86d1c669013e1d8ce1d37fc69f8bdf7bbf3ea17cad300a40c10b1dcda025f006deb8e8b99d91eea6ea117b58c4e0fe858686379aeabf0c06736bba33cc4b52af573056be4c947756eb61255c2a8bf240e402f2bfd0b5243299b91a8a23f0f288e7d0d7764399dd2f17e55c4d513daa06115afa941327add61e4aa48f9d9bf8738f4c1dd197d92e35d3a9ec392525aac0bd49c614d5e376b7b9a0b1a39ed3e2ca88201379c18b9050f94ae7afc7083aec43248cbb9009f86826565ff530a575b6ba81a5d19251889c8d3b356d5fe57c3afe52cb6872eac5715bd52b5ff9659ae1f01bdd9919776ce38f40ee758af2cf3bde0009485f9ccf4667afc7e8f830e5969e8e1f0fcf6e01bec99e9309965ca11a70ed844adf427f8421d33adfa358417d8b7491e56e82d0607a48cb7738771c957cd4146076ee0ab1d3b919bf3b46fbdb2e9fea2db25c19198ee628fea550f8d6b9a57131464651470bc97384535973eb5926be344714f7f2d773dc66fc8f5d12f4a1fa1a95003380bac6f8cd52bdd0bf0217ea03478e94c22023856e6a4988ccf81c036229e69d882aaa900a19466a1234093c7a3315190847beb94f8ef525c50e6c830f9e22a9e1c431649050c5bad7e77e38c457d7dd780d6521218af80b1cf2df51e01e35b2c01db3c74b8ff9d0d6943f897f48824198d076ab44579aabc62ded89e8f81c194c0a371007e9540aa4a0ec930cbcdf4dd6e3c28306dca5a25a01d207823c46820c35420014c11b68e8ebac730b1daa98b884db141044e2dd03b0ed4c214bd821ee5410597014dd7083f2fe3831c5932f3514537e0b4d0853680d02f2190a5582a75bfb75173053c0ced7553d4d24363accb52651056b802f0df48d8264f0c0cb9cb7b0967730049f291033a93e3bd4fe632414d5989e5b0771653198ad2922e2f3ab441b9c14fcf4f3a7b828a16bcfc0d714cce533ccda1c27bc3e48ebdef2aacc121e5113ad28a141560b69b9bff890970065b11bea62e6e4b1b21477fdde6eaf94393e27932ac2fe6ce871cf42a6ed6f8b0ae1ff5a79e0ca49ae80d1b6c246bbfadc47119011658899744662a22d4ea71892747759d475ae4e6f7a045dc3fdcd6866aed762babc6ccf182c5df3038700cd755cb2178ca1a5b29d1258e61ea909056b78b645632a0ef15bdc0ea84a9668852f53f9472a5bb6505cc3bdba2993e394959c1d63c61ba0367d39fe3fce035bcc3c752d15048fafe51ea71075b6f0dc9e5e313306247e1e39164c42b1eaf56660909a34bbdbafb90c82529bc951ca31afe853d4074db7557d7ec15b3fd92141848b8b428ac805b75a0bf4bd9371bf78b97ea102348a2c39c8f7b756b16b5c68d5dcc530473145bb5ef7e0b7c868b2b7ab7e40c0d1a40a8c53a17eb0ba3e42ecc883c362e6beceb57529f676c7c19210e38dca4adaa74b0e53729f21b9d0a60d4ff124d2293db5f498efb1525e63696412e5c43cfbc9b310873ad0823ee374dce3d50db028ea73dd7619d6c1e7a92469cbd17661fadddfc93ae92e286459b8feec83405611c5998f62d7e82800ffcbbd4f35251c0d63fcb76e707af99f38812188c754342a8dfda20ca7177b9565de1d6127ac5ff69099f6160ef50ed31b8b452f8b523c6954993adfbf337e5108ba88f045d2f8ad79853e5ddfae57d2cc9ee51e1b87273948fd61b417d7e1e25aea262cb4604c6bf57a52193a24198ac1ccba957ba0d63b97306ff9d49abf485f0852ec1f9a68f4d88ba0969ab053dc331cfb0e4f3dd8e898a926f4d90639a9dcc673b4a95633d3c55b750f737464d70aefd75f5cf23a0c4d60f5d2612d9b8581b360ac59ae2b989aae5ab2e2619aa3b1d4a7f7893461d1ddf25e41fd5cc2f62d2f55193ac2db9d0a433eaf42d597fe2d2a4ce6553acc2c74e7e64b9c64de0289f6fc4c879f42db66c7e37fd52f790bfc1ed8fa813167cc311acef240c5e436a7c90d1e1ff073243d89c4e35329c8b8516508879ff77108c8ae1b9e307dfece5641824b454f2a2376cbad476c1b865f8cb196f8605bb8d679788a35b385eab82bd1d375afb8363c633ebe2985cc9b7e8af3068f6d5c684cd2538999352410410328c4936c8fbffc97da00078c35d7c5d60e9f94421709c4145b35d1e05ac10ff4834d49c8e624ee07482d9f97682c8ddcaf6ce6c3660f410015893e33566db47efc3c0e6c2d85dc0ca0a9f94908bb83bd0a96b5a5f97a6c9266879d86667b433de197558f54cafbc2a21b0014241693f7dcbb9c78f797b52d9996fdb714190429435d0e40b641e9ccfbeb6c6dfd8a424f337fa2d52de5ec333658327132c557fe1edff84be887c23f9ffa93b49854deede86a1cbc0426deb46f019889eea08b3df053a5cb89c831eb2aa77360abdd8af5000bbc0f656235751b3cd5a1ddbf12874a87a98fc2e45f0b', + type: 0, + }, + }, + recipientId: null, + signature: + '7d008594b1c9dacc2d856ae544b7f5c0a25e86daf7d6c5cea38e547b294c26fae9b9b7f2ecf57b676be81ed169e9b0a427ce00df770f9890f2a74da6e57dc706', + }; + + const shortValueTransaction = { + id: '10889400336719857616', + type: 9, + timestamp: 226647242, + amount: 0, + senderPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', + senderId: 'U810656636599221322', + asset: { + state: { key: 'eth:address', value: 'f4011a1360ac2769e06', type: 0 }, + }, + recipientId: null, + signature: + 'fae36a90c8de7e2fd9eee9b5c4a721c4253055f3e85874ac9e166484f8c50aca33f4a2d46c72f0293d0eea2ef44dbb4cdf723fcec6fd4bc4b421f08de00ac805', + }; + + const shortValueFee = state.calculateFee(shortValueTransaction); + const longValueFee = state.calculateFee(longValueTransaction); + + expect(shortValueFee).greaterThan(0); + expect(longValueFee).greaterThan(shortValueFee); + }); + }); + + describe('verify()', () => { + it('should return error if asset is not set', (done) => { + const trs = _.cloneDeep(validTransaction); + delete trs.asset.state; + state.verify(trs, validSender, (err) => { + expect(err).to.equal('Invalid transaction asset'); + done(); + }); + }); + + it('should return error if asset type is out of range', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.state.type = -1; + state.verify(trs, validSender, (err) => { + expect(err).to.equal('Invalid state type'); + done(); + }); + }); + + it('should return error if asset value is empty', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.state.value = ' '; + state.verify(trs, validSender, (err) => { + expect(err).to.equal('Value must not be blank'); + done(); + }); + }); + + it('should return error if asset value is too long', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.state.value = 'a'.repeat(20482); + state.verify(trs, validSender, (err) => { + expect(err).to.equal('Value is too long. Maximum is 20480 characters'); + done(); + }); + }); + + it('should be okay for a valid transaction', (done) => { + const trs = _.cloneDeep(validTransaction); + state.verify(trs, validSender, (err) => { + expect(err).to.be.null; + done(); + }); + }); + }); + + describe('process()', () => { + it('should be okay', (done) => { + state.process(validTransaction, validSender, done); + }); + }); + + describe('getBytes()', () => { + it('should throw an error with no param', () => { + expect(state.getBytes).to.throw(); + }); + + it('should return same result when called multiple times', () => { + const firstCalculation = state.getBytes(validTransaction); + const secondCalculation = state.getBytes(validTransaction); + expect(firstCalculation.equals(secondCalculation)).to.be.true; + }); + + it('should return the valid buffer', () => { + expect(state.getBytes(validTransaction)).to.eql( + Buffer.from( + '3078383436303961333866656462636430326236353732333333343065366138636230396462363161386574683a6164647265737300000000', + 'hex' + ) + ); + }); + }); + + describe('apply()', () => { + it('should be okay', (done) => { + state.apply(validTransaction, dummyBlock, validSender, done); + }); + }); + + describe('undo()', () => { + it('should be okay', (done) => { + state.undo(validTransaction, dummyBlock, validSender, done); + }); + }); + + describe('applyUnconfirmed()', () => { + it('should be okay', (done) => { + state.applyUnconfirmed(validTransaction, validSender, done); + }); + }); + + describe('undoUnconfirmed()', () => { + it('should be okay', (done) => { + state.undoUnconfirmed(validTransaction, validSender, done); + }); + }); + + describe('objectNormalize()', () => { + it('should throw an error with no param', () => { + expect(state.objectNormalize).to.throw(); + }); + + it('should delete properties with null or undefined values from the asset', () => { + const trs = _.cloneDeep(validTransaction); + + trs.asset.state.blockId = null; + trs.asset.state.timestamp = undefined; + + const normalized = state.objectNormalize(trs); + expect(normalized.asset.state).to.not.have.key('blockId'); + expect(normalized.asset.state).to.not.have.key('timestamp'); + }); + }); + + describe('dbRead()', () => { + it('should throw an error with no param', () => { + expect(state.dbRead).to.throw(); + }); + + it('should return null if st_stored_value field is not present', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + delete rawTrs.st_stored_value; + const trs = state.dbRead(rawTrs); + expect(trs).to.be.null; + }); + + it('should return chat object with correct fields', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + const trs = state.dbRead(rawTrs); + const expectedKeys = ['value', 'key', 'type']; + expect(trs.state).to.be.an('object'); + expect(trs.state).to.have.keys(expectedKeys); + }); + }); + + describe('dbSave()', () => { + it('should throw an error with no param', () => { + expect(state.dbSave).to.throw(); + }); + + it('should return promise object for valid parameters', () => { + const saveQuery = state.dbSave(validTransaction); + const keys = ['table', 'fields', 'values']; + const valuesKeys = [ + 'stored_key', + 'stored_value', + 'type', + 'transactionId', + ]; + expect(saveQuery).to.be.an('object'); + expect(saveQuery).to.have.keys(keys); + expect(saveQuery.values).to.have.keys(valuesKeys); + }); + }); + + describe('afterSave()', () => { + it('should be okay', (done) => { + state.afterSave(validTransaction, done); + }); + }); + + describe('ready()', () => { + it('should return true when sender does not have multisignatures', () => { + expect(state.ready(validTransaction, validSender)).to.be.true; + }); + }); +}); diff --git a/test/unit/logic/transaction.js b/test/unit/logic/transaction.js index 360c1512..2100b1a8 100644 --- a/test/unit/logic/transaction.js +++ b/test/unit/logic/transaction.js @@ -1,364 +1,325 @@ -'use strict';/* eslint*/ - -var node = require('./../../node.js'); -var ed = require('../../../helpers/ed'); -var bignum = require('../../../helpers/bignum.js'); -var crypto = require('crypto'); -var async = require('async'); - -// var chai = require('chai'); -var expect = require('chai').expect; -var _ = require('lodash'); -var transactionTypes = require('../../../helpers/transactionTypes'); -var slots = require('../../../helpers/slots'); - -var modulesLoader = require('../../common/initModule').modulesLoader; -var Transaction = require('../../../logic/transaction.js'); -var Rounds = require('../../../modules/rounds.js'); -var AccountLogic = require('../../../logic/account.js'); -var AccountModule = require('../../../modules/accounts.js'); - -var Vote = require('../../../logic/vote.js'); -var Transfer = require('../../../logic/transfer.js'); -var Delegate = require('../../../logic/delegate.js'); -var Signature = require('../../../logic/signature.js'); -var Multisignature = require('../../../logic/multisignature.js'); -var InTransfer = require('../../../logic/inTransfer.js'); -var OutTransfer = require('../../../logic/outTransfer.js'); -var Chat = require('../../../logic/chat.js'); -var State = require('../../../logic/state.js'); - -// valid keypair sample (market delegate's passphrase) -var validPassword = 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon'; -var validHash = ed.createPassPhraseHash(validPassword); -var validKeypair = ed.makeKeypair(validHash); - -// stub for a valid sender -let validSender = { - username: null, - isDelegate: 0, - secondSignature: 0, - secondPublicKey: null, - vote: 0, - multisignatures: null, - multimin: 0, - multilifetime: 0, - nameexist: 0, - producedblocks: 0, - missedblocks: 0, - fees: 0, - rewards: 0, - virgin: 0 +'use strict'; /* eslint*/ + +const async = require('async'); +const { expect } = require('chai'); +const _ = require('lodash'); + +const constants = require('../../../helpers/constants.js'); +const bignum = require('../../../helpers/bignum.js'); + +const transactionTypes = require('../../../helpers/transactionTypes'); +const slots = require('../../../helpers/slots'); + +const { modulesLoader } = require('../../common/initModule'); +const Transaction = require('../../../logic/transaction.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const AccountModule = require('../../../modules/accounts.js'); + +const Vote = require('../../../logic/vote.js'); +const Transfer = require('../../../logic/transfer.js'); +const Delegate = require('../../../logic/delegate.js'); +const Signature = require('../../../logic/signature.js'); +const Multisignature = require('../../../logic/multisignature.js'); +const InTransfer = require('../../../logic/inTransfer.js'); +const OutTransfer = require('../../../logic/outTransfer.js'); +const Chat = require('../../../logic/chat.js'); +const State = require('../../../logic/state.js'); + +const { dummyBlock } = require('../../common/stubs/blocks.js'); +const { senderDefault } = require('../../common/stubs/transactions/common.js'); +const { + validTransaction, + validUnconfirmedTransaction, + rawValidTransaction, + validTransactionData, +} = require('../../common/stubs/transactions/transfer.js'); +const { + testAccountKeypair, + delegateAccount, + genesisAccount, + delegateAccountKeypair, + genesisKeypair, +} = require('../../common/stubs/account.js'); + +const validKeypair = testAccountKeypair; + +const testSender = { + ...senderDefault, + ...delegateAccount, }; +const testSenderKeypair = delegateAccountKeypair; -// valid sender to test transactions (kind delegate) -var testSender = _.defaults({ - address: 'U12559234133690317086', - publicKey: 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', - secret: 'weather play vibrant large edge clean notable april fire smoke drift hidden', - u_balance: 10000000000000, - balance: 100000000000000 -}, validSender); -const testSenderHash = node.accounts.createPassPhraseHash(testSender.secret); -const testSenderKeypair = node.accounts.makeKeypair(testSenderHash); - -// genesis account -const genesis = _.defaults({ - address: 'U15365455923155964650', - publicKey: 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', - secret: 'neck want coast appear army smile palm major crumble upper void warm', - balance: 0 -}, validSender); -const genesisHash = ed.createPassPhraseHash(genesis.secret); -const genesisKeypair = ed.makeKeypair(genesisHash); - -// valid new tx sample from a test sender -var validUnconfirmedTrs = { - type: 0, - amount: 100, - senderId: testSender.address, - senderPublicKey: testSender.publicKey, - recipientId: 'U7771441689362721578', - fee: 50000000, - timestamp: 1000, - asset: {} +const genesis = { + ...senderDefault, + ...genesisAccount, }; -// valid new tx sample from a test sender, but with keypair -var validTransactionData = { - type: 0, - amount: 8067474861277, - keypair: testSenderKeypair, - sender: testSender, - senderId: testSender.address, - senderPublicKey: testSender.publicKey, - recipientId: 'U7771441689362721578', - fee: 50000000, - timestamp: 1000 -}; - -// valid tx sample, got from api endpoint (from genesis to devs) -var validTransaction = { - id: '17190511997607511181', - blockId: '6438017970172540087', - type: 0, - block_timestamp: null, - timestamp: 0, - senderPublicKey: 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', - senderId: 'U15365455923155964650', - recipientId: 'U9781760580710719871', - amount: 490000000000000, - fee: 0, - signature: '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', - signatures: [], - asset: {} -}; - -// valid raw tx sample (same) -var rawValidTransaction = { - t_id: '17190511997607511181', - b_height: 981, - t_blockId: '6438017970172540087', - t_type: 0, - t_timestamp: 33363661, - t_senderPublicKey: 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', - m_recipientPublicKey: null, - t_senderId: 'U810656636599221322', - t_recipientId: 'U7771441689362721578', - t_amount: 490000000000000, - t_fee: 0, - t_signature: '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', - confirmations: 8343 -}; - -// from genesis to devs -var genesisTrs = { - type: 0, - amount: 490000000000000, - fee: 0, - timestamp: 0, - recipientId: 'U9781760580710719871', - senderId: 'U15365455923155964650', - senderPublicKey: 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', - signature: '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', - blockId: '6438017970172540087', - id: '17190511997607511181' -}; - - -describe('transaction', function () { - var transaction; - var accountModule; - - var attachTransferAsset = function (transaction, accountLogic, rounds, done) { - modulesLoader.initModuleWithDb(AccountModule, function (err, __accountModule) { - var transfer = new Transfer(); - transfer.bind(__accountModule, rounds); - transaction.attachAssetType(transactionTypes.SEND, transfer); - accountModule = __accountModule; - done(); - }, { - logic: { - account: accountLogic, - transaction: transaction +describe('transaction', () => { + let transaction; + let accountModule; + + function attachTransferAsset(transaction, accountLogic, rounds, done) { + modulesLoader.initModuleWithDb( + AccountModule, + (err, __accountModule) => { + const transfer = new Transfer(); + transfer.bind(__accountModule, rounds); + transaction.attachAssetType(transactionTypes.SEND, transfer); + accountModule = __accountModule; + done(); + }, + { + logic: { + account: accountLogic, + transaction: transaction, + }, } - }); + ); }; - before(function (done) { - async.auto({ - rounds: function (cb) { - modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + before((done) => { + async.auto( + { + rounds(cb) { + modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + }, + accountLogic(cb) { + modulesLoader.initLogicWithDb(AccountLogic, cb); + }, + transaction: [ + 'accountLogic', + (result, cb) => { + modulesLoader.initLogicWithDb(Transaction, cb, { + ed: require('../../../helpers/ed'), + account: result.accountLogic, + }); + }, + ], }, - accountLogic: function (cb) { - modulesLoader.initLogicWithDb(AccountLogic, cb); - }, - transaction: ['accountLogic', function (result, cb) { - modulesLoader.initLogicWithDb(Transaction, cb, { - ed: require('../../../helpers/ed'), - account: result.accountLogic - }); - }] - }, function (err, result) { - transaction = result.transaction; - transaction.bindModules(result); - attachTransferAsset(transaction, result.accountLogic, result.rounds, done); - }); + (err, result) => { + transaction = result.transaction; + transaction.bindModules(result); + attachTransferAsset( + transaction, + result.accountLogic, + result.rounds, + done + ); + } + ); }); - describe('create', function () { - it('should throw an error with no param', function () { + describe('create()', () => { + it('should throw an error with no param', () => { expect(transaction.create).to.throw(); }); - it('should throw an error when sender is not set', function () { - var trsData = _.cloneDeep(validTransactionData); + it('should throw an error when sender is not set', () => { + const trsData = _.cloneDeep(validTransactionData); delete trsData.sender; - expect(function () { + expect(() => { transaction.create(transaction, trsData); }).to.throw(); }); - it('should throw an error when keypair is not set', function () { - var trsData = _.cloneDeep(validTransactionData); + it('should throw an error when keypair is not set', () => { + const trsData = _.cloneDeep(validTransactionData); delete trsData.keypair; - expect(function () { + expect(() => { transaction.create(transaction, trsData); }).to.throw(); }); - it('should return transaction fee based on trs type', function () { + it('should return transaction fee based on trs type', () => { expect(transaction.create(validTransactionData).fee).to.equal(50000000); }); }); - describe('attachAssetType', function () { - it('should attach all transaction types', function () { - var appliedLogic; - appliedLogic = transaction.attachAssetType(transactionTypes.VOTE, new Vote()); + describe('attachAssetType()', () => { + it('should attach all transaction types', () => { + let appliedLogic; + appliedLogic = transaction.attachAssetType( + transactionTypes.VOTE, + new Vote() + ); expect(appliedLogic).to.be.an.instanceof(Vote); - appliedLogic = transaction.attachAssetType(transactionTypes.SEND, new Transfer()); + appliedLogic = transaction.attachAssetType( + transactionTypes.SEND, + new Transfer() + ); expect(appliedLogic).to.be.an.instanceof(Transfer); - appliedLogic = transaction.attachAssetType(transactionTypes.DELEGATE, new Delegate()); + appliedLogic = transaction.attachAssetType( + transactionTypes.DELEGATE, + new Delegate() + ); expect(appliedLogic).to.be.an.instanceof(Delegate); - appliedLogic = transaction.attachAssetType(transactionTypes.SIGNATURE, new Signature()); + appliedLogic = transaction.attachAssetType( + transactionTypes.SIGNATURE, + new Signature() + ); expect(appliedLogic).to.be.an.instanceof(Signature); - appliedLogic = transaction.attachAssetType(transactionTypes.MULTI, new Multisignature()); + appliedLogic = transaction.attachAssetType( + transactionTypes.MULTI, + new Multisignature() + ); expect(appliedLogic).to.be.an.instanceof(Multisignature); - appliedLogic = transaction.attachAssetType(transactionTypes.IN_TRANSFER, new InTransfer()); + appliedLogic = transaction.attachAssetType( + transactionTypes.IN_TRANSFER, + new InTransfer() + ); expect(appliedLogic).to.be.an.instanceof(InTransfer); - appliedLogic = transaction.attachAssetType(transactionTypes.OUT_TRANSFER, new OutTransfer()); + appliedLogic = transaction.attachAssetType( + transactionTypes.OUT_TRANSFER, + new OutTransfer() + ); expect(appliedLogic).to.be.an.instanceof(OutTransfer); - appliedLogic = transaction.attachAssetType(transactionTypes.CHAT_MESSAGE, new Chat()); + appliedLogic = transaction.attachAssetType( + transactionTypes.CHAT_MESSAGE, + new Chat() + ); expect(appliedLogic).to.be.an.instanceof(Chat); - appliedLogic = transaction.attachAssetType(transactionTypes.STATE, new State()); + appliedLogic = transaction.attachAssetType( + transactionTypes.STATE, + new State() + ); expect(appliedLogic).to.be.an.instanceof(State); return transaction; }); - it('should throw an error on invalid asset', function () { - expect(function () { - var invalidAsset = {}; + it('should throw an error on invalid asset', () => { + expect(() => { + const invalidAsset = {}; transaction.attachAssetType(-1, invalidAsset); }).to.throw('Invalid instance interface'); }); - it('should throw an error with no param', function () { + it('should throw an error with no param', () => { expect(transaction.attachAssetType).to.throw(); }); }); - describe('sign', function () { - it('should throw an error with no param', function () { + describe('sign()', () => { + it('should throw an error with no param', () => { expect(transaction.sign).to.throw(); }); - it('should sign transaction', function () { - var notSignedTx = _.cloneDeep(validTransaction); + it('should sign transaction', () => { + const notSignedTx = _.cloneDeep(validTransaction); delete notSignedTx.signature; - expect(transaction.sign(genesisKeypair, notSignedTx)).to.be.a('string').which.is.equal(validTransaction.signature); + expect(transaction.sign(genesisKeypair, notSignedTx)) + .to.be.a('string') + .which.is.equal(validTransaction.signature); }); }); // Multisignatures tests are disabled currently /* - describe('multisign', function () { + describe('multisign', () => { - it('should throw an error with no param', function () { + it('should throw an error with no param', () => { expect(transaction.multisign).to.throw(); }); - it('should multisign the transaction', function () { + it('should multisign the transaction', () => { expect(transaction.multisign(testSenderKeypair, validTransaction)).to.equal(validTransaction.signature); }); }); */ - describe('getId', function () { - it('should throw an error with no param', function () { + describe('getId()', () => { + it('should throw an error with no param', () => { expect(transaction.getId).to.throw(); }); - it('should generate the id of the trs', function () { - expect(transaction.getId(genesisTrs)).to.be.a('string').which.is.equal(genesisTrs.id); + it('should generate the id of the trs', () => { + expect(transaction.getId(validTransaction)) + .to.be.a('string') + .which.is.equal(validTransaction.id); }); - it('should update id if a field in trs value changes', function () { - var id = validTransaction.id; - var trs = _.cloneDeep(validTransaction); + it('should update id if a field in trs value changes', () => { + const id = validTransaction.id; + const trs = _.cloneDeep(validTransaction); trs.amount = 4000; expect(transaction.getId(trs)).to.not.equal(id); }); }); - describe('getHash', function () { - it('should throw an error with no param', function () { + describe('getHash()', () => { + it('should throw an error with no param', () => { expect(transaction.getHash).to.throw(); }); - it('should return hash for trs', function () { - var trs = validTransaction; - var expectedHash = '8d847c2495f790ee1f203c572f998b02376c37be57a8853bbbdcbc882d07b639'; - expect(transaction.getHash(trs).toString('hex')).to.be.a('string').which.is.equal(expectedHash); + it('should return hash for trs', () => { + const trs = _.cloneDeep(validTransaction); + const expectedHash = + '8d847c2495f790ee1f203c572f998b02376c37be57a8853bbbdcbc882d07b639'; + expect(transaction.getHash(trs).toString('hex')) + .to.be.a('string') + .which.is.equal(expectedHash); }); - it('should update hash if a field is trs value changes', function () { - var originalTrsHash = '8d847c2495f790ee1f203c572f998b02376c37be57a8853bbbdcbc882d07b639'; - var trs = _.cloneDeep(validTransaction); + it('should update hash if a field is trs value changes', () => { + const originalTrsHash = + '8d847c2495f790ee1f203c572f998b02376c37be57a8853bbbdcbc882d07b639'; + const trs = _.cloneDeep(validTransaction); trs.amount = 4000; - expect(transaction.getHash(trs).toString('hex')).to.not.equal(originalTrsHash); + expect(transaction.getHash(trs).toString('hex')).to.not.equal( + originalTrsHash + ); }); }); - describe('getBytes', function () { - it('should throw an error with no param', function () { + describe('getBytes()', () => { + it('should throw an error with no param', () => { expect(transaction.getBytes).to.throw(); }); - it('should return same result when called multiple times', function () { - var firstCalculation = transaction.getBytes(validTransaction); - var secondCalculation = transaction.getBytes(validTransaction); - expect(firstCalculation.equals(secondCalculation)).to.be.ok; + it('should return same result when called multiple times', () => { + const firstCalculation = transaction.getBytes(validTransaction); + const secondCalculation = transaction.getBytes(validTransaction); + expect(firstCalculation.equals(secondCalculation)).to.be.true; }); - it('should skip signature, second signature for getting bytes', function () { - var trsBytes = transaction.getBytes(validTransaction, true); + it('should skip signature, second signature for getting bytes', () => { + const trsBytes = transaction.getBytes(validTransaction, true); expect(trsBytes.length).to.equal(53); }); }); - describe('transaction.ready', function () { - it('should throw an error with no param', function () { + describe('ready()', () => { + it('should throw an error with no param', () => { expect(transaction.ready).to.throw(); }); - it('should throw error when trs type is invalid', function () { - var trs = _.cloneDeep(validTransaction); - var invalidTrsType = -1; + it('should throw error when trs type is invalid', () => { + const trs = _.cloneDeep(validTransaction); + const invalidTrsType = -1; trs.type = invalidTrsType; - expect(function () { - transaction.ready(trs, validSender); + expect(() => { + transaction.ready(trs, senderDefault); }).to.throw('Unknown transaction type ' + invalidTrsType); }); - it('should return false when sender not provided', function () { - var trs = validTransaction; - expect(transaction.ready(trs)).to.equal(false); + it('should return false when sender not provided', () => { + const trs = _.cloneDeep(validTransaction); + expect(transaction.ready(trs)).to.be.false; }); - it('should return true for valid trs and sender', function () { - var trs = validTransaction; - expect(transaction.ready(trs, validSender)).to.equal(true); + it('should return true for valid trs and sender', () => { + const trs = _.cloneDeep(validTransaction); + expect(transaction.ready(trs, senderDefault)).to.be.true; }); }); - describe('countById', function () { - it('should throw an error with no param', function () { + describe('countById()', () => { + it('should throw an error with no param', () => { expect(transaction.countById).to.throw(); }); - it('should return count of trs in db with trs id', function (done) { + it('should return count of trs in db with trs id', (done) => { transaction.countById(validTransaction, function (err, count) { expect(err).to.not.exist; expect(count).to.be.equal(1); @@ -366,8 +327,8 @@ describe('transaction', function () { }); }); - it('should return 1 for transaction from genesis block', function (done) { - transaction.countById(genesisTrs, function (err, count) { + it('should return 1 for transaction from genesis block', (done) => { + transaction.countById(validTransaction, function (err, count) { expect(err).to.not.exist; expect(count).to.be.equal(1); done(); @@ -375,98 +336,113 @@ describe('transaction', function () { }); }); - describe('checkConfirmed', function () { - it('should throw an error with no param', function () { + describe('checkConfirmed()', () => { + it('should throw an error with no param', () => { expect(transaction.checkConfirmed).to.throw(); }); - it('should not return error when trs is not confirmed', function (done) { - var trs = transaction.create(validTransactionData); - transaction.checkConfirmed(trs, function (err) { + it('should not return error when trs is not confirmed', (done) => { + const trs = transaction.create(validTransactionData); + transaction.checkConfirmed(trs, (err) => { expect(err).to.not.exist; done(); }); }); - it('should return error for transaction which is already confirmed', function (done) { - var dummyConfirmedTrs = { - id: '17190511997607511181' + it('should return error for transaction which is already confirmed', (done) => { + const dummyConfirmedTrs = { + id: '17190511997607511181', }; - transaction.checkConfirmed(dummyConfirmedTrs, function (err) { + transaction.checkConfirmed(dummyConfirmedTrs, (err) => { expect(err || []).to.include('Transaction is already confirmed'); done(); }); }); }); - describe('checkBalance', function () { - it('should throw an error with no param', function () { + describe('checkBalance()', () => { + it('should throw an error with no param', () => { expect(transaction.checkBalance).to.throw(); }); - it('should return error when sender has insufficient balance', function () { - var amount = '49000000000000000000000'; - var balanceKey = 'balance'; + it('should return error when sender has insufficient balance', () => { + const amount = '49000000000000000000000'; + const balanceKey = 'balance'; let sender = _.cloneDeep(testSender); sender.balance = 0; - var res = transaction.checkBalance(amount, balanceKey, validUnconfirmedTrs, sender); - expect(res.exceeded).to.equal(true); + const res = transaction.checkBalance( + amount, + balanceKey, + validUnconfirmedTransaction, + sender + ); + expect(res.exceeded).to.be.true; expect(res.error).to.include('Account does not have enough ADM:'); }); - it('should be okay if insufficient balance from genesis account', function () { - var amount = '999823366072900'; - var balanceKey = 'balance'; + it('should be okay if insufficient balance from genesis account', () => { + const amount = '999823366072900'; + const balanceKey = 'balance'; let sender = _.cloneDeep(genesis); sender.balance = 0; - var res = transaction.checkBalance(amount, balanceKey, genesisTrs, sender); - expect(res.exceeded).to.equal(false); + const res = transaction.checkBalance( + amount, + balanceKey, + validTransaction, + sender + ); + expect(res.exceeded).to.be.false; expect(res.error).to.not.exist; }); - it('should be okay if sender has sufficient balance', function () { - var balanceKey = 'balance'; - let sender = _.cloneDeep(validSender); + it('should be okay if sender has sufficient balance', () => { + const balanceKey = 'balance'; + let sender = _.cloneDeep(senderDefault); sender.balance = 100000001; - var res = transaction.checkBalance(validTransaction.amount, balanceKey, validTransaction, sender); - expect(res.exceeded).to.equal(false); + const res = transaction.checkBalance( + validTransaction.amount, + balanceKey, + validTransaction, + sender + ); + expect(res.exceeded).to.be.false; expect(res.error).to.not.exist; }); }); - describe('transaction.process', function () { - it('should throw an error with no param', function () { + describe('process()', () => { + it('should throw an error with no param', () => { expect(transaction.process).to.throw(); }); - it('should return error sender is not supplied', function (done) { + it('should return error sender is not supplied', (done) => { transaction.process(validTransaction, null, function (err, res) { expect(err).to.be.equal('Missing sender'); done(); }); }); - it('should return error if generated id is different from id supplied of trs', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error if generated id is different from id supplied of trs', (done) => { + const trs = _.cloneDeep(validTransaction); trs.id = 'invalid trs id'; - transaction.process(trs, validSender, function (err, res) { + transaction.process(trs, senderDefault, function (err, res) { expect(err).to.equal('Invalid transaction id'); done(); }); }); - it('should return error when failed to generate id', function (done) { - var trs = { - type: 0 + it('should return error when failed to generate id', (done) => { + const trs = { + type: 0, }; - transaction.process(trs, validSender, function (err, res) { + transaction.process(trs, senderDefault, function (err, res) { expect(err).to.equal('Failed to get transaction id'); done(); }); }); - it('should process the transaction', function (done) { - transaction.process(genesisTrs, genesis, function (err, res) { + it('should process the transaction', (done) => { + transaction.process(validTransaction, genesis, function (err, res) { expect(err).to.not.be.ok; expect(res).to.be.an('object'); expect(res.senderId).to.be.a('string').which.is.equal(genesis.address); @@ -475,10 +451,10 @@ describe('transaction', function () { }); }); - describe('transaction.verify', function () { - function createAndProcess (trsData, sender, cb) { - var trs = transaction.create(trsData); - transaction.process(trs, sender, function (err, __trs) { + describe('verify()', () => { + function createAndProcess(trsData, sender, cb) { + const trs = transaction.create(trsData); + transaction.process(trs, sender, (err, __trs) => { expect(err).to.not.exist; expect(__trs).to.be.an('object'); cb(__trs); @@ -486,18 +462,18 @@ describe('transaction', function () { }); } - it('should return error when sender is missing', function (done) { - transaction.verify(validTransaction, null, {}, function (err) { + it('should return error when sender is missing', (done) => { + transaction.verify(validTransaction, null, {}, (err) => { expect(err).to.equal('Missing sender'); done(); }); }); - it('should return error with invalid trs type', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error with invalid trs type', (done) => { + const trs = _.cloneDeep(validTransaction); trs.type = -1; - transaction.verify(trs, validSender, {}, function (err) { + transaction.verify(trs, senderDefault, {}, (err) => { expect(err).to.include('Unknown transaction type'); done(); }); @@ -505,70 +481,84 @@ describe('transaction', function () { // Second signature tests are disabled currently - // it('should return error when missing sender second signature', function (done) { - // var trs = _.cloneDeep(validUnconfirmedTrs); + // it('should return error when missing sender second signature', (done) => { + // const trs = _.cloneDeep(validUnconfirmedTransaction); // trs.signSignature = [transaction.sign(testSenderKeypair, trs)]; - // var vs = _.cloneDeep(testSender); + // const vs = _.cloneDeep(testSender); // vs.secondSignature = '839eba0f811554b9f935e39a68b3078f90bea22c5424d3ad16630f027a48362f78349ddc3948360045d6460404f5bc8e25b662d4fd09e60c89453776962df40d'; - // transaction.verify(trs, vs, {}, function (err) { + // transaction.verify(trs, vs, {}, (err) => { // expect(err).to.include('Missing sender second signature'); // done(); // }); // }); - it('should return error when sender does not have a second signature', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error when sender does not have a second signature', (done) => { + const trs = _.cloneDeep(validTransaction); trs.signSignature = [transaction.sign(validKeypair, trs)]; - transaction.verify(trs, validSender, {}, function (err) { + transaction.verify(trs, senderDefault, {}, (err) => { expect(err).to.include('Sender does not have a second signature'); done(); }); }); - it('should return error when requester does not have a second signature', function (done) { - var trs = _.cloneDeep(validTransaction); - var dummyRequester = { - secondSignature: 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f' + it('should return error when requester does not have a second signature', (done) => { + const trs = _.cloneDeep(validTransaction); + const dummyRequester = { + secondSignature: + 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', }; - trs.requesterPublicKey = '839eba0f811554b9f935e39a68b3078f90bea22c5424d3ad16630f027a48362f78349ddc3948360045d6460404f5bc8e25b662d4fd09e60c89453776962df40d'; + trs.requesterPublicKey = + '839eba0f811554b9f935e39a68b3078f90bea22c5424d3ad16630f027a48362f78349ddc3948360045d6460404f5bc8e25b662d4fd09e60c89453776962df40d'; - transaction.verify(trs, validSender, dummyRequester, function (err) { + transaction.verify(trs, senderDefault, dummyRequester, (err) => { expect(err).to.include('Missing requester second signature'); done(); }); }); - it('should return error when trs sender publicKey and sender public key are different', function (done) { - var trs = _.cloneDeep(validTransaction); - var invalidPublicKey = '01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746'; + it('should return error when trs sender publicKey and sender public key are different', (done) => { + const trs = _.cloneDeep(validTransaction); + const invalidPublicKey = + '01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746'; trs.senderPublicKey = invalidPublicKey; - transaction.verify(trs, genesis, {}, function (err) { - expect(err).to.include(['Invalid sender public key:', invalidPublicKey, 'expected:', validSender.publicKey].join(' ')); + transaction.verify(trs, genesis, {}, (err) => { + expect(err).to.include( + [ + 'Invalid sender public key:', + invalidPublicKey, + 'expected:', + senderDefault.publicKey, + ].join(' ') + ); done(); }); }); - it('should be impossible to send the money from genesis account', function (done) { - var trs = transaction.create(validTransactionData); + it('should be impossible to send the money from genesis account', (done) => { + const trs = transaction.create(validTransactionData); trs.senderId = 'U15365455923155964650'; - trs.senderPublicKey = 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae'; - var vs = _.cloneDeep(validSender); - vs.publicKey = 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae'; + trs.senderPublicKey = + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae'; + const vs = _.cloneDeep(senderDefault); + vs.publicKey = + 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae'; vs.address = 'U15365455923155964650'; - transaction.verify(trs, vs, {}, function (err) { - expect(err).to.include('Invalid sender. Can not send from genesis account'); + transaction.verify(trs, vs, {}, (err) => { + expect(err).to.include( + 'Invalid sender. Can not send from genesis account' + ); done(); }); }); - it('should return error on different sender address in trs and sender', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error on different sender address in trs and sender', (done) => { + const trs = _.cloneDeep(validTransaction); trs.senderId = 'U2581762640681118072'; - transaction.verify(trs, genesis, {}, function (err) { + transaction.verify(trs, genesis, {}, (err) => { expect(err).to.include('Invalid sender address'); done(); }); @@ -577,26 +567,26 @@ describe('transaction', function () { // Multisignatures tests are disabled currently /* - it('should return error when Account does not belong to multisignature group', function (done) { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should return error when Account does not belong to multisignature group', (done) => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(senderDefault); // Different publicKey for multisignature account vs.multisignatures = [node.eAccount.publicKey]; trs.requesterPublicKey = validKeypair.publicKey.toString('hex'); delete trs.signature; trs.signature = transaction.sign(validKeypair, trs); - transaction.verify(trs, vs, {}, function (err) { + transaction.verify(trs, vs, {}, (err) => { expect(err).to.equal('Account does not belong to multisignature group'); done(); }); }); */ - it('should return error when signature is not correct', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error when signature is not correct', (done) => { + const trs = _.cloneDeep(validTransaction); // testSenderKeypair is for a different account trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, genesis, {}, function (err) { + transaction.verify(trs, genesis, {}, (err) => { expect(err).to.include('Failed to verify signature'); done(); }); @@ -605,74 +595,75 @@ describe('transaction', function () { // Multisignatures tests are disabled currently /* - it('should return error when duplicate signature in transaction', function (done) { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should return error when duplicate signature in transaction', (done) => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(senderDefault); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; delete trs.signature; - trs.signatures = Array.apply(null, Array(2)).map(function () { return transaction.sign(validKeypair, trs); }); + trs.signatures = Array.apply(null, Array(2)).map(() => { return transaction.sign(validKeypair, trs); }); trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, vs, {}, function (err) { + transaction.verify(trs, vs, {}, (err) => { expect(err).to.equal('Encountered duplicate signature in transaction'); done(); }); }); - it('should return error when failed to verify multisignature', function (done) { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should return error when failed to verify multisignature', (done) => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(senderDefault); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; trs.requesterPublicKey = validKeypair.publicKey.toString('hex'); delete trs.signature; // using validKeypair as opposed to testSenderKeypair trs.signatures = [transaction.sign(validKeypair, trs)]; trs.signature = transaction.sign(validKeypair, trs); - transaction.verify(trs, vs, {}, function (err) { + transaction.verify(trs, vs, {}, (err) => { expect(err).to.equal('Failed to verify multisignature'); done(); }); }); - it('should be okay with valid multisignature', function (done) { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should be okay with valid multisignature', (done) => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(senderDefault); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; delete trs.signature; trs.signature = transaction.sign(testSenderKeypair, trs); trs.signatures = [transaction.multisign(validKeypair, trs)]; - transaction.verify(trs, vs, {}, function (err) { + transaction.verify(trs, vs, {}, (err) => { expect(err).to.not.exist; done(); }); }); */ - it('should return error when second signature is invalid', function (done) { - var vs = _.cloneDeep(validSender); + it('should return error when second signature is invalid', (done) => { + const vs = _.cloneDeep(senderDefault); vs.secondPublicKey = validKeypair.publicKey.toString('hex'); vs.secondSignature = 1; - var trsData = _.cloneDeep(validTransactionData); - createAndProcess(trsData, validSender, function (trs) { - trs.signSignature = '7af5f0ee2c4d4c83d6980a46efe31befca41f7aa8cda5f7b4c2850e4942d923af058561a6a3312005ddee566244346bdbccf004bc8e2c84e653f9825c20be008'; - transaction.verify(trs, vs, function (err) { + const trsData = _.cloneDeep(validTransactionData); + createAndProcess(trsData, senderDefault, function (trs) { + trs.signSignature = + '7af5f0ee2c4d4c83d6980a46efe31befca41f7aa8cda5f7b4c2850e4942d923af058561a6a3312005ddee566244346bdbccf004bc8e2c84e653f9825c20be008'; + transaction.verify(trs, vs, (err) => { expect(err).to.equal('Failed to verify second signature'); done(); }); }); }); - it('should be okay for valid second signature', function (done) { - var sender = _.cloneDeep(testSender); + it('should be okay for valid second signature', (done) => { + const sender = _.cloneDeep(testSender); sender.secondPublicKey = validKeypair.publicKey.toString('hex'); sender.secondSignature = 1; - var trsData = _.cloneDeep(validTransactionData); + const trsData = _.cloneDeep(validTransactionData); trsData.sender = sender; trsData.secondKeypair = validKeypair; createAndProcess(trsData, testSender, function (trs) { - transaction.verify(trs, testSender, {}, function (err) { - transaction.verify(trs, sender, function (err) { + transaction.verify(trs, testSender, {}, (err) => { + transaction.verify(trs, sender, (err) => { expect(err).to.not.exist; done(); }); @@ -680,343 +671,418 @@ describe('transaction', function () { }); }); - it('should throw return error transaction fee is incorrect', function (done) { - var trs = _.cloneDeep(genesisTrs); + it('should throw return error transaction fee is incorrect', (done) => { + const trs = _.cloneDeep(validTransaction); trs.fee = -100; - transaction.verify(trs, genesis, {}, function (err) { + transaction.verify(trs, genesis, {}, (err) => { expect(err).to.include('Invalid transaction fee'); done(); }); }); - it('should verify transaction with correct fee (without data field)', function (done) { - let trs = _.cloneDeep(validUnconfirmedTrs); + it('should verify transaction with correct fee (without data field)', (done) => { + let trs = _.cloneDeep(validUnconfirmedTransaction); trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, testSender, {}, function (err) { + transaction.verify(trs, testSender, {}, (err) => { expect(err).to.not.exist; done(); }); }); - it('should return error when transaction amount is invalid', function (done) { - var trsData = _.cloneDeep(validUnconfirmedTrs); - trsData.amount = node.constants.totalAmount + 10; + it('should return error when transaction amount is invalid', (done) => { + const trsData = _.cloneDeep(validUnconfirmedTransaction); + trsData.amount = constants.totalAmount + 10; trsData.signature = transaction.sign(testSenderKeypair, trsData); - transaction.verify(trsData, testSender, {}, function (err) { + transaction.verify(trsData, testSender, {}, (err) => { expect(err).to.include('Invalid transaction amount'); done(); }); }); - it('should return error when account balance is less than transaction amount', function (done) { - var trsData = _.cloneDeep(validUnconfirmedTrs); - trsData.amount = node.constants.totalAmount; + it('should return error when account balance is less than transaction amount', (done) => { + const trsData = _.cloneDeep(validUnconfirmedTransaction); + trsData.amount = constants.totalAmount; trsData.signature = transaction.sign(testSenderKeypair, trsData); - transaction.verify(trsData, testSender, {}, function (err) { + transaction.verify(trsData, testSender, {}, (err) => { expect(err).to.include('Account does not have enough ADM:'); done(); }); }); - it('should return error on timestamp smaller than the int32 range', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); + it('should return error on timestamp smaller than the int32 range', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); trs.timestamp = -2147483648 - 1; delete trs.signature; trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, testSender, {}, function (err) { + transaction.verify(trs, testSender, {}, (err) => { expect(err).to.include('Invalid transaction timestamp'); done(); }); }); - it('should return error on timestamp bigger than the int32 range', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); + it('should return error on timestamp bigger than the int32 range', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); trs.timestamp = 2147483647 + 1; delete trs.signature; trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, testSender, {}, function (err) { + transaction.verify(trs, testSender, {}, (err) => { expect(err).to.include('Invalid transaction timestamp'); done(); }); }); - it('should return error on future timestamp', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); + it('should return error on future timestamp', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); trs.timestamp = slots.getTime() + 100; delete trs.signature; trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, testSender, {}, function (err) { + transaction.verify(trs, testSender, {}, (err) => { expect(err).to.include('Invalid transaction timestamp'); done(); }); }); - it('should verify proper transaction with proper sender', function (done) { - let trs = _.cloneDeep(validUnconfirmedTrs); + it('should verify proper transaction with proper sender', (done) => { + let trs = _.cloneDeep(validUnconfirmedTransaction); trs.signature = transaction.sign(testSenderKeypair, trs); - transaction.verify(trs, testSender, {}, function (err) { + transaction.verify(trs, testSender, {}, (err) => { expect(err).to.not.be.ok; done(); }); }); - it('should throw an error with no param', function () { + it('should throw an error with no param', () => { expect(transaction.verify).to.throw(); }); }); - describe('verifySignature', function () { - it('should throw an error with no param', function () { + describe('verifySignature()', () => { + it('should throw an error with no param', () => { expect(transaction.verifySignature).to.throw(); }); - it('should return false if trs is changed', function () { - var trs = _.cloneDeep(validTransactionData); + it('should return false if trs is changed', () => { + const trs = _.cloneDeep(validTransactionData); trs.amount = 1001; - expect(transaction.verifySignature(trs, testSender.publicKey, trs.signature)).to.equal(false); + expect( + transaction.verifySignature(trs, testSender.publicKey, trs.signature) + ).to.be.false; }); - it('should return false if signature not provided', function () { - var trs = validTransaction; - expect(transaction.verifySignature(trs, validSender.publicKey, null)).to.equal(false); + it('should return false if signature not provided', () => { + const trs = _.cloneDeep(validTransaction); + expect( + transaction.verifySignature(trs, senderDefault.publicKey, null) + ).to.be.false; }); - it('should return valid signature for correct trs', function () { - var trs = genesisTrs; - expect(transaction.verifySignature(trs, genesis.publicKey, trs.signature)).to.equal(true); + it('should return valid signature for correct trs', () => { + const trs = _.cloneDeep(validTransaction); + expect( + transaction.verifySignature(trs, genesis.publicKey, trs.signature) + ).to.be.true; }); - it('should throw if public key is invalid', function () { - var trs = validTransaction; - var invalidPublicKey = '123123123'; - expect(function () { + it('should throw if public key is invalid', () => { + const trs = _.cloneDeep(validTransaction); + const invalidPublicKey = '123123123'; + expect(() => { transaction.verifySignature(trs, invalidPublicKey, trs.signature); }).to.throw(); }); }); - describe('verifySecondSignature', function () { - it('should throw an error with no param', function () { + describe('verifySecondSignature()', () => { + it('should throw an error with no param', () => { expect(transaction.verifySecondSignature).to.throw(); }); - it('should verify the second signature correctly', function () { - var signature = transaction.sign(validKeypair, validTransaction); - expect(transaction.verifySecondSignature(validTransaction, validKeypair.publicKey.toString('hex'), signature)).to.equal(true); + it('should verify the second signature correctly', () => { + const signature = transaction.sign(validKeypair, validTransaction); + expect( + transaction.verifySecondSignature( + validTransaction, + validKeypair.publicKey.toString('hex'), + signature + ) + ).to.be.true; }); }); - describe('verifyBytes', function () { - it('should throw an error with no param', function () { + describe('verifyBytes()', () => { + it('should throw an error with no param', () => { expect(transaction.verifyBytes).to.throw(); }); - it('should return when sender public is different', function () { - var trsBytes = transaction.getBytes(validTransaction); - var invalidPublicKey = 'addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9'; - expect(transaction.verifyBytes(trsBytes, invalidPublicKey, validTransaction.signature)).to.equal(false); - }); - - it('should throw when public key is not in the right format', function () { - var trsBytes = transaction.getBytes(validTransaction); - var invalidPublicKey = 'iddb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9'; - expect(function () { - transaction.verifyBytes(trsBytes, invalidPublicKey, validTransaction.signature); + it('should return when sender public is different', () => { + const trsBytes = transaction.getBytes(validTransaction); + const invalidPublicKey = + 'addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9'; + expect( + transaction.verifyBytes( + trsBytes, + invalidPublicKey, + validTransaction.signature + ) + ).to.be.false; + }); + + it('should throw when public key is not in the right format', () => { + const trsBytes = transaction.getBytes(validTransaction); + const invalidPublicKey = + 'iddb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9'; + expect(() => { + transaction.verifyBytes( + trsBytes, + invalidPublicKey, + validTransaction.signature + ); }).to.throw(); }); - it('should be okay for valid bytes', function () { - var trsBytes = transaction.getBytes(genesisTrs, true, true); - var res = transaction.verifyBytes(trsBytes, genesisTrs.senderPublicKey, genesisTrs.signature); - expect(res).to.equal(true); + it('should be okay for valid bytes', () => { + const trsBytes = transaction.getBytes(validTransaction, true, true); + const res = transaction.verifyBytes( + trsBytes, + validTransaction.senderPublicKey, + validTransaction.signature + ); + expect(res).to.be.true; }); }); - describe('transaction.apply', function () { - var dummyBlock = { - id: '9314232245035524467', - height: 1 - }; - - function undoTransaction (trs, sender, done) { + describe('apply()', () => { + function undoTransaction(trs, sender, done) { transaction.undo(trs, dummyBlock, sender, done); } - it('should throw an error with no param', function () { - expect(function () { transaction.apply(); }).to.throw(); + it('should throw an error with no param', () => { + expect(() => { + transaction.apply(); + }).to.throw(); }); - it('should be okay with valid params', function (done) { - var trs = validTransaction; + it('should be okay with valid params', (done) => { + const trs = _.cloneDeep(validTransaction); transaction.apply(trs, dummyBlock, genesis, done); }); - it('should return error on if balance is low', function (done) { - var trs = _.cloneDeep(validTransactionData); + it('should return error on if balance is low', (done) => { + const trs = _.cloneDeep(validTransactionData); trs.amount = '9850458911801908'; let sender = _.cloneDeep(testSender); sender.balance = 0; - transaction.apply(trs, dummyBlock, sender, function (err) { + transaction.apply(trs, dummyBlock, sender, (err) => { expect(err).to.include('Account does not have enough '); done(); }); }); - it('should subtract balance from sender account on valid transaction', function (done) { - accountModule.getAccount({ publicKey: validUnconfirmedTrs.senderPublicKey }, function (err, accountBefore) { - var amount = new bignum(validUnconfirmedTrs.amount.toString()).plus(validUnconfirmedTrs.fee.toString()); - var balanceBefore = new bignum(accountBefore.balance.toString()); - - transaction.apply(validUnconfirmedTrs, dummyBlock, testSender, function (err) { - accountModule.getAccount({ publicKey: validUnconfirmedTrs.senderPublicKey }, function (err, accountAfter) { - expect(err).to.not.exist; - var balanceAfter = new bignum(accountAfter.balance.toString()); - expect(balanceAfter.plus(amount).toString()).to.equal(balanceBefore.toString()); - undoTransaction(validUnconfirmedTrs, testSender, done); - }); - }); - }); + it('should subtract balance from sender account on valid transaction', (done) => { + accountModule.getAccount( + { publicKey: validUnconfirmedTransaction.senderPublicKey }, + function (err, accountBefore) { + const amount = new bignum( + validUnconfirmedTransaction.amount.toString() + ).plus(validUnconfirmedTransaction.fee.toString()); + const balanceBefore = new bignum(accountBefore.balance.toString()); + + transaction.apply( + validUnconfirmedTransaction, + dummyBlock, + testSender, + (err) => { + accountModule.getAccount( + { publicKey: validUnconfirmedTransaction.senderPublicKey }, + function (err, accountAfter) { + expect(err).to.not.exist; + const balanceAfter = new bignum( + accountAfter.balance.toString() + ); + expect(balanceAfter.plus(amount).toString()).to.equal( + balanceBefore.toString() + ); + undoTransaction( + validUnconfirmedTransaction, + testSender, + done + ); + } + ); + } + ); + } + ); }); }); - describe('undo', function () { - var dummyBlock = { - id: '9314232245035524467', - height: 1 - }; - - function applyTransaction (trs, sender, done) { + describe('undo()', () => { + function applyTransaction(trs, sender, done) { transaction.apply(trs, dummyBlock, sender, done); } - it('should throw an error with no param', function () { + it('should throw an error with no param', () => { expect(transaction.undo).to.throw(); }); - it('should not update sender balance when transaction is invalid', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); - var amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); + it('should not update sender balance when transaction is invalid', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); + const amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); delete trs.recipientId; - accountModule.getAccount({ publicKey: trs.senderPublicKey }, function (err, accountBefore) { - var balanceBefore = new bignum(accountBefore.balance.toString()); - - transaction.undo(trs, dummyBlock, testSender, function (err) { - accountModule.getAccount({ publicKey: trs.senderPublicKey }, function (err, accountAfter) { - var balanceAfter = new bignum(accountAfter.balance.toString()); - - expect(balanceBefore.plus(amount.multipliedBy(2)).toString()).to.not.equal(balanceAfter.toString()); - expect(balanceBefore.toString()).to.equal(balanceAfter.toString()); - done(); + accountModule.getAccount( + { publicKey: trs.senderPublicKey }, + function (err, accountBefore) { + const balanceBefore = new bignum(accountBefore.balance.toString()); + + transaction.undo(trs, dummyBlock, testSender, (err) => { + accountModule.getAccount( + { publicKey: trs.senderPublicKey }, + function (err, accountAfter) { + const balanceAfter = new bignum(accountAfter.balance.toString()); + + expect( + balanceBefore.plus(amount.multipliedBy(2)).toString() + ).to.not.equal(balanceAfter.toString()); + expect(balanceBefore.toString()).to.equal( + balanceAfter.toString() + ); + done(); + } + ); }); - }); - }); - }); - - it('should be okay with valid params', function (done) { - var trs = validUnconfirmedTrs; - var amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); - - accountModule.getAccount({ publicKey: trs.senderPublicKey }, function (err, accountBefore) { - var balanceBefore = new bignum(accountBefore.balance.toString()); - - transaction.undo(trs, dummyBlock, testSender, function (err) { - accountModule.getAccount({ publicKey: trs.senderPublicKey }, function (err, accountAfter) { - expect(err).to.not.exist; - - var balanceAfter = new bignum(accountAfter.balance.toString()); - expect(balanceBefore.plus(amount).toString()).to.equal(balanceAfter.toString()); - applyTransaction(trs, testSender, done); + } + ); + }); + + it('should be okay with valid params', (done) => { + const trs = validUnconfirmedTransaction; + const amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); + + accountModule.getAccount( + { publicKey: trs.senderPublicKey }, + function (err, accountBefore) { + const balanceBefore = new bignum(accountBefore.balance.toString()); + + transaction.undo(trs, dummyBlock, testSender, (err) => { + accountModule.getAccount( + { publicKey: trs.senderPublicKey }, + function (err, accountAfter) { + expect(err).to.not.exist; + + const balanceAfter = new bignum(accountAfter.balance.toString()); + expect(balanceBefore.plus(amount).toString()).to.equal( + balanceAfter.toString() + ); + applyTransaction(trs, testSender, done); + } + ); }); - }); - }); + } + ); }); }); - describe('applyUnconfirmed', function () { - function undoUnconfirmedTransaction (trs, sender, done) { + describe('applyUnconfirmed()', () => { + function undoUnconfirmedTransaction(trs, sender, done) { transaction.undoUnconfirmed(trs, sender, done); } - it('should throw an error with no param', function () { - expect(function () { transaction.applyUnconfirmed(); }).to.throw(); + it('should throw an error with no param', () => { + expect(() => { + transaction.applyUnconfirmed(); + }).to.throw(); }); - it('should be okay with valid params', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); + it('should be okay with valid params', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); transaction.applyUnconfirmed(trs, testSender, done); }); - it('should return error on if balance is low', function (done) { - var trs = _.cloneDeep(validUnconfirmedTrs); + it('should return error on if balance is low', (done) => { + const trs = _.cloneDeep(validUnconfirmedTransaction); trs.amount = '985045891180190800000000000000'; - transaction.applyUnconfirmed(trs, testSender, function (err) { + transaction.applyUnconfirmed(trs, testSender, (err) => { expect(err).to.include('Account does not have enough ADM'); done(); }); }); - it('should okay for valid params', function (done) { - transaction.applyUnconfirmed(validUnconfirmedTrs, testSender, function (err) { - expect(err).to.not.exist; - undoUnconfirmedTransaction(validUnconfirmedTrs, testSender, done); - }); + it('should okay for valid params', (done) => { + transaction.applyUnconfirmed( + validUnconfirmedTransaction, + testSender, + (err) => { + expect(err).to.not.exist; + undoUnconfirmedTransaction( + validUnconfirmedTransaction, + testSender, + done + ); + } + ); }); }); - describe('undoUnconfirmed', function () { - function applyUnconfirmedTransaction (trs, sender, done) { + describe('undoUnconfirmed()', () => { + function applyUnconfirmedTransaction(trs, sender, done) { transaction.applyUnconfirmed(trs, sender, done); } - it('should throw an error with no param', function () { + it('should throw an error with no param', () => { expect(transaction.undoUnconfirmed).to.throw(); }); - it('should be okay with valid params', function (done) { - transaction.undoUnconfirmed(validUnconfirmedTrs, testSender, function (err) { - expect(err).to.not.exist; - applyUnconfirmedTransaction(validUnconfirmedTrs, testSender, done); - }); + it('should be okay with valid params', (done) => { + transaction.undoUnconfirmed( + validUnconfirmedTransaction, + testSender, + (err) => { + expect(err).to.not.exist; + applyUnconfirmedTransaction( + validUnconfirmedTransaction, + testSender, + done + ); + } + ); }); }); - describe('dbSave', function () { - it('should throw an error with no param', function () { + describe('dbSave()', () => { + it('should throw an error with no param', () => { expect(transaction.dbSave).to.throw(); }); - it('should throw an error when type is not specified', function () { - var trs = _.cloneDeep(validTransaction); + it('should throw an error when type is not specified', () => { + const trs = _.cloneDeep(validTransaction); delete trs.type; - expect(function () { + expect(() => { transaction.dbSave(trs); }).to.throw(); }); - it('should create comma separated trs signatures', function () { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should create comma separated trs signatures', () => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(senderDefault); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; delete trs.signature; trs.signature = transaction.sign(testSenderKeypair, trs); trs.signatures = [transaction.multisign(validKeypair, trs)]; - var savePromise = transaction.dbSave(trs); - expect(savePromise).to.be.an('Array'); - expect(savePromise).to.have.length(1); - var trsValues = savePromise[0].values; - expect(trsValues).to.have.property('signatures').which.is.equal(trs.signatures.join(',')); - }); - - it('should return promise object for valid parameters', function () { - var savePromise = transaction.dbSave(validTransaction); - var keys = [ - 'table', - 'fields', - 'values' - ]; - var valuesKeys = [ + const saveQuery = transaction.dbSave(trs); + expect(saveQuery).to.be.an('array'); + expect(saveQuery).to.have.length(1); + const trsValues = saveQuery[0].values; + expect(trsValues) + .to.have.property('signatures') + .which.is.equal(trs.signatures.join(',')); + }); + + it('should return promise object for valid parameters', () => { + const saveQuery = transaction.dbSave(validTransaction); + const keys = ['table', 'fields', 'values']; + const valuesKeys = [ 'id', 'blockId', 'type', @@ -1029,65 +1095,67 @@ describe('transaction', function () { 'fee', 'signature', 'signSignature', - 'signatures' + 'signatures', ]; - expect(savePromise).to.be.an('Array'); - expect(savePromise).to.have.length(1); - expect(savePromise[0]).to.have.keys(keys); - expect(savePromise[0].values).to.have.keys(valuesKeys); + expect(saveQuery).to.be.an('array'); + expect(saveQuery).to.have.length(1); + expect(saveQuery[0]).to.have.keys(keys); + expect(saveQuery[0].values).to.have.keys(valuesKeys); }); }); - describe('afterSave', function () { - it('should throw an error with no param', function () { + describe('afterSave()', () => { + it('should throw an error with no param', () => { expect(transaction.afterSave).to.throw(); }); - it('should invoke the passed callback', function (done) { + it('should invoke the passed callback', (done) => { transaction.afterSave(validTransaction, done); }); }); - describe('objectNormalize', function () { - it('should throw an error with no param', function () { + describe('objectNormalize()', () => { + it('should throw an error with no param', () => { expect(transaction.objectNormalize).to.throw(); }); - it('should remove keys with null or undefined attribute', function () { - var trs = _.cloneDeep(validTransaction); + it('should remove keys with null or undefined attribute', () => { + const trs = _.cloneDeep(validTransaction); trs.amount = null; expect(_.keys(transaction.objectNormalize(trs))).to.not.include('amount'); }); - it('should not remove any keys with valid entries', function () { - expect(_.keys(transaction.objectNormalize(validTransaction))).to.have.length(11); + it('should not remove any keys with valid entries', () => { + expect( + _.keys(transaction.objectNormalize(validTransaction)) + ).to.have.length(11); }); - it('should throw error for invalid schema types', function () { - var trs = _.cloneDeep(validTransaction); + it('should throw error for invalid schema types', () => { + const trs = _.cloneDeep(validTransaction); trs.amount = 'Invalid value'; - expect(function () { + expect(() => { transaction.objectNormalize(trs); }).to.throw(); }); }); - describe('dbRead', function () { - it('should throw an error with no param', function () { + describe('dbRead()', () => { + it('should throw an error with no param', () => { expect(transaction.dbRead).to.throw(); }); - it('should return null if id field is not present', function () { - var rawTrs = _.cloneDeep(rawValidTransaction); + it('should return null if id field is not present', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); delete rawTrs.t_id; - var trs = transaction.dbRead(rawTrs); - expect(trs).to.be.a('null'); + const trs = transaction.dbRead(rawTrs); + expect(trs).to.be.null; }); - it('should return transaction object with correct fields', function () { - var rawTrs = _.cloneDeep(rawValidTransaction); - var trs = transaction.dbRead(rawTrs); - var expectedKeys = [ + it('should return transaction object with correct fields', () => { + const rawTrs = _.cloneDeep(rawValidTransaction); + const trs = transaction.dbRead(rawTrs); + const expectedKeys = [ 'id', 'height', 'blockId', @@ -1105,10 +1173,10 @@ describe('transaction', function () { 'signSignature', 'signatures', 'confirmations', - 'asset' + 'asset', ]; expect(trs).to.be.an('object'); - expect((trs)).to.have.keys(expectedKeys); + expect(trs).to.have.keys(expectedKeys); }); }); }); diff --git a/test/unit/logic/transfer.js b/test/unit/logic/transfer.js index ffc8f762..6e83de4a 100644 --- a/test/unit/logic/transfer.js +++ b/test/unit/logic/transfer.js @@ -1,126 +1,52 @@ 'use strict';/* eslint*/ -var node = require('./../../node.js'); -var ed = require('../../../helpers/ed'); -var bignum = require('../../../helpers/bignum.js'); -var crypto = require('crypto'); -var async = require('async'); - -var chai = require('chai'); -var expect = require('chai').expect; -var _ = require('lodash'); -var transactionTypes = require('../../../helpers/transactionTypes'); - -var modulesLoader = require('../../common/initModule').modulesLoader; -var TransactionLogic = require('../../../logic/transaction.js'); -var Transfer = require('../../../logic/transfer.js'); -var Rounds = require('../../../modules/rounds.js'); -var AccountLogic = require('../../../logic/account.js'); -var AccountModule = require('../../../modules/accounts.js'); -var DelegateModule = require('../../../modules/delegates.js'); - -// valid keypair sample (market delegate's passphrase) -var validPassword = 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon'; -var validHash = ed.createPassPhraseHash(validPassword); -var validKeypair = ed.makeKeypair(validHash); - -// stub for a valid sender -let validSender = { - username: null, - isDelegate: 0, - secondSignature: 0, - secondPublicKey: null, - vote: 0, - multisignatures: null, - multimin: 0, - multilifetime: 0, - nameexist: 0, - producedblocks: 0, - missedblocks: 0, - fees: 0, - rewards: 0, - virgin: 0 +const constants = require('../../../helpers/constants.js'); +const bignum = require('../../../helpers/bignum.js'); +const async = require('async'); + +const expect = require('chai').expect; +const _ = require('lodash'); +const transactionTypes = require('../../../helpers/transactionTypes'); + +const modulesLoader = require('../../common/initModule').modulesLoader; +const TransactionLogic = require('../../../logic/transaction.js'); +const Transfer = require('../../../logic/transfer.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const AccountModule = require('../../../modules/accounts.js'); + +const { dummyBlock } = require('../../common/stubs/blocks.js'); +const { senderDefault } = require('../../common/stubs/transactions/common.js'); +const { + validTransaction, + validUnconfirmedTransaction, + validTransactionData, +} = require('../../common/stubs/transactions/transfer.js'); +const { + delegateAccount, +} = require('../../common/stubs/account.js'); + +const validSender = { + ...senderDefault, + ...delegateAccount, }; -// valid sender to test transactions (kind delegate) -validSender = _.defaults({ - address: 'U12559234133690317086', - publicKey: 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', - secret: 'weather play vibrant large edge clean notable april fire smoke drift hidden', - u_balance: 10000000000000, - balance: 100000000000000 -}, validSender); - -// valid sender to test transactions (kind delegate) -var testSender = _.defaults({ - address: 'U12559234133690317086', - publicKey: 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', - secret: 'weather play vibrant large edge clean notable april fire smoke drift hidden', - u_balance: 10000000000000, - balance: 100000000000000 -}, validSender); -const testSenderHash = node.accounts.createPassPhraseHash(testSender.secret); -const testSenderKeypair = node.accounts.makeKeypair(testSenderHash); - -// valid new tx sample from a test sender -var validUnconfirmedTrs = { - type: 0, - amount: 100, - senderId: testSender.address, - senderPublicKey: testSender.publicKey, - recipientId: 'U7771441689362721578', - fee: 50000000, - timestamp: 1000, - asset: {} -}; - -// valid new tx sample from a test sender, but with keypair -var validTransactionData = { - type: 0, - amount: 8067474861277, - keypair: testSenderKeypair, - sender: testSender, - senderId: testSender.address, - senderPublicKey: testSender.publicKey, - recipientId: 'U7771441689362721578', - fee: 50000000, - timestamp: 1000 -}; - -// valid tx sample, got from api endpoint (from genesis to devs) -var validTransaction = { - id: '17190511997607511181', - blockId: '6438017970172540087', - type: 0, - block_timestamp: null, - timestamp: 0, - senderPublicKey: 'b80bb6459608dcdeb9a98d1f2b0111b2bf11e53ef2933e6769bb0198e3a97aae', - senderId: 'U15365455923155964650', - recipientId: 'U9781760580710719871', - amount: 490000000000000, - fee: 0, - signature: '85dc703a2b82698193ecbd86fd7aff1b057dfeb86e2a390ef42c1998bf1e9269c0048f42285e208a1e14a63843defbabece1bc96730f317f0cc16e23bb1b4d01', - signatures: [], - asset: {} -}; +describe('transfer', () => { + let transfer; + let transaction; + let transferBindings; + let accountModule; - -describe('transfer', function () { - var transfer; - var transaction; - var transferBindings; - var accountModule; - - before(function (done) { + before((done) => { async.auto({ - rounds: function (cb) { + rounds(cb) { modulesLoader.initModule(Rounds, modulesLoader.scope, cb); }, - accountLogic: function (cb) { + accountLogic(cb) { modulesLoader.initLogicWithDb(AccountLogic, cb, {}); }, - transactionLogic: ['rounds', 'accountLogic', function (result, cb) { - modulesLoader.initLogicWithDb(TransactionLogic, function (err, __transaction) { + transactionLogic: ['rounds', 'accountLogic', (result, cb) => { + modulesLoader.initLogicWithDb(TransactionLogic, (err, __transaction) => { __transaction.bindModules(result.rounds); cb(err, __transaction); }, { @@ -128,7 +54,7 @@ describe('transfer', function () { account: result.account }); }], - accountModule: ['accountLogic', 'transactionLogic', function (result, cb) { + accountModule: ['accountLogic', 'transactionLogic', (result, cb) => { modulesLoader.initModuleWithDb(AccountModule, cb, { logic: { account: result.accountLogic, @@ -136,7 +62,7 @@ describe('transfer', function () { } }); }] - }, function (err, result) { + }, (err, result) => { expect(err).to.not.exist; transfer = new Transfer(); transferBindings = { @@ -152,213 +78,203 @@ describe('transfer', function () { }); }); - describe('bind', function () { - it('should be okay with correct params', function () { - expect(function () { + describe('bind()', () => { + it('should be okay with correct params', () => { + expect(() => { transfer.bind(transferBindings.account, transferBindings.rounds); }).to.not.throw(); }); - after(function () { + after(() => { transfer.bind(transferBindings.account, transferBindings.rounds); }); }); - describe('create', function () { - it('should throw with empty parameters', function () { - expect(function () { + describe('create()', () => { + it('should throw with empty parameters', () => { + expect(() => { transfer.create(); }).to.throw(); }); - it('should be okay with valid parameters', function () { + it('should be okay with valid parameters', () => { expect(transfer.create(validTransactionData, validTransaction)).to.be.an('object'); }); }); - describe('calculateFee', function () { - it('should return the correct fee', function () { - expect(transfer.calculateFee()).to.equal(node.constants.fees.send); + describe('calculateFee()', () => { + it('should return the correct fee', () => { + expect(transfer.calculateFee()).to.equal(constants.fees.send); }); }); - describe('verify', function () { - it('should return error if recipientId is not set', function (done) { - var trs = _.cloneDeep(validTransaction); + describe('verify()', () => { + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); delete trs.recipientId; - transfer.verify(trs, validSender, function (err) { + transfer.verify(trs, validSender, (err) => { expect(err).to.equal('Missing recipient'); done(); }); }); - it('should return error if amount is less than 0', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error if amount is less than 0', (done) => { + const trs = _.cloneDeep(validTransaction); trs.amount = -10; - transfer.verify(trs, validSender, function (err) { + transfer.verify(trs, validSender, (err) => { expect(err).to.equal('Invalid transaction amount'); done(); }); }); - it('should verify okay for valid transaction', function (done) { + it('should verify okay for valid transaction', (done) => { transfer.verify(validTransaction, validSender, done); }); }); - describe('process', function () { - it('should be okay', function (done) { + describe('process()', () => { + it('should be okay', (done) => { transfer.process(validTransaction, validSender, done); }); }); - describe('getBytes', function () { - it('should be okay', function () { - expect(transfer.getBytes(validTransaction)).to.eql(null); + describe('getBytes()', () => { + it('should be okay', () => { + expect(transfer.getBytes(validTransaction)).to.be.null; }); }); - describe('apply', function () { - var dummyBlock = { - id: '9314232245035524467', - height: 1 - }; - + describe('apply()', () => { function undoTransaction (trs, sender, done) { transfer.undo.call(transaction, trs, dummyBlock, sender, done); } - it('should return error if recipientId is not set', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); delete trs.recipientId; - transfer.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - expect(err).to.equal('Invalid public key'); + transfer.apply.call(transaction, trs, dummyBlock, validSender, (err) => { + expect(err).to.equal('Missing address or public key'); done(); }); }); - it('should be okay for a valid transaction', function (done) { - accountModule.getAccount({ address: validUnconfirmedTrs.recipientId }, function (err, accountBefore) { + it('should be okay for a valid transaction', (done) => { + accountModule.getAccount({ address: validUnconfirmedTransaction.recipientId }, (err, accountBefore) => { expect(err).to.not.exist; expect(accountBefore).to.exist; - var amount = new bignum(validUnconfirmedTrs.amount.toString()); - var balanceBefore = new bignum(accountBefore.balance.toString()); + const amount = new bignum(validUnconfirmedTransaction.amount.toString()); + const balanceBefore = new bignum(accountBefore.balance.toString()); - transfer.apply.call(transaction, validUnconfirmedTrs, dummyBlock, testSender, function (err) { + transfer.apply.call(transaction, validUnconfirmedTransaction, dummyBlock, validSender, (err) => { expect(err).to.not.exist; - accountModule.getAccount({ address: validUnconfirmedTrs.recipientId }, function (err, accountAfter) { + accountModule.getAccount({ address: validUnconfirmedTransaction.recipientId }, (err, accountAfter) => { expect(err).to.not.exist; expect(accountAfter).to.exist; - var balanceAfter = new bignum(accountAfter.balance.toString()); + const balanceAfter = new bignum(accountAfter.balance.toString()); expect(balanceBefore.plus(amount).toString()).to.equal(balanceAfter.toString()); - undoTransaction(validUnconfirmedTrs, testSender, done); + undoTransaction(validUnconfirmedTransaction, validSender, done); }); }); }); }); }); - describe('undo', function () { - var dummyBlock = { - id: '9314232245035524467', - height: 1 - }; - + describe('undo()', () => { function applyTransaction (trs, sender, done) { transfer.apply.call(transaction, trs, dummyBlock, sender, done); } - it('should return error if recipientId is not set', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error if recipientId is not set', (done) => { + const trs = _.cloneDeep(validTransaction); delete trs.recipientId; - transfer.undo.call(transaction, trs, dummyBlock, validSender, function (err) { - expect(err).to.equal('Invalid public key'); + transfer.undo.call(transaction, trs, dummyBlock, validSender, (err) => { + expect(err).to.equal('Missing address or public key'); done(); }); }); - it('should be okay for a valid transaction', function (done) { - accountModule.getAccount({ address: validUnconfirmedTrs.recipientId }, function (err, accountBefore) { + it('should be okay for a valid transaction', (done) => { + accountModule.getAccount({ address: validUnconfirmedTransaction.recipientId }, (err, accountBefore) => { expect(err).to.not.exist; - var amount = new bignum(validUnconfirmedTrs.amount.toString()); - var balanceBefore = new bignum(accountBefore.balance.toString()); + const amount = new bignum(validUnconfirmedTransaction.amount.toString()); + const balanceBefore = new bignum(accountBefore.balance.toString()); - transfer.undo.call(transaction, validUnconfirmedTrs, dummyBlock, testSender, function (err) { + transfer.undo.call(transaction, validUnconfirmedTransaction, dummyBlock, validSender, (err) => { expect(err).to.not.exist; - accountModule.getAccount({ address: validUnconfirmedTrs.recipientId }, function (err, accountAfter) { + accountModule.getAccount({ address: validUnconfirmedTransaction.recipientId }, (err, accountAfter) => { expect(err).to.not.exist; - var balanceAfter = new bignum(accountAfter.balance.toString()); + const balanceAfter = new bignum(accountAfter.balance.toString()); expect(balanceAfter.plus(amount).toString()).to.equal(balanceBefore.toString()); - applyTransaction(validUnconfirmedTrs, testSender, done); + applyTransaction(validUnconfirmedTransaction, validSender, done); }); }); }); }); }); - describe('applyUnconfirmed', function () { - it('should be okay with valid params', function (done) { + describe('applyUnconfirmed()', () => { + it('should be okay with valid params', (done) => { transfer.applyUnconfirmed.call(transaction, validTransaction, validSender, done); }); }); - describe('undoUnconfirmed', function () { - it('should be okay with valid params', function (done) { + describe('undoUnconfirmed()', () => { + it('should be okay with valid params', (done) => { transfer.undoUnconfirmed.call(transaction, validTransaction, validSender, done); }); }); - describe('objectNormalize', function () { - it('should remove blockId from trs', function () { - var trs = _.cloneDeep(validTransaction); + describe('objectNormalize()', () => { + it('should remove blockId from trs', () => { + const trs = _.cloneDeep(validTransaction); trs.blockId = '9314232245035524467'; expect(transfer.objectNormalize(trs)).to.not.have.key('blockId'); }); }); - describe('dbRead', function () { - it('should be okay', function () { - expect(transfer.dbRead(validTransaction)).to.eql(null); + describe('dbRead()', () => { + it('should be okay', () => { + expect(transfer.dbRead(validTransaction)).to.be.null; }); }); - describe('dbSave', function () { - it('should be okay', function () { - expect(transfer.dbRead(validTransaction)).to.eql(null); + describe('dbSave()', () => { + it('should be okay', () => { + expect(transfer.dbRead(validTransaction)).to.be.null; }); }); - describe('ready', function () { - it('should return true for single signature trs', function () { - expect(transfer.ready(validTransaction, validSender)).to.equal(true); + describe('ready()', () => { + it('should return true for single signature trs', () => { + expect(transfer.ready(validTransaction, validSender)).to.be.true; }); // Multisignatures tests are disabled currently /* - it('should return false for multi signature transaction with less signatures', function () { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should return false for multi signature transaction with less signatures', () => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(validSender); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; - expect(transaction.ready(trs, vs)).to.equal(false); + expect(transaction.ready(trs, vs)).to.be.false; }); - it('should return true for multi signature transaction with at least min signatures', function () { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); + it('should return true for multi signature transaction with at least min signatures', () => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(validSender); vs.multisignatures = [validKeypair.publicKey.toString('hex')]; vs.multimin = 1; delete trs.signature; trs.signature = transaction.sign(senderKeypair, trs); trs.signatures = [transaction.multisign(validKeypair, trs)]; - expect(transaction.ready(trs, vs)).to.equal(true); + expect(transaction.ready(trs, vs)).to.be.true; }); */ }); diff --git a/test/unit/logic/vote.js b/test/unit/logic/vote.js index e77a31f1..3f6259f5 100644 --- a/test/unit/logic/vote.js +++ b/test/unit/logic/vote.js @@ -1,321 +1,315 @@ -'use strict';/* eslint*/ - -var crypto = require('crypto'); -var async = require('async'); - -var chai = require('chai'); -var expect = require('chai').expect; -var _ = require('lodash'); - -var node = require('./../../node.js'); -var ed = require('../../../helpers/ed'); -var diff = require('../../../helpers/diff.js'); -var transactionTypes = require('../../../helpers/transactionTypes'); -var constants = require('../../../helpers/constants.js'); - -var modulesLoader = require('../../common/initModule').modulesLoader; -var TransactionLogic = require('../../../logic/transaction.js'); -var Vote = require('../../../logic/vote.js'); -var Transfer = require('../../../logic/transfer.js'); -var Delegate = require('../../../logic/delegate.js'); -var Rounds = require('../../../modules/rounds.js'); -var AccountLogic = require('../../../logic/account.js'); -var AccountModule = require('../../../modules/accounts.js'); -var DelegateModule = require('../../../modules/delegates.js'); - -// valid keypair sample (market delegate's passphrase) -var validPassword = 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon'; -var validHash = ed.createPassPhraseHash(validPassword); -var validKeypair = ed.makeKeypair(validHash); - -var validSender = { - balance: 8067474861277, - u_balance: 8067474861277, - password: 'rally clean ladder crane gadget century timber jealous shine scorpion beauty salon', - username: 'market', - publicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', - multimin: 0, - address: 'U810656636599221322' -}; - -var senderHash = ed.createPassPhraseHash(validSender.password); -var senderKeypair = ed.makeKeypair(senderHash); - -var transactionVotes = [ - '-9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f' -]; - -var validTransactionData = { - type: 3, - amount: 8067474861277, - sender: validSender, - senderId: 'U810656636599221322', - fee: 10000000, - keypair: senderKeypair, - publicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', - votes: transactionVotes -}; - -var validTransaction = { - type: 3, - amount: 0, - senderPublicKey: 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d0', - requesterPublicKey: null, - timestamp: 34253582, - asset: { - votes: ['-9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f'] - }, - data: undefined, - recipientId: 'U810656636599221322', - signature: 'de668e2722fbc2fd02bac1bb66ff1238d75354f64ca0adc5b1967f5f4e67038336cee6a85af43ed9fa5f3a091890738de14c857bd7b1f9bade7ff1da1c395a0e', - id: '5962289265698105102', - fee: 100000000, - senderId: 'U810656636599221322' -}; - -var existedDelegateKey = '81dd616f47bda681c929b9035aa1cbc9c41ba9d4af91f04744d1325e1b1af099'; -var invalidDelegateKey = 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30fg'; - -describe('vote', function () { - var voteBindings; - var vote; - var accountsModule; - var transaction; - var dummyBlock = { - id: '9314232245035524467', - height: 1 - }; - - var votedDelegates = [ +'use strict'; /* eslint*/ + +const async = require('async'); + +const { expect } = require('chai'); +const _ = require('lodash'); + +const diff = require('../../../helpers/diff.js'); +const transactionTypes = require('../../../helpers/transactionTypes.js'); +const constants = require('../../../helpers/constants.js'); + +const { modulesLoader } = require('../../common/initModule'); + +const TransactionLogic = require('../../../logic/transaction.js'); +const Vote = require('../../../logic/vote.js'); +const Transfer = require('../../../logic/transfer.js'); +const Rounds = require('../../../modules/rounds.js'); +const AccountLogic = require('../../../logic/account.js'); +const AccountModule = require('../../../modules/accounts.js'); +const DelegateModule = require('../../../modules/delegates.js'); + +const { dummyBlock } = require('../../common/stubs/blocks.js'); +const { + iAccount, + testAccount, + testAccountKeypair, +} = require('../../common/stubs/account.js'); +const { + validTransactionData, + validTransaction, + existedDelegateKey, + invalidDelegateKey, +} = require('../../common/stubs/transactions/vote.js'); + +describe('vote', () => { + let voteBindings; + let vote; + let accountsModule; + let transaction; + + const votedDelegates = [ 'd365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', 'd3a3c26c3906080689d0c2ccd3df30f2f4797c881e21a92aa4579bc68744581f', - '2deabea717a9e9054e3759e3041b84409dd6195c74d9d7736e0cd8442c000f5a' + '2deabea717a9e9054e3759e3041b84409dd6195c74d9d7736e0cd8442c000f5a', ]; - function addVotes (votes, done) { - var trs = _.clone(validTransaction); + function addVotes(votes, done) { + const trs = _.clone(validTransaction); trs.asset.votes = votes; - async.parallel([ - function (cb) { - vote.apply.call(transaction, trs, dummyBlock, validSender, cb); - }, function (cb) { - vote.applyUnconfirmed.call(transaction, trs, validSender, cb); - } - ], done); + async.parallel( + [ + (cb) => { + vote.apply.call(transaction, trs, dummyBlock, testAccount, cb); + }, + (cb) => { + vote.applyUnconfirmed.call(transaction, trs, testAccount, cb); + }, + ], + done + ); } - function checkAccountVotes (senderPublicKey, state, votes, action, done) { + function checkAccountVotes(senderPublicKey, state, votes, action, done) { votes = action == 'apply' ? votes : diff.reverse(votes); - accountsModule.getAccount({ publicKey: senderPublicKey }, function (err, account) { - var delegates = ((state === 'confirmed') ? account.delegates : account.u_delegates) || []; - var groupedVotes = _.groupBy(votes, function (v) { - return v[0]; - }); - var fil = delegates.filter(function (v) { - return groupedVotes['+'] && groupedVotes['+'].indexOf('+' + v) != -1; - }); - // added one because expect doesn't have greaterThanEqualTo condition - expect(delegates.filter(function (v) { - return groupedVotes['+'] && groupedVotes['+'].indexOf('+' + v) != -1; - }).length + 1).to.be.above(groupedVotes['+'] ? groupedVotes['+'].length : 0); - expect(delegates.filter(function (v) { - return groupedVotes['-'] && groupedVotes['-'].indexOf('-' + v) != -1; - }).length).to.equal(0); - done(); - }); + accountsModule.getAccount( + { publicKey: senderPublicKey }, + (err, account) => { + const delegates = + (state === 'confirmed' ? account.delegates : account.u_delegates) || + []; + const groupedVotes = _.groupBy(votes, (v) => v[0]); + + expect( + delegates.filter( + (v) => groupedVotes['+'] && groupedVotes['+'].indexOf('+' + v) != -1 + ).length + ).to.be.greaterThanOrEqual( + groupedVotes['+'] ? groupedVotes['+'].length : 0 + ); + expect( + delegates.filter( + (v) => groupedVotes['-'] && groupedVotes['-'].indexOf('-' + v) != -1 + ).length + ).to.equal(0); + done(); + } + ); } - before(function (done) { - async.auto({ - rounds: function (cb) { - modulesLoader.initModule(Rounds, modulesLoader.scope, cb); - }, - accountLogic: function (cb) { - modulesLoader.initLogicWithDb(AccountLogic, cb, {}); - }, - transactionLogic: ['rounds', 'accountLogic', function (result, cb) { - modulesLoader.initLogicWithDb(TransactionLogic, function (err, __transaction) { - __transaction.bindModules(result); - cb(err, __transaction); - }, { - ed: require('../../../helpers/ed'), - account: result.account - }); - }], - accountModule: ['accountLogic', 'transactionLogic', function (result, cb) { - modulesLoader.initModuleWithDb(AccountModule, cb, { - logic: { - account: result.accountLogic, - transaction: result.transactionLogic - } - }); - }], - delegateModule: ['accountModule', function (result, cb) { - modulesLoader.initModuleWithDb(DelegateModule, function (err, __delegates) { - // not all required bindings, only the ones required for votes - __delegates.onBind({ - rounds: result.rounds, - accounts: result.accountModule - }); - cb(err, __delegates); - }, { - logic: { - transaction: result.transactionLogic + before((done) => { + async.auto( + { + rounds(cb) { + modulesLoader.initModule(Rounds, modulesLoader.scope, cb); + }, + accountLogic(cb) { + modulesLoader.initLogicWithDb(AccountLogic, cb, {}); + }, + transactionLogic: [ + 'rounds', + 'accountLogic', + (result, cb) => { + modulesLoader.initLogicWithDb( + TransactionLogic, + (err, __transaction) => { + __transaction.bindModules(result); + cb(err, __transaction); + }, + { + ed: require('../../../helpers/ed'), + account: result.account, + } + ); }, - library: { - schema: modulesLoader.scope.schema - } - }); - }] - }, function (err, result) { - expect(err).to.not.exist; - vote = new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema); - voteBindings = { - delegate: result.delegateModule, - rounds: result.rounds, - account: result.accountModule - }; - vote.bind(result.delegateModule, result.rounds); - transaction = result.transactionLogic; - transaction.attachAssetType(transactionTypes.VOTE, vote); - accountsModule = result.accountModule; - done(); - }); + ], + accountModule: [ + 'accountLogic', + 'transactionLogic', + (result, cb) => { + modulesLoader.initModuleWithDb(AccountModule, cb, { + logic: { + account: result.accountLogic, + transaction: result.transactionLogic, + }, + }); + }, + ], + delegateModule: [ + 'accountModule', + (result, cb) => { + modulesLoader.initModuleWithDb( + DelegateModule, + (err, __delegates) => { + // not all required bindings, only the ones required for votes + __delegates.onBind({ + rounds: result.rounds, + accounts: result.accountModule, + }); + cb(err, __delegates); + }, + { + logic: { + transaction: result.transactionLogic, + }, + library: { + schema: modulesLoader.scope.schema, + }, + } + ); + }, + ], + }, + (err, result) => { + expect(err).to.not.exist; + vote = new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema); + voteBindings = { + delegate: result.delegateModule, + rounds: result.rounds, + account: result.accountModule, + }; + vote.bind(result.delegateModule, result.rounds); + transaction = result.transactionLogic; + transaction.attachAssetType(transactionTypes.VOTE, vote); + accountsModule = result.accountModule; + done(); + } + ); }); - before(function (done) { + before((done) => { // create new account for testing; - var transfer = new Transfer(); + const transfer = new Transfer(); transfer.bind(voteBindings.account, voteBindings.rounds); transaction.attachAssetType(transactionTypes.SEND, transfer); - var sendTrs = { + const sendTrs = { type: 0, amount: 8067474861277, - senderPublicKey: 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', + senderPublicKey: + 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', requesterPublicKey: null, timestamp: 34251006, asset: {}, data: undefined, recipientId: '2262452491031990877L', - signature: 'f2910e221d88134265974d9fc8efee0532e7e14ffdb22a9674c64bfd01863e70da75db51f7e0adcfbe87d9efdaef9f914f577ca08a7664db290e8e5ad89eb30c', + signature: + 'f2910e221d88134265974d9fc8efee0532e7e14ffdb22a9674c64bfd01863e70da75db51f7e0adcfbe87d9efdaef9f914f577ca08a7664db290e8e5ad89eb30c', id: '4802102241260248478', fee: 10000000, - senderId: '16313739661670634666L' + senderId: '16313739661670634666L', }; - var sender = { + const sender = { username: null, isDelegate: 0, address: '16313739661670634666L', - publicKey: 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', + publicKey: + 'c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f', balance: 9850458911801508, u_balance: 9850458911801508, - blockId: '8505659485551877884' + blockId: '8505659485551877884', }; transaction.apply(sendTrs, dummyBlock, sender, done); }); - before(function (done) { - addVotes(votedDelegates.map(function (v) { - return '+' + v; - }), function (err) { - // it's okay if it returns error, because that means I've already voted for these delegates - done(); - }); + before((done) => { + addVotes( + votedDelegates.map((v) => `+${v}`), + (err) => { + // it's okay if it returns error, because that means I've already voted for these delegates + done(); + } + ); }); - describe('bind', function () { - it('should be okay with correct params', function () { - expect(function () { + describe('bind()', () => { + it('should be okay with correct params', () => { + expect(() => { vote.bind(voteBindings.delegate, voteBindings.rounds); }).to.not.throw(); }); - after(function () { + after(() => { vote.bind(voteBindings.delegate, voteBindings.rounds); }); }); - describe('create', function () { - it('should throw with empty parameters', function () { - expect(function () { + describe('create()', () => { + it('should throw with empty parameters', () => { + expect(() => { vote.create(); }).to.throw(); }); - it('should be okay with valid parameters', function () { - expect(vote.create(validTransactionData, validTransaction)).to.be.an('object'); + it('should be okay with valid parameters', () => { + expect(vote.create(validTransactionData, validTransaction)).to.be.an( + 'object' + ); }); }); - describe('calculateFee', function () { - it('should return the correct fee', function () { - expect(vote.calculateFee()).to.equal(node.constants.fees.vote); + describe('calculateFee()', () => { + it('should return the correct fee', () => { + expect(vote.calculateFee()).to.equal(constants.fees.vote); }); }); - describe('verify', function () { - it('should return error when recipientId and sender id are different', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.recipientId = node.iAccount.address; - vote.verify(trs, validSender, function (err) { + describe('verify()', () => { + it('should return error when recipientId and sender id are different', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.recipientId = iAccount.address; + vote.verify(trs, testAccount, (err) => { expect(err).to.equal('Invalid recipient'); done(); }); }); - it('should return error when votes are not set', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error when votes are not set', (done) => { + const trs = _.cloneDeep(validTransaction); delete trs.asset.votes; - vote.verify(trs, validSender, function (err) { + vote.verify(trs, testAccount, (err) => { expect(err).to.equal('Invalid transaction asset'); done(); }); }); - it('should return error asset votes are not an array', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error asset votes are not an array', (done) => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes = '+' + votedDelegates[0]; - vote.verify(trs, validSender, function (err) { + vote.verify(trs, testAccount, (err) => { expect(err).to.equal('Invalid votes. Must be an array'); done(); }); }); - it('should return error when voting for an account twice', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = Array.apply(null, Array(2)).map(function (v, i) { + it('should return error when voting for an account twice', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = Array.apply(null, Array(2)).map((v, i) => { return (i % 2 ? '+' : '-') + votedDelegates[0]; }); - vote.verify(trs, validSender, function (err) { - expect(err).to.equal('Multiple votes for same delegate are not allowed'); + vote.verify(trs, testAccount, (err) => { + expect(err).to.equal( + 'Multiple votes for same delegate are not allowed' + ); done(); }); }); - it('should return error when votes array is empty', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error when votes array is empty', (done) => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes = []; - vote.verify(trs, validSender, function (err) { + vote.verify(trs, testAccount, (err) => { expect(err).to.equal('Invalid votes. Must not be empty'); done(); }); }); - it('should return error when removing vote for delegate sender has not voted', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = ['-' + node.iAccount.publicKey]; - vote.verify(trs, validSender, function (err) { - expect(err).to.equal('Failed to remove vote, account has not voted for this delegate'); + it('should return error when removing vote for delegate sender has not voted', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = ['-' + iAccount.publicKey]; + vote.verify(trs, testAccount, (err) => { + expect(err).to.equal( + 'Failed to remove vote, account has not voted for this delegate' + ); done(); }); }); - it('should return error if votes are more than 33', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return error if votes are more than 33', (done) => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes = [ '-904c294899819cce0283d8d351cb10febfa0e9f0acd90a820ec8eb90a7084c37', '-399a7d14610c4da8800ed929fc6a05133deb8fbac8403dec93226e96fa7590ee', @@ -357,310 +351,459 @@ describe('vote', function () { '-94b163c5a5ad346db1c84edaff51604164476cf78b8834b6b610dd03bd6b65d9', '-6164b0cc68f8de44cde90c78e838b9ee1d6041fa61cf0cfbd834d76bb369a10e', '-3476bba16437ee0e04a29daa34d753139fbcfc14152372d7be5b7c75d51bac6c', - '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746' + '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746', ]; - vote.verify(trs, validSender, function (err) { - expect(err).to.equal('Voting limit exceeded. Maximum is 33 votes per transaction'); + vote.verify(trs, testAccount, (err) => { + expect(err).to.equal( + 'Voting limit exceeded. Maximum is 33 votes per transaction' + ); done(); }); }); - it('should return error for casting multiple votes for same account in a transaction', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = Array.apply(null, Array(2)).map(function (v, i) { + it('should return error for casting multiple votes for same account in a transaction', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = Array.apply(null, Array(2)).map((v, i) => { return '+904c294899819cce0283d8d351cb10febfa0e9f0acd90a820ec8eb90a7084c37'; }); - vote.verify(trs, validSender, function (err) { - expect(err).to.equal('Multiple votes for same delegate are not allowed'); + vote.verify(trs, testAccount, (err) => { + expect(err).to.equal( + 'Multiple votes for same delegate are not allowed' + ); done(); }); }); - it('should verify transaction with correct params', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = ['-d365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089']; - vote.verify(trs, validSender, done); + it('should verify transaction with correct params', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = [ + '-d365e59c9880bd5d97c78475010eb6d96c7a3949140cda7e667f9513218f9089', + ]; + vote.verify(trs, testAccount, done); }); }); - describe('verifyVote', function () { - it('should throw if vote is of invalid length', function (done) { - var invalidVote = '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746'; - vote.verifyVote(invalidVote, function (err) { + describe('verifyVote()', () => { + it('should throw if vote is of invalid length', (done) => { + const invalidVote = + '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746'; + vote.verifyVote(invalidVote, (err) => { expect(err).to.equal('Invalid vote format'); done(); }); }); - it('should be okay for removing vote', function (done) { - var validVote = '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746f'; + it('should be okay for removing vote', (done) => { + const validVote = + '-01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746f'; vote.verifyVote(validVote, done); }); - it('should be okay for adding vote', function (done) { - var validVote = '+01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746f'; + it('should be okay for adding vote', (done) => { + const validVote = + '+01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398d746f'; vote.verifyVote(validVote, done); }); }); - describe('checkConfirmedDelegates (add vote)', function () { - it('should return err if vote is already made to a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { + describe('checkConfirmedDelegates()', () => { + it('should return err if vote is already made to a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { return '+' + v; }); - vote.checkConfirmedDelegates(trs, function (err) { - expect(err).to.equal('Failed to add vote, account has already voted for this delegate'); + vote.checkConfirmedDelegates(trs, (err) => { + expect(err).to.equal( + 'Failed to add vote, account has already voted for this delegate' + ); done(); }); }); - it('should return err when account is not a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = ['+' + node.iAccount.publicKey]; - vote.checkConfirmedDelegates(trs, function (err) { + it('should return err when account is not a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = ['+' + iAccount.publicKey]; + vote.checkConfirmedDelegates(trs, (err) => { expect(err).to.equal('Delegate not found'); done(); }); }); - it('should be okay when adding vote to a delegate', function (done) { - var trs = _.clone(validTransaction); - // remove existed votes - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', () => null); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); + it('should be okay when adding vote to a delegate', (done) => { + const trs = _.clone(validTransaction); + // remove existing votes + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + () => null + ); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); vote.checkConfirmedDelegates(trs, () => null); // restore votes - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', done); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + done + ); }); }); }); - }); - describe('checkConfirmedDelegates (remove vote)', function () { - it('should return err if vote is not made for a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = ['-9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c']; - vote.checkConfirmedDelegates(trs, function (err) { - expect(err).to.equal('Failed to remove vote, account has not voted for this delegate'); + it('should return err if vote is not made for a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = [ + '-9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c', + ]; + vote.checkConfirmedDelegates(trs, (err) => { + expect(err).to.equal( + 'Failed to remove vote, account has not voted for this delegate' + ); done(); }); }); - it('should be okay when removing vote for a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should be okay when removing vote for a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes = [`-${existedDelegateKey}`]; vote.checkConfirmedDelegates(trs, done); }); }); - describe('checkUnconfirmedDelegates (add vote)', function () { - it('should return err if vote is already made to a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { + describe('checkUnconfirmedDelegates()', () => { + it('should return err if vote is already made to a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { return '+' + v; }); - vote.checkUnconfirmedDelegates(trs, function (err) { - expect(err).to.equal('Failed to add vote, account has already voted for this delegate'); + vote.checkUnconfirmedDelegates(trs, (err) => { + expect(err).to.equal( + 'Failed to add vote, account has already voted for this delegate' + ); done(); }); }); - it('should return err when account is not a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); + it('should return err when account is not a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes = [`+${invalidDelegateKey}`]; - vote.checkUnconfirmedDelegates(trs, function (err) { - expect(err).to.equal('Delegate not found'); + vote.checkUnconfirmedDelegates(trs, (err) => { + expect(err).to.include('Invalid public key'); done(); }); }); - it('should be okay when adding vote to a delegate', function (done) { - var trs = _.clone(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', () => null); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - // vote.checkUnconfirmedDelegates(trs, done); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', done); + it('should be okay when adding vote to a delegate', (done) => { + const trs = _.clone(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + () => null + ); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + done + ); }); }); }); - }); - describe('checkUnconfirmedDelegates (remove vote)', function () { - it('should return err if vote is not made for a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = ['-9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c']; - vote.checkUnconfirmedDelegates(trs, function (err) { - expect(err).to.equal('Failed to remove vote, account has not voted for this delegate'); + it('should return err if vote is not made for a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = [ + '-9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c', + ]; + vote.checkUnconfirmedDelegates(trs, (err) => { + expect(err).to.equal( + 'Failed to remove vote, account has not voted for this delegate' + ); done(); }); }); - it('should return okay when removing vote for a delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { + it('should return okay when removing vote for a delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { return '-' + v; }); vote.checkUnconfirmedDelegates(trs, done); }); }); - describe('process', function () { - it('should be okay', function (done) { - vote.process(validTransaction, validSender, done); + describe('process()', () => { + it('should be okay', (done) => { + vote.process(validTransaction, testAccount, done); }); }); - describe('apply', function () { - it('should remove votes for delegates', function (done) { - var trs = _.clone(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', done); + describe('apply()', () => { + it('should remove votes for delegates', (done) => { + const trs = _.clone(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + done + ); }); }); - it('should add vote for delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - vote.apply.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'apply', done); + it('should add vote for delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.apply.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'apply', + done + ); }); }); }); - describe('undo', function () { - it('should undo remove votes for delegates', function (done) { - var trs = _.clone(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.undo.call(transaction, validTransaction, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'undo', done); + describe('undo()', () => { + it('should undo remove votes for delegates', (done) => { + const trs = _.clone(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; }); - }); - - it('should undo add vote for delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - vote.undo.call(transaction, trs, dummyBlock, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'confirmed', trs.asset.votes, 'undo', done); + vote.undo.call( + transaction, + validTransaction, + dummyBlock, + testAccount, + (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'undo', + done + ); + } + ); + }); + + it('should undo add vote for delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.undo.call(transaction, trs, dummyBlock, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'confirmed', + trs.asset.votes, + 'undo', + done + ); }); }); }); - describe('applyUnconfirmed', function () { - it('should remove votes for delegates', function (done) { - var trs = _.clone(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.applyUnconfirmed.call(transaction, validTransaction, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'unconfirmed', trs.asset.votes, 'apply', done); + describe('applyUnconfirmed()', () => { + it('should remove votes for delegates', (done) => { + const trs = _.clone(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; }); - }); - - it('should add vote for delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - vote.applyUnconfirmed.call(transaction, trs, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'unconfirmed', trs.asset.votes, 'apply', done); + vote.applyUnconfirmed.call( + transaction, + validTransaction, + testAccount, + (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'unconfirmed', + trs.asset.votes, + 'apply', + done + ); + } + ); + }); + + it('should add vote for delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.applyUnconfirmed.call(transaction, trs, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'unconfirmed', + trs.asset.votes, + 'apply', + done + ); }); }); }); - describe('undoUnconfirmed', function () { - it('should undo remove votes for delegates', function (done) { - var trs = _.clone(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '-' + v; }); - vote.undoUnconfirmed.call(transaction, validTransaction, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'unconfirmed', trs.asset.votes, 'undo', done); + describe('undoUnconfirmed()', () => { + it('should undo remove votes for delegates', (done) => { + const trs = _.clone(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '-' + v; }); - }); - - it('should undo add vote for delegate', function (done) { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = votedDelegates.map(function (v) { return '+' + v; }); - vote.undoUnconfirmed.call(transaction, trs, validSender, function (err) { - checkAccountVotes(trs.senderPublicKey, 'unconfirmed', trs.asset.votes, 'undo', done); + vote.undoUnconfirmed.call( + transaction, + validTransaction, + testAccount, + (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'unconfirmed', + trs.asset.votes, + 'undo', + done + ); + } + ); + }); + + it('should undo add vote for delegate', (done) => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = votedDelegates.map((v) => { + return '+' + v; + }); + vote.undoUnconfirmed.call(transaction, trs, testAccount, (err) => { + checkAccountVotes( + trs.senderPublicKey, + 'unconfirmed', + trs.asset.votes, + 'undo', + done + ); }); }); }); - describe('objectNormalize', function () { - it('should normalize object for valid trs', function () { - expect(vote.objectNormalize.call(transaction, validTransaction)).to.eql(validTransaction); + describe('objectNormalize()', () => { + it('should normalize object for valid trs', () => { + expect(vote.objectNormalize.call(transaction, validTransaction)).to.eql( + validTransaction + ); }); - it('should throw error for duplicate votes in a transaction', function () { - var trs = _.cloneDeep(validTransaction); + it('should throw error for duplicate votes in a transaction', () => { + const trs = _.cloneDeep(validTransaction); trs.asset.votes.push(trs.asset.votes[0]); - expect(function () { + expect(() => { vote.objectNormalize.call(transaction, trs); - }).to.throw('Failed to validate vote schema: Array items are not unique (indexes 0 and 3)'); + }).to.throw( + 'Failed to validate vote schema: Array items are not unique (indexes 0 and 3)' + ); }); - it('should return error when votes array is longer than maximum acceptable', function () { - var trs = _.cloneDeep(validTransaction); - trs.asset.votes = Array.apply(null, Array(constants.maxVotesPerTransaction + 1)).map(function () { - return '+' + node.iAccount.publicKey; + it('should return error when votes array is longer than maximum acceptable', () => { + const trs = _.cloneDeep(validTransaction); + trs.asset.votes = Array.apply( + null, + Array(constants.maxVotesPerTransaction + 1) + ).map(() => { + return '+' + iAccount.publicKey; }); - expect(function () { + expect(() => { vote.objectNormalize.call(transaction, trs); - }).to.throw('Failed to validate vote schema: Array is too long (34), maximum 33'); + }).to.throw( + 'Failed to validate vote schema: Array is too long (34), maximum 33' + ); }); }); - describe('dbRead', function () { - it('should read votes correct', function () { - var rawVotes = '+9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f,+141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a,+3ff32442bb6da7d60c1b7752b24e6467813c9b698e0f278d48c43580da972135'; - expect(vote.dbRead({ - v_votes: rawVotes - })).to.eql({ - votes: rawVotes.split(',') + describe('dbRead()', () => { + it('should read votes correct', () => { + const rawVotes = + '+9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f,+141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a,+3ff32442bb6da7d60c1b7752b24e6467813c9b698e0f278d48c43580da972135'; + expect( + vote.dbRead({ + v_votes: rawVotes, + }) + ).to.eql({ + votes: rawVotes.split(','), }); }); - it('should return null if no votes are supplied', function () { - expect(vote.dbRead({ - v_votes: null - })).to.eql(null); + it('should return null if no votes are supplied', () => { + expect( + vote.dbRead({ + v_votes: null, + }) + ).to.be.null; }); }); - describe('dbSave', function () { - it('should create return db save promise', function () { - var valuesKeys = ['votes', 'transactionId']; - var savePromise = vote.dbSave(validTransaction); - expect(savePromise).to.be.an('object').with.keys(['table', 'fields', 'values']); - expect(savePromise.values).to.have.keys(valuesKeys); - expect(savePromise.values.votes).to.eql(validTransaction.asset.votes.join(',')); + describe('dbSave()', () => { + it('should create return db save promise', () => { + const valuesKeys = ['votes', 'transactionId']; + const saveQuery = vote.dbSave(validTransaction); + expect(saveQuery) + .to.be.an('object') + .with.keys(['table', 'fields', 'values']); + expect(saveQuery.values).to.have.keys(valuesKeys); + expect(saveQuery.values.votes).to.equal( + validTransaction.asset.votes.join(',') + ); }); }); - describe('ready', function () { - it('should return true for single signature trs', function () { - expect(vote.ready(validTransaction, validSender)).to.equal(true); + + describe('ready()', () => { + it('should return true for single signature trs', () => { + expect(vote.ready(validTransaction, testAccount)).to.be.true; }); - it('should return false for multi signature transaction with less signatures', function () { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); - vs.multisignatures = [validKeypair.publicKey.toString('hex')]; - expect(transaction.ready(trs, vs)).to.equal(false); + it('should return false for multi signature transaction with less signatures', () => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(testAccount); + vs.multisignatures = [testAccountKeypair.publicKey.toString('hex')]; + expect(transaction.ready(trs, vs)).to.be.false; }); - it('should return true for multi signature transaction with alteast min signatures', function () { - var trs = _.cloneDeep(validTransaction); - var vs = _.cloneDeep(validSender); - vs.multisignatures = [validKeypair.publicKey.toString('hex')]; + it('should return true for multi signature transaction with alteast min signatures', () => { + const trs = _.cloneDeep(validTransaction); + const vs = _.cloneDeep(testAccount); + vs.multisignatures = [testAccountKeypair.publicKey.toString('hex')]; vs.multimin = 1; delete trs.signature; - trs.signature = transaction.sign(senderKeypair, trs); - trs.signatures = [transaction.multisign(validKeypair, trs)]; - expect(transaction.ready(trs, vs)).to.equal(true); + trs.signature = transaction.sign(testAccountKeypair, trs); + trs.signatures = [transaction.multisign(testAccountKeypair, trs)]; + expect(transaction.ready(trs, vs)).to.be.true; }); }); }); diff --git a/test/unit/modules/accounts.js b/test/unit/modules/accounts.js new file mode 100644 index 00000000..1a8f4d80 --- /dev/null +++ b/test/unit/modules/accounts.js @@ -0,0 +1,700 @@ +'use strict'; + +const { expect } = require('chai'); +const sinon = require('sinon'); + +const { modulesLoader } = require('../../common/initModule.js'); + +const constants = require('../../../helpers/constants.js'); +const bignum = require('../../../helpers/bignum.js'); + +const { isPublicKey } = require('../../../helpers/publicKey.js'); + +const Accounts = require('../../../modules/accounts.js'); + +const { + testAccount, + notAMnemonicPassphrase, + nonExistingAddress, + invalidPublicKey, + invalidAddress, +} = require('../../common/stubs/account.js'); +const { removeQueuedJob } = require('../../common/globalAfter.js'); + +describe('accounts', function () { + /** + * @type {Accounts} + */ + let accounts; + let modules; + + const dummyBlock = { + id: '9314232245035524467', + height: 1, + timestamp: 0, + }; + + before(function (done) { + modulesLoader.initAllModules((err, __modules) => { + if (err) { + return done(err); + } + + const blocks = __modules.blocks; + blocks.lastBlock.set(dummyBlock); + + const delegates = __modules.delegates; + delegates.onBind(__modules); + + const transactions = __modules.transactions; + transactions.onBind(__modules); + + modules = __modules; + accounts = __modules.accounts; + + done(); + }); + }); + + describe('generateAddressBuPublicKey()', () => { + it('should throw an error when called without parameters', () => { + expect(accounts.generateAddressByPublicKey).to.throw(); + }); + + it('should throw error when called with invalid public key', () => { + expect(() => + accounts.generateAddressByPublicKey(invalidPublicKey) + ).to.throw('Invalid public key'); + }); + + it('should return a valid address when called with valid public key', () => { + const address = accounts.generateAddressByPublicKey( + testAccount.publicKey + ); + expect(address).to.equal(testAccount.address); + }); + }); + + describe('getAccount()', () => { + it('should throw error when called without parameters', () => { + expect(accounts.getAccount).to.throw(); + }); + + it('should return null if no account matches the address', (done) => { + const filter = { address: nonExistingAddress }; + accounts.getAccount(filter, ['address'], (err, account) => { + expect(err).not.to.exist; + expect(account).to.be.null; + done(); + }); + }); + + it('should return error when called with invalid public key and NO fields provided', (done) => { + const filter = { publicKey: invalidPublicKey }; + accounts.getAccount(filter, (err) => { + expect(err).to.include('Invalid public key'); + done(); + }); + }); + + it('should return error when called with invalid public key and fields argument is provided', (done) => { + const filter = { publicKey: invalidPublicKey }; + accounts.getAccount(filter, ['balance'], (err) => { + expect(err).to.include('Invalid public key'); + done(); + }); + }); + + it('should throw an error when called with no callback AND fields parameter', () => { + const filter = { publicKey: invalidPublicKey }; + expect(() => accounts.getAccount(filter)).to.throw(); + }); + + it('should throw an error when called with no callback but fields parameter', () => { + const filter = { publicKey: invalidPublicKey }; + expect(() => accounts.getAccount(filter, ['balance'])).to.throw(); + }); + + it('should throw an error when fields parameter is not an array', () => { + const filter = { publicKey: testAccount.publicKey }; + const invalidFields = 123; + expect(() => accounts.getAccount(filter, invalidFields)).to.throw(); + }); + + it("should return the specified fields of an account matching the given address", (done) => { + const filter = { address: testAccount.address }; + accounts.getAccount( + filter, + ['username', 'address', 'publicKey'], + (err, account) => { + expect(err).not.to.exist; + expect(account).to.eql({ + username: testAccount.username, + address: testAccount.address, + publicKey: testAccount.publicKey, + }); + done(); + } + ); + }); + + it("should return the specified fields of an account matching the given public key", (done) => { + const filter = { publicKey: testAccount.publicKey }; + accounts.getAccount(filter, ['username', 'address'], (err, account) => { + expect(err).not.to.exist; + expect(account).to.eql({ + username: testAccount.username, + address: testAccount.address, + }); + done(); + }); + }); + }); + + // inherits behaviour from logic.account.getAll() + describe('getAccounts()', () => { + it('should throw error when called without parameters', () => { + expect(accounts.getAccounts).to.throw(); + }); + }); + + describe('setAccountAndGet', () => { + it('should return error when called without public key or address', (done) => { + accounts.setAccountAndGet({}, (err, accounts) => { + expect(accounts).not.to.exist; + expect(err).to.equal('Missing address or public key'); + done(); + }); + }); + + it('should throw an error when invalid data is provided and no callback is specified', () => { + expect(() => accounts.setAccountAndGet({})).to.throw( + 'Missing address or public key' + ); + }); + + it('should return error when invalid public key is provided', (done) => { + const cb = sinon.fake(); + expect(() => + accounts.setAccountAndGet({ publicKey: invalidPublicKey }, cb) + ).to.throw('Invalid public key'); + expect(cb.called).to.be.false; + done(); + }); + + it("should change the account balance and return the account", (done) => { + const amount = 100000; + + function undo(previous) { + accounts.setAccountAndGet( + { + publicKey: testAccount.publicKey, + balance: previous.balance, + u_balance: previous.u_balance, + }, + (err) => { + expect(err).not.to.exist; + done(); + } + ); + } + + accounts.getAccount( + { address: testAccount.address }, + ['balance', 'u_balance'], + (err, accountBefore) => { + expect(err).not.to.exist; + + const balance = new bignum(accountBefore.balance) + .plus(amount) + .toString(); + const u_balance = new bignum(accountBefore.balance) + .plus(amount) + .toString(); + + accounts.setAccountAndGet( + { + publicKey: testAccount.publicKey, + balance, + u_balance, + }, + (err, account) => { + expect(err).not.to.exist; + + // check returned values + expect(account.balance).to.equal(balance); + expect(account.u_balance).to.equal(u_balance); + + // check if the values were actually saved + accounts.getAccount( + { address: testAccount.address }, + ['balance', 'u_balance'], + (err, accountAfter) => { + expect(err).not.to.exist; + + expect(accountAfter.balance).to.equal(balance); + expect(accountAfter.u_balance).to.equal(u_balance); + + undo(accountBefore); + } + ); + } + ); + } + ); + }); + }); + + describe('mergeAccountAndGet', () => { + it('should return error when called without parameters', (done) => { + accounts.mergeAccountAndGet({}, (err, accounts) => { + expect(accounts).not.to.exist; + expect(err).to.equal('Missing address or public key'); + done(); + }); + }); + + it('should throw an error when invalid data is provided and no callback is specified', () => { + expect(() => accounts.mergeAccountAndGet({})).to.throw( + 'Missing address or public key' + ); + }); + + it('should throw an error when invalid public key is provided and no address is specified', (done) => { + const cb = sinon.fake(); + expect(() => + accounts.mergeAccountAndGet({ publicKey: invalidPublicKey }, cb) + ).to.throw('Invalid public key'); + expect(cb.called).to.be.false; + done(); + }); + + it("should change the account balance and return the account", (done) => { + const amount = 100000; + + function undo(previous) { + accounts.mergeAccountAndGet( + { + publicKey: testAccount.publicKey, + balance: -amount, + u_balance: -amount, + }, + (err) => { + expect(err).not.to.exist; + + accounts.getAccount( + { publicKey: testAccount.publicKey }, + ['balance', 'u_balance'], + (err, account) => { + expect(err).not.to.exist; + expect(account.balance).to.equal(previous.balance); + expect(account.u_balance).to.equal(previous.u_balance); + + done(); + } + ); + } + ); + } + + accounts.getAccount( + { address: testAccount.address }, + ['balance', 'u_balance'], + (err, accountBefore) => { + expect(err).not.to.exist; + + const balance = new bignum(accountBefore.balance) + .plus(amount) + .toString(); + const u_balance = new bignum(accountBefore.u_balance) + .plus(amount) + .toString(); + + accounts.mergeAccountAndGet( + { + publicKey: testAccount.publicKey, + balance: amount, + u_balance: amount, + }, + (err, account) => { + expect(err).not.to.exist; + + // check returned values + expect(account.balance).to.equal(balance); + expect(account.u_balance).to.equal(u_balance); + + // check if the values were actually saved + accounts.getAccount( + { address: testAccount.address }, + ['balance', 'u_balance'], + (err, accountAfter) => { + expect(err).not.to.exist; + + expect(accountAfter.balance).to.equal(balance); + expect(accountAfter.u_balance).to.equal(u_balance); + + undo(accountBefore); + } + ); + } + ); + } + ); + }); + }); + + describe('isLoaded', () => { + it('should return false before accounts.onBind() was called', function () { + expect(accounts.isLoaded()).to.be.false; + }); + }); + + describe('onBind()', () => { + it('should initialize modules', () => { + accounts.onBind(modules); + expect(accounts.isLoaded()).to.be.true; + }); + }); + + describe('shared', () => { + const accountKeys = [ + 'address', + 'unconfirmedBalance', + 'balance', + 'publicKey', + 'unconfirmedSignature', + 'secondSignature', + 'secondPublicKey', + 'multisignatures', + 'u_multisignatures', + ]; + + describe('open()', () => { + it('should return error if "secret" is of invalid type', (done) => { + const body = { secret: true }; + accounts.shared.open({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include('Expected type string but found'); + done(); + }); + }); + + it('should return error if "secret" is invalid mnemonic', (done) => { + const body = { secret: notAMnemonicPassphrase }; + accounts.shared.open({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include('Mnemonic string is invalid'); + done(); + }); + }); + + it('should return an existing account', (done) => { + const body = { secret: testAccount.secret }; + accounts.shared.open({ body }, (err, response) => { + expect(err).not.to.exist; + + expect(response.account).to.have.all.keys(accountKeys); + expect(response.account.address).to.equal(testAccount.address); + expect(response.account.publicKey).to.equal(testAccount.publicKey); + + done(); + }); + }); + + it('should generate a new account from valid passphrase', (done) => { + const body = { secret: modulesLoader.scope.ed.generatePassphrase() }; + + accounts.shared.open({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.account).to.have.all.keys(accountKeys); + + done(); + }); + }); + + it('should throw with invalid passphrase', (done) => { + const body = { secret: notAMnemonicPassphrase }; + + accounts.shared.open({ body }, (err, response) => { + expect(err).to.include('Mnemonic string is invalid'); + expect(response).not.to.exist; + done(); + }); + }); + }); + + describe('new()', () => { + it('should return error when invalid public key is provided', (done) => { + const body = { publicKey: invalidPublicKey }; + + accounts.shared.new({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include( + "Object didn't pass validation for format publicKey" + ); + done(); + }); + }); + + it('should return account data for a new account', (done) => { + const passphrase = modulesLoader.scope.ed.generatePassphrase(); + const hash = modulesLoader.scope.ed.createPassPhraseHash(passphrase); + const keypair = modulesLoader.scope.ed.makeKeypair(hash); + const publicKey = keypair.publicKey.toString('hex'); + + const body = { publicKey }; + accounts.shared.new({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.account).to.have.all.keys(accountKeys); + done(); + }); + }); + + it('should return account data for an existing account', (done) => { + const body = { publicKey: testAccount.publicKey }; + accounts.shared.new({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.account).to.have.all.keys(accountKeys); + done(); + }); + }); + }); + + describe('getBalance()', () => { + it('should return error when invalid address is provided', (done) => { + const body = { address: testAccount.publicKey }; + accounts.shared.getBalance({ body }, (err, response) => { + expect(err).to.include( + "Object didn't pass validation for format address" + ); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return balance for an existing account', (done) => { + const body = { address: testAccount.address }; + accounts.shared.getBalance({ body }, (err, response) => { + expect(err).not.to.exist; + + const balanceKeys = ['balance', 'unconfirmedBalance']; + expect(response).to.have.all.keys(balanceKeys); + done(); + }); + }); + + it('should return zero balance for non-existing account', (done) => { + const body = { address: nonExistingAddress }; + accounts.shared.getBalance({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.balance).to.equal('0'); + expect(response.unconfirmedBalance).to.equal('0'); + done(); + }); + }); + }); + + describe('getPublickey()', () => { + it('should return an error when invalid address is provided', (done) => { + const body = { address: testAccount.publicKey }; + accounts.shared.getPublickey({ body }, (err, response) => { + expect(err).to.include( + "Object didn't pass validation for format address" + ); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return public key for an existing account', (done) => { + const body = { address: testAccount.address }; + accounts.shared.getPublickey({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.publicKey).to.equal(testAccount.publicKey); + done(); + }); + }); + + it('should return error for non-existing account', (done) => { + const body = { address: nonExistingAddress }; + accounts.shared.getPublickey({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.equal('Account not found'); + done(); + }); + }); + }); + + describe('generatePublicKey()', () => { + const responseKeys = ['publicKey']; + + it('should generate public key for a new account', (done) => { + const passphrase = modulesLoader.scope.ed.generatePassphrase(); + const body = { secret: passphrase }; + accounts.shared.generatePublicKey({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(responseKeys); + expect(isPublicKey(response.publicKey)).to.be.true; + done(); + }); + }); + + it('should return public key for existing account', (done) => { + const body = { secret: testAccount.secret }; + accounts.shared.generatePublicKey({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(responseKeys); + expect(response.publicKey).to.equal(testAccount.publicKey); + done(); + }); + }); + + it('should return null publicKey and the error when invalid mnemonic passphrase is provided', (done) => { + const body = { secret: notAMnemonicPassphrase }; + accounts.shared.generatePublicKey({ body }, (err, response) => { + expect(err).to.include('Mnemonic string is invalid'); + expect(response.publicKey).to.be.null; + done(); + }); + }); + + it('should return error when provided passphrase is of invalid type', (done) => { + const body = { secret: 404 }; + accounts.shared.generatePublicKey({ body }, (err, response) => { + expect(err).to.include('Expected type string'); + expect(response).not.to.exist; + done(); + }); + }); + }); + + describe('getDelegates()', () => { + const responseKeys = ['delegates']; + + it('should return error when invalid address is provided', (done) => { + const body = { address: testAccount.publicKey }; + accounts.shared.getDelegates({ body }, (err, response) => { + expect(err).to.include( + "Object didn't pass validation for format address" + ); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return the delegates voted by the address', (done) => { + const body = { address: testAccount.address }; + accounts.shared.getDelegates({ body }, (err, response) => { + expect(err).not.to.exist; + accounts.getAccount(body, (err, account) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(responseKeys); + expect(response.delegates).to.be.an('array'); + response.delegates.forEach((delegate) => + expect(account.delegates).to.include(delegate.publicKey) + ); + done(); + }); + }); + }); + }); + + describe('getDelegatesFee()', () => { + it('should return delegates fee', (done) => { + accounts.shared.getDelegatesFee({}, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(['fee']); + expect(response.fee).to.equal(constants.fees.delegate); + done(); + }); + }); + }); + + describe('getAccount()', () => { + it('should return the account matching the given address', (done) => { + const body = { address: testAccount.address }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).not.to.exist; + + const { account } = response; + expect(account).to.have.all.keys(accountKeys); + expect(account.address).to.equal(testAccount.address); + expect(account.publicKey).to.equal(testAccount.publicKey); + done(); + }); + }); + + it('should return the account matching the given publicKey', (done) => { + const body = { publicKey: testAccount.publicKey }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).not.to.exist; + + const { account } = response; + expect(account).to.have.all.keys(accountKeys); + expect(account.address).to.equal(testAccount.address); + expect(account.publicKey).to.equal(testAccount.publicKey); + done(); + }); + }); + + it('should return the account the account matching the given public key and address', (done) => { + const body = { + address: testAccount.address, + publicKey: testAccount.publicKey, + }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).not.to.exist; + + const { account } = response; + expect(account).to.have.all.keys(accountKeys); + expect(account.address).to.equal(testAccount.address); + expect(account.publicKey).to.equal(testAccount.publicKey); + done(); + }); + }); + + it('should return error if the address and the public key do not match', (done) => { + const body = { + address: nonExistingAddress, + publicKey: testAccount.publicKey, + }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).to.equal('Account publicKey does not match address'); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return error for non-existing account', (done) => { + const body = { address: nonExistingAddress }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).to.equal('Account not found'); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return error when invalid public key is provided', (done) => { + const body = { publicKey: invalidPublicKey }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).to.include( + "Object didn't pass validation for format publicKey" + ); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return error when invalid address is provided', (done) => { + const body = { address: invalidAddress }; + accounts.shared.getAccount({ body }, (err, response) => { + expect(err).to.include( + "Object didn't pass validation for format address" + ); + expect(response).not.to.exist; + done(); + }); + }); + }); + }); +}); diff --git a/test/unit/modules/blocks.js b/test/unit/modules/blocks.js index e8bd628b..247292d5 100644 --- a/test/unit/modules/blocks.js +++ b/test/unit/modules/blocks.js @@ -1,29 +1,105 @@ 'use strict'; -var chai = require('chai'); -var expect = require('chai').expect; +const { expect } = require('chai'); -var express = require('express'); -var sinon = require('sinon'); +const _ = require('lodash'); +const sinon = require('sinon'); -var modulesLoader = require('../../common/initModule').modulesLoader; +const { modulesLoader } = require('../../common/initModule.js'); +const { dummyBlock } = require('../../common/stubs/blocks.js'); + +const constants = require('../../../helpers/constants.js'); +const Blocks = require('../../../modules/blocks.js'); +const { removeQueuedJob } = require('../../common/globalAfter.js'); + +const generateFreshTimestamp = (secondsAgo) => { + const delta = + secondsAgo === undefined ? constants.blockReceiptTimeOut - 1 : secondsAgo; + const currentTimestamp = + Math.floor(Date.now() / 1000) - Math.floor(constants.epochTime / 1000); + + return currentTimestamp - delta; +}; describe('blocks', function () { - var blocks; + /** + * @type {Blocks} + */ + let blocks; before(function (done) { - modulesLoader.initModules([ - { blocks: require('../../../modules/blocks') } - ], [ - { 'transaction': require('../../../logic/transaction') }, - { 'block': require('../../../logic/block') }, - { 'peers': require('../../../logic/peers.js') } - ], {}, function (err, __blocks) { - if (err) { - return done(err); + modulesLoader.initModules( + [{ blocks: Blocks }], + [ + { transaction: require('../../../logic/transaction') }, + { block: require('../../../logic/block') }, + { peers: require('../../../logic/peers.js') }, + ], + {}, + function (err, __blocks) { + if (err) { + return done(err); + } + blocks = __blocks.blocks; + done(); } - blocks = __blocks.blocks; - done(); + ); + }); + + describe('lastBlock', () => { + afterEach(() => { + blocks.lastBlock.set({}); + }); + + describe('set()', () => { + it('should set the last block and return it', () => { + const block = _.cloneDeep(dummyBlock); + + const result = blocks.lastBlock.set(block); + expect(result).to.eql(block); + + const lastBlock = blocks.lastBlock.get(); + expect(lastBlock).to.eql(block); + }); + }); + + describe('get()', () => { + it('should return the last set block', () => { + const beforeBlock = blocks.lastBlock.get(); + expect(beforeBlock).to.eql({}); + + blocks.lastBlock.set(dummyBlock); + + const afterBlock = blocks.lastBlock.get(); + expect(afterBlock).to.eql(dummyBlock); + }); + }); + + describe('isFresh()', () => { + it('should return false when last block is not set', () => { + const fresh = blocks.lastBlock.isFresh(); + expect(fresh).to.be.false; + }); + + it('should return false when the last block is too old', () => { + const block = _.cloneDeep(dummyBlock); + block.timestamp = 0; + + blocks.lastBlock.set(block); + + const fresh = blocks.lastBlock.isFresh(); + expect(fresh).to.be.false; + }); + + it('should return true for the block with the timestamp within constants.blockRecepitTimeOut', () => { + const block = _.cloneDeep(dummyBlock); + block.timestamp = generateFreshTimestamp(); + + blocks.lastBlock.set(block); + + const fresh = blocks.lastBlock.isFresh(); + expect(fresh).to.be.true; + }); }); }); @@ -49,7 +125,9 @@ describe('blocks', function () { expect(tracker.log.calledThrice).to.ok; expect(tracker.applied).to.equals(5); - expect(tracker.applyNext.bind(tracker)).to.throw('Cannot apply transaction over the limit: 5'); + expect(tracker.applyNext.bind(tracker)).to.throw( + 'Cannot apply transaction over the limit: 5' + ); }); }); }); diff --git a/test/unit/modules/blocks/verify.js b/test/unit/modules/blocks/verify.js index e0f99217..511fdab4 100644 --- a/test/unit/modules/blocks/verify.js +++ b/test/unit/modules/blocks/verify.js @@ -4,6 +4,7 @@ var expect = require('chai').expect; var modulesLoader = require('../../../common/initModule').modulesLoader; var BlockLogic = require('../../../../logic/block.js'); var exceptions = require('../../../../helpers/exceptions.js'); +const { removeQueuedJob } = require('../../../common/globalAfter.js'); var previousBlock = { blockSignature: 'a74cd53bebf9cf003cfd5fed8c053e1b64660e89a654078ff3341348145bbb0f34d1bde4a254b139ebae03117b346a2aab77fc8607eed9c7431db5eb4d4cbe0b', diff --git a/test/unit/modules/cache.js b/test/unit/modules/cache.js index a7fa1dee..137531b6 100644 --- a/test/unit/modules/cache.js +++ b/test/unit/modules/cache.js @@ -1,6 +1,5 @@ 'use strict'; -var node = require('./../../node.js'); var chai = require('chai'); var expect = require('chai').expect; var async = require('async'); @@ -49,7 +48,7 @@ describe('cache', function () { var cache; before(function (done) { - node.config.cacheEnabled = true; + modulesLoader.scope.config.cacheEnabled = true; done(); }); @@ -152,7 +151,7 @@ describe('cache', function () { expect(result).to.be.an('array'); expect(result).to.have.length(2); result.forEach(function (value) { - expect(value).to.eql(null); + expect(value).to.be.null; }); return callback(err, result); }); diff --git a/test/unit/modules/delegates.js b/test/unit/modules/delegates.js new file mode 100644 index 00000000..356f07ce --- /dev/null +++ b/test/unit/modules/delegates.js @@ -0,0 +1,405 @@ +'use strict'; + +const whyIsNodeRunning = require('why-is-node-running') +const { expect } = require('chai'); + +const { removeQueuedJob } = require('../../common/globalAfter.js'); +const { modulesLoader } = require('../../common/initModule.js'); +const { + testAccount, + invalidPublicKey, + invalidAddress, +} = require('../../common/stubs/account.js'); + +const constants = require('../../../helpers/constants.js'); +const Delegates = require('../../../modules/delegates.js'); + +const aDelegate = testAccount; + +const validGeneratorPubicKey = aDelegate.publicKey; + +describe('delegates', function () { + /** + * @type {Delegates} + */ + let delegates; + let modules; + + const dummyBlock = { + id: '9314232245035524467', + height: 1, + timestamp: 0, + }; + + before(() => { + delete require.cache[require.resolve('../../../modules/delegates.js')]; + }); + + before(function (done) { + modulesLoader.initAllModules((err, __modules) => { + if (err) { + return done(err); + } + + const blocks = __modules.blocks; + blocks.lastBlock.set(dummyBlock); + + modules = __modules; + delegates = __modules.delegates; + + done(); + }); + }); + + describe('isLoaded', () => { + it('should return false before delegates.onBind() was called', function () { + expect(delegates.isLoaded()).to.be.false; + }); + }); + + describe('onBind()', () => { + it('should initialize modules', () => { + delegates.onBind(modules); + expect(delegates.isLoaded()).to.be.true; + }); + }); + + describe('generateDelegateList', () => { + it('should generate delegate list with different positions at the following height', (done) => { + const height = 0; + delegates.generateDelegateList(height, (err, previousList) => { + expect(err).to.not.exist; + expect(previousList).not.to.be.empty; + + previousList.forEach((item) => expect(item).to.be.a.string); + + delegates.generateDelegateList(height + 1, (err, nextList) => { + expect(err).to.not.exist; + expect(previousList.length).to.equal(nextList.length); + expect(previousList).to.have.members(nextList); + expect(previousList).not.to.eql(nextList); + done(); + }); + }); + }); + }); + + describe('getDelegates', () => { + it('should throw when called with no parameters', () => { + expect(delegates.getDelegates).to.throw(); + }); + + it('should return all 101 delegates', (done) => { + delegates.getDelegates({}, {}, (err, response) => { + expect(response.delegates).to.be.an('array'); + expect(response.count).to.equal(101); + expect(err).not.to.exist; + done(); + }); + }); + }); + + describe('shared', () => { + describe('getDelegate', () => { + it('should return error when invalid username is provided', (done) => { + const body = { username: 1 }; + delegates.shared.getDelegate({ body }, (err, response) => { + expect(err).to.include('Expected type string'); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return error when invalid publicKey is provided', (done) => { + const body = {publicKey: invalidPublicKey} + delegates.shared.getDelegate({ body }, (err, response) => { + expect(err).to.include("Object didn't pass validation for format publicKey") + expect(response).not.to.exist; + done(); + }); + }); + + it('should return error when invalid address is provided', (done) => { + const body = {address: invalidAddress} + delegates.shared.getDelegate({ body }, (err, response) => { + expect(err).to.include("Object didn't pass validation for format address") + expect(response).not.to.exist; + done(); + }); + }); + + it('should find delegate matching the username', (done) => { + const body = { username: aDelegate.username }; + delegates.shared.getDelegate({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.property('delegate'); + + const { delegate } = response; + + expect(delegate.username).to.equal(aDelegate.username); + expect(delegate.publicKey).to.equal(aDelegate.publicKey); + expect(delegate.address).to.equal(aDelegate.address); + + done(); + }); + }); + + it('should find delegate matching the public key', (done) => { + const body = { publicKey: aDelegate.publicKey }; + delegates.shared.getDelegate({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.property('delegate'); + + const { delegate } = response; + + expect(delegate.username).to.equal(aDelegate.username); + expect(delegate.publicKey).to.equal(aDelegate.publicKey); + expect(delegate.address).to.equal(aDelegate.address); + + done(); + }); + }); + + // it('should find delegate matching the address', (done) => { + // const body = { address: aDelegate.address } + // delegates.shared.getDelegate({ body }, (err, response) => { + // expect(err).not.to.exist; + // expect(response).to.have.property('delegate'); + + // const { delegate } = response; + + // expect(delegate.username).to.equal(aDelegate.username); + // expect(delegate.publicKey).to.equal(aDelegate.publicKey); + // expect(delegate.address).to.equal(aDelegate.address); + + // done(); + // }); + // }); + }); + + describe('getNextForgers', () => { + it('should return next forgers for the current height', (done) => { + const body = {}; + delegates.shared.getNextForgers({ body }, (err, response) => { + const keys = [ + 'currentBlock', + 'currentBlockSlot', + 'currentSlot', + 'delegates', + ]; + + expect(err).not.to.exist; + expect(response).to.have.keys(keys); + + expect(response.currentBlock).to.equal(dummyBlock.height); + expect(response.currentBlockSlot).to.equal(0); + expect(response.currentSlot).to.be.greaterThan(0); + expect(response.delegates).not.to.be.empty; + done(); + }); + }); + + it('should limit delegates count in response', (done) => { + const body = { limit: 1 }; + delegates.shared.getNextForgers({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.delegates.length).to.equal(1); + done(); + }); + }); + }); + + describe('search', () => { + it('should throw when no "q" parameter is provided', (done) => { + const body = { orderBy: 'username' }; + delegates.shared.search({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.equal('Missing required property: q'); + done(); + }); + }); + + it('should throw error when invalid "orderBy" parameter is provided', (done) => { + const body = { q: 'market', orderBy: 'votesWeight' }; + delegates.shared.search({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.equal('Invalid sort field'); + done(); + }); + }); + + it('should return all delegates with "er" in its username', (done) => { + const body = { q: 'er' }; + delegates.shared.search({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.key('delegates'); + // todo + response.delegates.forEach((delegate) => + expect(delegate.username).to.include(body.q) + ); + done(); + }); + }); + + it('should find the delegate matching the query', (done) => { + const body = { q: 'market' }; + delegates.shared.search({ body }, (err, response) => { + expect(err).not.to.exist; + response.delegates.forEach((delegate) => + expect(delegate.username).to.include(body.q) + ); + done(); + }); + }); + }); + + describe('count', () => { + it('should return number of delegates in database', (done) => { + delegates.shared.count({}, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.key('count'); + expect(response.count).to.be.greaterThanOrEqual(101); + done(); + }); + }); + }); + + describe('getVoters', () => { + it('should throw error when no public key is provided', (done) => { + const body = {}; + delegates.shared.getVoters({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.equal('Missing required property: publicKey'); + done(); + }); + }); + + it('should return voters of the delegate matching the public key', (done) => { + const body = { publicKey: aDelegate.publicKey }; + delegates.shared.getVoters({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.key('accounts'); + expect(response.accounts).not.to.be.empty; + done(); + }); + }); + + it('should return voters of the delegate in descending order by balance', (done) => { + const body = { publicKey: aDelegate.publicKey }; + delegates.shared.getVoters({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.property('accounts').that.is.an("array").that.is + .not.empty; + + const isSorted = response.accounts.every((_, index, array) => { + if (index === 0) { + return true; + } + + return Number(array[index].balance) <= Number(array[index - 1].balance); + }); + expect(isSorted).to.be.true; + done(); + }); + }); + }); + + describe('getFee', () => { + it('should return the delegate registration fee', () => { + delegates.shared.getFee({}, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.key('fee'); + expect(response.fee).to.equal(constants.fees.delegate); + }); + }); + }); + + describe('getForgedByAccount', () => { + it('should return error when invalid generator public key is provided', (done) => { + const body = { generatorPublicKey: invalidPublicKey }; + delegates.shared.getForgedByAccount({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include( + "Object didn't pass validation for format publicKey" + ); + done(); + }); + }); + + it('should return error when invalid "start" parameter is provided', (done) => { + const body = { + generatorPublicKey: validGeneratorPubicKey, + start: 'string', + end: 61741820, + }; + + delegates.shared.getForgedByAccount({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include('Expected type integer but found type string'); + done(); + }); + }); + + it('should return error when invalid "end" parameter is provided', (done) => { + const body = { + generatorPublicKey: validGeneratorPubicKey, + start: 61741820, + end: 'string', + }; + + delegates.shared.getForgedByAccount({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.include('Expected type integer but found type string'); + done(); + }); + }); + + it('should return error when no accounts match the generator public key', (done) => { + const body = { + generatorPublicKey: + 'f4011a1360ac2769e066c789acaaeffa9d707690d4d3f6085a7d52756fbc30d1', + }; + + delegates.shared.getForgedByAccount({ body }, (err, response) => { + expect(response).not.to.exist; + expect(err).to.equal('Account not found'); + done(); + }); + }); + + it('should return delegate forging stats for the provided public key', (done) => { + const body = { generatorPublicKey: validGeneratorPubicKey }; + delegates.shared.getForgedByAccount({ body }, (err, response) => { + const keys = ['fees', 'rewards', 'forged']; + + expect(response).to.have.all.keys(keys); + expect(err).not.to.exist; + done(); + }); + }); + + it('should return delegate past forging stats with forged amount less than current', (done) => { + const body = { generatorPublicKey: validGeneratorPubicKey }; + delegates.shared.getForgedByAccount({ body }, (err, allTimeStats) => { + expect(err).not.to.exist; + + const allTimeForgedAmount = Number(allTimeStats.forged); + expect(allTimeForgedAmount).not.to.be.NaN; + + delegates.shared.getForgedByAccount( + { body: { ...body, start: 0, end: 61741820 } }, + (err, intervalStats) => { + expect(err).not.to.exist; + + const intervalForgedAmount = Number(intervalStats.forged); + expect(intervalForgedAmount).not.to.be.NaN; + + expect(intervalForgedAmount).to.be.lessThan(allTimeForgedAmount); + done(); + } + ); + }); + }); + }); + }); +}); diff --git a/test/unit/modules/node.js b/test/unit/modules/node.js new file mode 100644 index 00000000..fb85df4d --- /dev/null +++ b/test/unit/modules/node.js @@ -0,0 +1,110 @@ +'use strict'; + +const { expect } = require('chai'); +const semver = require('semver'); + +const { removeQueuedJob } = require('../../common/globalAfter.js'); +const { modulesLoader } = require('../../common/initModule.js'); +const { isHex } = require('../../common/assert.js'); + +const Node = require('../../../modules/node.js'); +const constants = require('../../../helpers/constants.js'); + +describe('node', function () { + /** + * @type {Node} + */ + let nodeModule; + let modules; + + const dummyBlock = { + id: '9314232245035524467', + height: 1, + timestamp: 0, + }; + + const library = { + lastCommit: '07757855c143e69e417da6e3918e0e57a3dd1864', + build: '', + }; + + before(function (done) { + modulesLoader.initAllModules((err, __modules) => { + if (err) { + return done(err); + } + + const blocks = __modules.blocks; + blocks.lastBlock.set(dummyBlock); + + modules = __modules; + + const scope = { + ...modulesLoader.scope, + ...library, + }; + + modulesLoader.initModuleWithDb( + Node, + (err, module) => { + if (err) { + return done(err); + } + + nodeModule = module; + done(); + }, + scope + ); + }); + }); + + describe('isLoaded()', () => { + it('should return false before delegates.onBind() was called', (done) => { + expect(nodeModule.isLoaded()).to.be.false; + done(); + }); + }); + + describe('onBind()', () => { + it('should initialize modules', (done) => { + nodeModule.onBind(modules); + expect(nodeModule.isLoaded()).to.be.true; + done(); + }); + }); + + describe('shared', () => { + describe('getStatus()', () => { + it('should return valid node status', (done) => { + nodeModule.shared.getStatus({}, (err, response) => { + expect(err).not.to.exist; + const keys = ['network', 'version', 'wsClient']; + expect(response).to.have.keys(keys); + + expect(isHex(response.network.broadhash)).to.be.true; + + expect(response.network.epoch).to.equal(constants.epochTime); + expect(response.network.height).to.equal(dummyBlock.height); + expect(response.network.fee).to.be.greaterThan(0); + expect(response.network.milestone).to.satisfy(Number.isInteger); + + const { nethash } = modulesLoader.scope.config; + expect(response.network.nethash).to.equal(nethash); + + expect(response.network.reward).to.satisfy(Number.isInteger); + expect(response.network.supply).to.satisfy(Number.isInteger); + + const versionKeys = ['build', 'commit', 'version']; + expect(response.version).to.have.all.keys(versionKeys); + expect(response.version.commit).to.equal(library.lastCommit); + expect(response.version.build).to.equal(library.build); + + expect(semver.valid(response.version.version)).not.to.be.null; + + done(); + }); + }); + }); + }); +}); diff --git a/test/unit/modules/peers.js b/test/unit/modules/peers.js index 8bf86fa9..7ed95b2c 100644 --- a/test/unit/modules/peers.js +++ b/test/unit/modules/peers.js @@ -8,7 +8,9 @@ var randomString = require('randomstring'); var _ = require('lodash'); var config = require('../../config.json'); -var randomPeer = require('../../common/objectStubs').randomPeer; + +const { removeQueuedJob } = require('../../common/globalAfter.js'); +const { validPeer } = require('../../common/stubs/peers.js'); var modulesLoader = require('../../common/initModule').modulesLoader; var currentPeers = []; @@ -27,7 +29,13 @@ describe('peers', function () { } before(function (done) { - modulesLoader.initAllModules(function (err, __modules) { + modulesLoader.initModules([ + { system: require('../../../modules/system.js') }, + { peers: require('../../../modules/peers.js') }, + { transport: require('../../../modules/transport.js') }, + ], [ + { 'peers': require('../../../logic/peers.js') } + ], { nonce: NONCE }, (err, __modules) => { if (err) { return done(err); } @@ -35,7 +43,7 @@ describe('peers', function () { modules = __modules; peers.onBind(__modules); done(); - }, { nonce: NONCE }); + }); }); beforeEach(function (done) { @@ -50,20 +58,20 @@ describe('peers', function () { var sandboxHelper = require('../../../helpers/sandbox.js'); sinon.stub(sandboxHelper, 'callMethod').returns(true); peers.sandboxApi(); - expect(sandboxHelper.callMethod.calledOnce).to.be.ok; + expect(sandboxHelper.callMethod.calledOnce).to.be.true; sandboxHelper.callMethod.restore(); }); }); describe('update', function () { it('should insert new peer', function (done) { - peers.update(randomPeer); + peers.update(validPeer); getPeers(function (err, __peers) { expect(currentPeers.length + 1).that.equals(__peers.length); currentPeers = __peers; var inserted = __peers.find(function (p) { - return p.ip + ':' + p.port === randomPeer.ip + ':' + randomPeer.port; + return p.ip + ':' + p.port === validPeer.ip + ':' + validPeer.port; }); expect(inserted).to.be.an('object'); expect(inserted).not.to.be.empty; @@ -72,7 +80,7 @@ describe('peers', function () { }); it('should update existing peer', function (done) { - var toUpdate = _.clone(randomPeer); + var toUpdate = _.clone(validPeer); toUpdate.height += 1; peers.update(toUpdate); @@ -80,18 +88,18 @@ describe('peers', function () { expect(currentPeers.length).that.equals(__peers.length); currentPeers = __peers; var updated = __peers.find(function (p) { - return p.ip + ':' + p.port === randomPeer.ip + ':' + randomPeer.port; + return p.ip + ':' + p.port === validPeer.ip + ':' + validPeer.port; }); expect(updated).to.be.an('object'); expect(updated).not.to.be.empty; - expect(updated.ip + ':' + updated.port).that.equals(randomPeer.ip + ':' + randomPeer.port); + expect(updated.ip + ':' + updated.port).that.equals(validPeer.ip + ':' + validPeer.port); expect(updated.height).that.equals(toUpdate.height); done(); }); }); it('should insert new peer if ip or port changed', function (done) { - var toUpdate = _.clone(randomPeer); + var toUpdate = _.clone(validPeer); toUpdate.port += 1; peers.update(toUpdate); @@ -169,7 +177,7 @@ describe('peers', function () { describe('remove', function () { before(function (done) { - peers.update(randomPeer); + peers.update(validPeer); done(); }); @@ -177,12 +185,12 @@ describe('peers', function () { getPeers(function (err, __peers) { currentPeers = __peers; var peerToRemove = currentPeers.find(function (p) { - return p.ip + ':' + p.port === randomPeer.ip + ':' + randomPeer.port; + return p.ip + ':' + p.port === validPeer.ip + ':' + validPeer.port; }); expect(peerToRemove).to.be.an('object').and.not.to.be.empty; expect(peerToRemove.state).that.equals(2); - expect(peers.remove(peerToRemove.ip, peerToRemove.port)).to.be.ok; + expect(peers.remove(peerToRemove.ip, peerToRemove.port)).to.be.true; getPeers(function (err, __peers) { expect(currentPeers.length - 1).that.equals(__peers.length); currentPeers = __peers; @@ -200,23 +208,23 @@ describe('peers', function () { var ip = require('neoip'); it('should accept peer with public ip', function () { - expect(peers.acceptable([randomPeer])).that.is.an('array').and.to.deep.equal([randomPeer]); + expect(peers.acceptable([validPeer])).that.is.an('array').and.to.deep.equal([validPeer]); }); it('should not accept peer with private ip', function () { - var privatePeer = _.clone(randomPeer); + var privatePeer = _.clone(validPeer); privatePeer.ip = '127.0.0.1'; expect(peers.acceptable([privatePeer])).that.is.an('array').and.to.be.empty; }); it('should not accept peer with adm-js-api os', function () { - var privatePeer = _.clone(randomPeer); + var privatePeer = _.clone(validPeer); privatePeer.os = 'adm-js-api'; expect(peers.acceptable([privatePeer])).that.is.an('array').and.to.be.empty; }); it('should not accept peer with host\'s nonce', function () { - var peer = _.clone(randomPeer); + var peer = _.clone(validPeer); peer.nonce = NONCE; expect(peers.acceptable([peer])).that.is.an('array').and.to.be.empty; }); @@ -240,15 +248,15 @@ describe('peers', function () { it('should accept peer with public ip', function (done) { sinon.stub(modules.transport, 'getFromPeer').callsArgWith(2, null, { success: true, - peer: randomPeer, + peer: validPeer, body: { - success: true, height: randomPeer.height, peers: [randomPeer] + success: true, height: validPeer.height, peers: [validPeer] } }); - peers.ping(randomPeer, function (err, res) { - expect(modules.transport.getFromPeer.calledOnce).to.be.ok; - expect(modules.transport.getFromPeer.calledWith(randomPeer)).to.be.ok; + peers.ping(validPeer, function (err, res) { + expect(modules.transport.getFromPeer.calledOnce).to.be.true; + expect(modules.transport.getFromPeer.calledWith(validPeer)).to.be.true; modules.transport.getFromPeer.restore(); done(); }); @@ -265,11 +273,11 @@ describe('peers', function () { var config = require('../../config.json'); var initialPeers = _.clone(config.peers.list); if (initialPeers.length === 0) { - config.peers.list.push(randomPeer); + config.peers.list.push(validPeer); } peers.onBlockchainReady(); setTimeout(function () { - expect(peers.discover.calledOnce).to.be.ok; + expect(peers.discover.calledOnce).to.be.true; peers.discover.restore(); done(); }, 1000); @@ -285,7 +293,7 @@ describe('peers', function () { sinon.stub(peers, 'discover').callsArgWith(0, null); peers.onPeersReady(); setTimeout(function () { - expect(peers.discover.calledOnce).to.be.ok; + expect(peers.discover.calledOnce).to.be.true; peers.discover.restore(); done(); }, 1000); diff --git a/test/unit/modules/rounds.js b/test/unit/modules/rounds.js index cc28973d..69f5ca0c 100644 --- a/test/unit/modules/rounds.js +++ b/test/unit/modules/rounds.js @@ -1,9 +1,8 @@ 'use strict'; -var chai = require('chai'); +const { expect } = require('chai'); var express = require('express'); var _ = require('lodash'); -var node = require('../../node.js'); var Rounds = require('../../../modules/rounds.js'); var modulesLoader = require('../../common/initModule').modulesLoader; @@ -22,16 +21,16 @@ describe('rounds', function () { describe('calc', function () { it('should calculate round number from given block height', function () { - node.expect(rounds.calc(100)).equal(1); - node.expect(rounds.calc(200)).equal(2); - node.expect(rounds.calc(303)).equal(3); - node.expect(rounds.calc(304)).equal(4); + expect(rounds.calc(100)).equal(1); + expect(rounds.calc(200)).equal(2); + expect(rounds.calc(303)).equal(3); + expect(rounds.calc(304)).equal(4); }); it('should calculate round number from Number.MAX_VALUE', function () { var res = rounds.calc(Number.MAX_VALUE); - node.expect(_.isNumber(res)).to.be.ok; - node.expect(res).to.be.below(Number.MAX_VALUE); + expect(_.isNumber(res)).to.be.true; + expect(res).to.be.below(Number.MAX_VALUE); }); }); }); diff --git a/test/unit/modules/transactions.js b/test/unit/modules/transactions.js new file mode 100644 index 00000000..3034ad7e --- /dev/null +++ b/test/unit/modules/transactions.js @@ -0,0 +1,915 @@ +'use strict'; + +const { expect } = require('chai'); +const sinon = require('sinon'); + +const Transactions = require('../../../modules/transactions.js'); +const Transaction = require('../../../logic/transaction.js'); + +const Vote = require('../../../logic/vote.js'); +const Transfer = require('../../../logic/transfer.js'); +const Delegate = require('../../../logic/delegate.js'); +const Signature = require('../../../logic/signature.js'); +const Multisignature = require('../../../logic/multisignature.js'); +const InTransfer = require('../../../logic/inTransfer.js'); +const OutTransfer = require('../../../logic/outTransfer.js'); +const Chat = require('../../../logic/chat.js'); +const State = require('../../../logic/state.js'); + +const { modulesLoader } = require('../../common/initModule.js'); +const transactionTypes = require('../../../helpers/transactionTypes.js'); + +const { removeQueuedJob } = require('../../common/globalAfter.js'); + +const { + testAccount, + genesisAccount, + nonExistingAddress, +} = require('../../common/stubs/account.js'); +const { + unconfirmedTransaction, + nonExistingTransactionId, + unconfirmedTransactionId, + existingTransaction, + existingTransactionWithAsset, +} = require('../../common/stubs/transactions.js'); +const { genesisBlockId } = require('../../common/stubs/blocks.js'); + +describe('transactions', function () { + /** + * @type {Transactions} + */ + let transactions; + let modules; + + before(() => { + delete require.cache[require.resolve('../../../modules/transactions.js')]; + }); + + before(function (done) { + modulesLoader.initLogicWithDb(Transaction, (err, transaction) => { + if (err) { + throw err; + } + + transaction.attachAssetType(transactionTypes.VOTE, new Vote()); + transaction.attachAssetType(transactionTypes.SEND, new Transfer()); + transaction.attachAssetType(transactionTypes.DELEGATE, new Delegate()); + transaction.attachAssetType(transactionTypes.SIGNATURE, new Signature()); + transaction.attachAssetType(transactionTypes.MULTI, new Multisignature()); + transaction.attachAssetType( + transactionTypes.IN_TRANSFER, + new InTransfer() + ); + transaction.attachAssetType( + transactionTypes.OUT_TRANSFER, + new OutTransfer() + ); + transaction.attachAssetType(transactionTypes.CHAT_MESSAGE, new Chat()); + transaction.attachAssetType(transactionTypes.STATE, new State()); + + transaction.checkBalance = sinon.fake.returns({ + exceeded: false, + error: null + }) + + modulesLoader.initAllModules( + (err, __modules) => { + if (err) { + return done(err); + } + + modules = __modules; + transactions = __modules.transactions; + + done(); + }, + { logic: { transaction } } + ); + }); + }); + + describe('isLoaded', () => { + it('should return false before transactions.onBind() was called', () => { + expect(transactions.isLoaded()).to.be.false; + }); + }); + + describe('onBind()', () => { + it('should initialize modules', () => { + transactions.onBind(modules); + expect(transactions.isLoaded()).to.be.true; + }); + }); + + describe('shared', () => { + describe('getTransactions', () => { + const getTransactionsKeys = ['transactions', 'count']; + + it('should find the transactions matching the block id', (done) => { + const body = { blockId: genesisBlockId }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + response.transactions.forEach((transaction) => + expect(transaction.blockId).to.equal(body.blockId) + ); + + done(); + }); + }); + + it('should return error for invalid "blockId" type', (done) => { + const body = { blockId: 'abc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include("Object didn't pass validation for format id"); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should find transactions matching the "fromHeight" and "toHeight" parameters', (done) => { + const body = { fromHeight: 1, 'and:toHeight': 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => + expect(transaction.height).to.be.within( + body.fromHeight, + body['and:toHeight'] + ) + ); + + done(); + }); + }); + + it('should find transactions matching the "minAmount" and "maxAmount" parameters', (done) => { + const minAmount = 490000000000000; + const maxAmount = 2000000000000000; + const body = { minAmount, 'and:maxAmount': maxAmount }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).length.to.be.greaterThanOrEqual(2); + response.transactions.forEach((transaction) => + expect(transaction.amount).to.be.within(minAmount, maxAmount) + ); + + done(); + }); + }); + + it('should find transactions matching the "senderId"', (done) => { + const body = { senderId: genesisAccount.address }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).length.to.be.greaterThanOrEqual(3); + response.transactions.forEach((transaction) => + expect(transaction.senderId).to.equal(body.senderId) + ); + + done(); + }); + }); + + it('should find transactions matching one of the "senderIds"', (done) => { + const body = { + senderIds: [testAccount.address, genesisAccount.address], + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + response.transactions.forEach((transaction) => + expect(body.senderIds).to.include(transaction.senderId) + ); + + done(); + }); + }); + + it('should find transactions matching the "recipientId"', (done) => { + const body = { recipientId: testAccount.address }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => + expect(transaction.recipientId).to.equal(body.recipientId) + ); + + done(); + }); + }); + + it('should find transactions matching one of the "recipientIds"', (done) => { + const body = { + recipientIds: [testAccount.address, 'U9781760580710719871'], + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).length.to.be.greaterThanOrEqual(2); + response.transactions.forEach((transaction) => + expect(body.recipientIds).to.include(transaction.recipientId) + ); + + done(); + }); + }); + + it('should find transactions matching the "senderPublicKey"', (done) => { + const body = { senderPublicKey: genesisAccount.publicKey }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => + expect(transaction.senderPublicKey).to.equal(body.senderPublicKey) + ); + + done(); + }); + }); + + it('should find transactions matching the "recipientPublicKey"', (done) => { + const body = { recipientPublicKey: testAccount.publicKey }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => + expect(transaction.recipientPublicKey).to.equal( + body.recipientPublicKey + ) + ); + + done(); + }); + }); + + it('should find transactions matching the "type"', (done) => { + const body = { type: transactionTypes.VOTE }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => + expect(transaction.type).to.equal(body.type) + ); + + done(); + }); + }); + + it('should find transactions matching one of the "types"', (done) => { + const types = [transactionTypes.CHAT_MESSAGE, transactionTypes.VOTE]; + + const body = { + types: types.join(','), + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + response.transactions.forEach((transaction) => + expect(types.map(Number)).to.include(transaction.type) + ); + + done(); + }); + }); + + it('should return an empty result for non-existing address as senderId', (done) => { + const body = { senderId: nonExistingAddress }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).to.be.an('array').that.is.empty; + + done(); + }); + }); + + it('should return error for invalid parameters', (done) => { + const body = { minAmount: 'invalid' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include('Expected type integer'); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should return empty result for conflicting filters', (done) => { + const body = { fromHeight: 100, 'and:toHeight': 1 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).to.be.empty; + + done(); + }); + }); + + it('should support pagination', (done) => { + const body = { senderId: testAccount.address, limit: 10, offset: 5 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).length.to.be.at.most(5); + + done(); + }); + }); + + it('should find transactions with OR logic by default (blockId OR senderId)', (done) => { + const body = { blockId: genesisBlockId, senderId: testAccount.address }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach( + (transaction) => + expect( + transaction.blockId === body.blockId || + transaction.senderId === body.senderId + ).to.be.true + ); + + done(); + }); + }); + + it('should find transactions with AND logic (blockId AND senderId)', (done) => { + const body = { + blockId: genesisBlockId, + 'and:senderId': testAccount.address, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect(transaction.blockId).to.equal(body.blockId); + expect(transaction.senderId).to.equal(testAccount.address); + }); + + done(); + }); + }); + + it('should find transactions with OR logic across ranges (toHeight OR minAmount)', (done) => { + const body = { toHeight: 1, minAmount: 1000000 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach( + (transaction) => + expect( + transaction.height <= body.toHeight || + transaction.amount >= body.minAmount + ).to.be.true + ); + + done(); + }); + }); + + it('should find transactions with AND logic across ranges (fromHeight AND toHeight)', (done) => { + const body = { toHeight: 100, 'and:fromHeight': 1 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect(transaction.height).to.be.within(1, 100); + }); + + done(); + }); + }); + + it('should ignore "or" from the first parameter', (done) => { + const body = { 'or:fromHeight': 1, 'and:toHeight': 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect(transaction.height).to.be.within(1, 100); + }); + + done(); + }); + }); + + it('should return error for an invalid prefix', (done) => { + const body = { 'not:fromHeight': 2, 'nor:toHeight': 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include('Incorrect condition'); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should return error for multiple prefixes', (done) => { + const body = { 'and:or:fromHeight': 2, toHeight: 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include('Invalid parameter supplied'); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should return error for non existing parameter', (done) => { + const body = { maxAura: 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include('Parameter is not supported'); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should combine senderId AND recipientId with OR for type', (done) => { + const body = { + senderId: testAccount.address, + 'and:recipientId': testAccount.address, + type: transactionTypes.VOTE, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect( + (transaction.senderId === body.senderId && + transaction.recipientId === body['and:recipientId']) || + transaction.type === body.type + ).to.be.true; + }); + + done(); + }); + }); + + it('should handle complex combinations (minAmount AND maxAmount AND type)', (done) => { + const body = { + minAmount: 100000000, + 'and:maxAmount': 500000000000000, + 'and:type': transactionTypes.SEND, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect( + (transaction.amount >= body.minAmount && + transaction.amount <= body['and:maxAmount']) || + transaction.type === body.type + ).to.be.true; + }); + + done(); + }); + }); + + it('should handle nested AND conditions with recipientPublicKey', (done) => { + const body = { + recipientPublicKey: testAccount.publicKey, + 'and:toHeight': 100, + 'and:fromHeight': 1, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect(transaction.recipientPublicKey).to.equal( + body.recipientPublicKey + ); + expect(transaction.height).to.be.within(1, 100); + }); + + done(); + }); + }); + + it('should find transactions with OR logic for multiple recipientIds', (done) => { + const body = { + recipientIds: [testAccount.address, genesisAccount.address], + minAmount: 50000000, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + + expect(response.transactions).not.to.be.empty; + response.transactions.forEach((transaction) => { + expect( + body.recipientIds.includes(transaction.recipientId) || + transaction.amount >= body.minAmount + ).to.be.true; + }); + + done(); + }); + }); + + it('should return empty response when no transaction matches complex filters', (done) => { + const body = { + blockId: genesisBlockId, + 'and:senderId': nonExistingAddress, + 'and:type': transactionTypes.VOTE, + }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).to.be.an('array').that.is.empty; + + done(); + }); + }); + + it('should sort transactions by height in descending order', (done) => { + const body = { orderBy: 'height:desc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + const heights = response.transactions.map( + (transaction) => transaction.height + ); + expect(heights).to.eql([...heights].sort((a, b) => b - a)); + + done(); + }); + }); + + it('should sort transactions by height in ascending order', (done) => { + const body = { orderBy: 'height:asc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + const heights = response.transactions.map( + (transaction) => transaction.height + ); + expect(heights).to.eql([...heights].sort((a, b) => a - b)); + + done(); + }); + }); + + it('should sort transactions by amount in descending order', (done) => { + const body = { orderBy: 'amount:desc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + const amounts = response.transactions.map( + (transaction) => transaction.amount + ); + expect(amounts).to.eql([...amounts].sort((a, b) => b - a)); + + done(); + }); + }); + + it('should sort transactions by amount in ascending order', (done) => { + const body = { orderBy: 'amount:asc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + const amounts = response.transactions.map( + (transaction) => transaction.amount + ); + expect(amounts).to.eql([...amounts].sort((a, b) => a - b)); + + done(); + }); + }); + + it('should sort transactions by type in ascending order', (done) => { + const body = { orderBy: 'type:asc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + const types = response.transactions.map( + (transaction) => transaction.type + ); + expect(types).to.eql([...types].sort((a, b) => a - b)); + + done(); + }); + }); + + it('should handle invalid sort field gracefully', (done) => { + const body = { orderBy: 'nonexistentField:asc' }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).to.include('Invalid sort field'); + expect(response).not.to.exist; + + done(); + }); + }); + + it('should sort transactions with filters (height desc with minAmount)', (done) => { + const body = { orderBy: 'height:desc', minAmount: 100 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).not.to.be.empty; + + response.transactions.forEach((transaction) => + expect(transaction.amount).to.be.at.least(100) + ); + + const heights = response.transactions.map( + (transaction) => transaction.height + ); + expect(heights).to.eql([...heights].sort((a, b) => b - a)); + + done(); + }); + }); + + it('should sort transactions with pagination (amount asc, limit 5, offset 10)', (done) => { + const body = { orderBy: 'amount:asc', limit: 5, offset: 10 }; + + transactions.shared.getTransactions({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsKeys); + expect(response.transactions).length.to.be.at.most(5); + + const amounts = response.transactions.map( + (transaction) => transaction.amount + ); + expect(amounts).to.eql([...amounts].sort((a, b) => a - b)); + + done(); + }); + }); + }); + + describe('getTransaction', () => { + it('should return error with no parameters', (done) => { + const body = {}; + transactions.shared.getTransaction({ body }, (err, response) => { + expect(err).to.equal('Missing required property: id'); + expect(response).not.to.exist; + done(); + }); + }); + + it('should return transaction without asset by id', (done) => { + const body = { id: existingTransactionWithAsset.id }; + transactions.shared.getTransaction({ body }, (err, response) => { + expect(err).not.to.exist; + + expect(response.transaction).to.deep.include(existingTransaction); + done(); + }); + }); + + it('should return transaction with asset by id', (done) => { + const body = { id: existingTransactionWithAsset.id, returnAsset: 1 }; + transactions.shared.getTransaction({ body }, (err, response) => { + expect(err).not.to.exist; + expect(response.transaction).to.deep.include( + existingTransactionWithAsset + ); + done(); + }); + }); + + it('should return error for non-existing transaction id', (done) => { + const body = { id: nonExistingTransactionId }; + transactions.shared.getTransaction({ body }, (err, response) => { + expect(err).to.equal('Transaction not found'); + expect(response).not.to.exist; + done(); + }); + }); + }); + + describe('getTransactionsCount', () => { + const getTransactionsCountKeys = [ + 'confirmed', + 'multisignature', + 'unconfirmed', + 'queued', + ]; + + it('should return valid object', (done) => { + transactions.shared.getTransactionsCount({}, (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getTransactionsCountKeys); + expect(response.confirmed).to.be.above(0); + expect(response.multisignature).to.equal(0); + expect(response.unconfirmed).to.be.a('number'); + expect(response.queued).to.be.a('number'); + + done(); + }); + }); + }); + + describe('transactions in pool', () => { + beforeEach((done) => { + transactions.receiveTransactions([unconfirmedTransaction], true, done); + }); + + afterEach(() => { + transactions.removeUnconfirmedTransaction(unconfirmedTransactionId); + expect(transactions.transactionInPool(unconfirmedTransactionId)).to.be + .false; + }); + + describe('queued transactions', () => { + describe('getQueuedTransactions', () => { + const getQueuedTransactionsKeys = ['transactions', 'count']; + + it('should return queued transactions', (done) => { + transactions.shared.getQueuedTransactions( + { body: {} }, + (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys(getQueuedTransactionsKeys); + expect(response.count).to.be.a('number'); + expect(response.transactions).to.be.an('array'); + expect(response.transactions).not.to.be.empty; + + response.transactions.forEach((transaction) => { + expect(transaction.id).to.be.a.string; + expect(transaction.receivedAt).to.be.a.string; + expect(transaction.blockId).not.to.exist; + expect(transaction.height).not.to.exist; + }); + + done(); + } + ); + }); + }); + + describe('getQueuedTransactions', () => { + it('should return error with no "id" parameter', (done) => { + transactions.shared.getQueuedTransaction( + { body: {} }, + (err, response) => { + expect(err).to.equal('Missing required property: id'); + expect(response).not.to.exist; + + done(); + } + ); + }); + + it('should return queued transaction', (done) => { + const body = { id: unconfirmedTransactionId }; + transactions.shared.getQueuedTransaction( + { body }, + (err, response) => { + expect(err).not.to.exist; + expect(response.transaction).to.eql(unconfirmedTransaction); + + done(); + } + ); + }); + }); + }); + + describe('unconfirmed transactions', () => { + beforeEach((done) => { + transactions.fillPool(done); + }); + + describe('getUnconfirmedTransactions', () => { + const getUnconfirmedTransactionsKeys = ['transactions', 'count']; + + it('should return unconfirmed transactions', (done) => { + transactions.shared.getUnconfirmedTransactions( + { body: {} }, + (err, response) => { + expect(err).not.to.exist; + expect(response).to.have.all.keys( + getUnconfirmedTransactionsKeys + ); + expect(response.count).to.be.a('number'); + expect(response.transactions).to.be.an('array'); + expect(response.transactions).not.to.be.empty; + + response.transactions.forEach((transaction) => { + expect(transaction.id).to.be.a.string; + expect(transaction.receivedAt).to.be.a.string; + expect(transaction.blockId).not.to.exist; + expect(transaction.height).not.to.exist; + }); + + done(); + } + ); + }); + }); + + describe('getUnconfirmedTransaction', () => { + it('should return error with no "id" parameter', (done) => { + transactions.shared.getUnconfirmedTransaction( + { body: {} }, + (err, response) => { + expect(err).to.equal('Missing required property: id'); + expect(response).not.to.exist; + + done(); + } + ); + }); + + it('should return unconfirmed transaction', (done) => { + const body = { id: unconfirmedTransactionId }; + transactions.shared.getUnconfirmedTransaction( + { body }, + (err, response) => { + expect(err).not.to.exist; + expect(response.transaction).to.eql(unconfirmedTransaction); + + done(); + } + ); + }); + }); + }); + }); + }); +}); diff --git a/test/unit/schema/multisignatures.js b/test/unit/schema/multisignatures.js index 52a90b7b..8938f551 100644 --- a/test/unit/schema/multisignatures.js +++ b/test/unit/schema/multisignatures.js @@ -1,4 +1,4 @@ -var node = require('../../node.js'); +const { randomAccount } = require('../../common/utils.js'); var ZSchema = require('../../../helpers/z_schema.js'); var schema = require('../../../schema/multisignatures.js'); @@ -27,13 +27,13 @@ describe('multisignatures', function () { var testBody; beforeEach(function () { - var account = node.randomAccount(); + var account = randomAccount(); testBody = { secret: account.password, publicKey: account.publicKeyHex, min: 2, lifetime: 1, - keysgroup: Array.apply(null, Array(4)).map(function () { return '+' + node.randomAccount().publicKey; }) + keysgroup: Array.apply(null, Array(4)).map(function () { return '+' + randomAccount().publicKey; }) }; }); @@ -81,7 +81,7 @@ describe('multisignatures', function () { }); it('should return error when keysgroup length is greater than maximum acceptable length', function () { - testBody.keysgroup = Array.apply(null, Array(16)).map(function () { return node.randomAccount().publicKey; }); + testBody.keysgroup = Array.apply(null, Array(16)).map(function () { return randomAccount().publicKey; }); validator.validate(testBody, schema.addMultisignature); expect(validator.getLastErrors().map(function (e) { return e.message; diff --git a/test/unit/schema/transactions.js b/test/unit/schema/transactions.js index 519f88a9..03d6cd44 100644 --- a/test/unit/schema/transactions.js +++ b/test/unit/schema/transactions.js @@ -1,6 +1,7 @@ var expect = require('chai').expect; -var node = require('../../node.js'); +const { testAccount, delegateAccount } = require('../../common/stubs/account.js') + var ZSchema = require('../../../helpers/z_schema.js'); var schema = require('../../../schema/transactions.js'); @@ -36,17 +37,17 @@ describe('transactions', function () { testBody = { blockId: '1465651642158264047', type: 0, - senderId: node.testSender.address, - senderPublicKey: node.testSender.publicKey, - ownerPublicKey: node.testSender.publicKey, - ownerAddress: node.testSender.address, - recipientId: node.kindDelegate.address, + senderId: testAccount.address, + senderPublicKey: testAccount.publicKey, + ownerPublicKey: testAccount.publicKey, + ownerAddress: testAccount.address, + recipientId: delegateAccount.address, amount: 100, fee: 20, - senderPublicKeys: [node.testSender.publicKey, node.kindDelegate.publicKey], - recipientPublicKeys: [node.testSender.publicKey, node.kindDelegate.publicKey], - senderIds: [node.testSender.address, node.kindDelegate.address], - recipientIds: [node.testSender.address, node.kindDelegate.address], + senderPublicKeys: [testAccount.publicKey, delegateAccount.publicKey], + recipientPublicKeys: [testAccount.publicKey, delegateAccount.publicKey], + senderIds: [testAccount.address, delegateAccount.address], + recipientIds: [testAccount.address, delegateAccount.address], fromHeight: 1, toHeight: 2, fromTimestamp: 0, diff --git a/test/unit/sql/blockRewards.js b/test/unit/sql/blockRewards.js index a0123604..5f27d2f5 100644 --- a/test/unit/sql/blockRewards.js +++ b/test/unit/sql/blockRewards.js @@ -58,7 +58,7 @@ function calcSupply_test (height_start, height_end, expected_reward, done) { expect(rows).to.be.an('array'); expect(rows.length).to.equal(1); expect(rows[0]).to.be.an('object'); - expect(rows[0].result).to.equal(true); + expect(rows[0].result).to.be.true; done(); }).catch(function (err) { done(err); @@ -70,7 +70,7 @@ function calcSupply_test_fail (height_start, height_end, expected_reward, done) expect(rows).to.be.an('array'); expect(rows.length).to.equal(1); expect(rows[0]).to.be.an('object'); - expect(rows[0].result).to.equal(false); + expect(rows[0].result).to.be.false; done(); }).catch(function (err) { done(err);