mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-05 21:35:49 +00:00
Add test runner for RippleAPI, begin to break up large test file
This commit is contained in:
@@ -44,7 +44,6 @@
|
||||
"mocha": "6.2.0",
|
||||
"mocha-junit-reporter": "^1.9.1",
|
||||
"nyc": "^14.1.1",
|
||||
"source-map-support": "0.5.12",
|
||||
"ts-node": "^8.4.1",
|
||||
"typescript": "^3.6.4",
|
||||
"webpack": "^4.30.0",
|
||||
@@ -63,6 +62,7 @@
|
||||
"docgen": "node --harmony scripts/build_docs.js",
|
||||
"prepublish": "yarn clean && yarn build",
|
||||
"test": "TS_NODE_PROJECT=src/tsconfig.json nyc mocha --exit",
|
||||
"test:watch": "TS_NODE_PROJECT=src/tsconfig.json mocha --watch --reporter dot",
|
||||
"lint": "eslint src/**/*.ts 'test/*-test.{ts,js}'",
|
||||
"perf": "./scripts/perf_test.sh",
|
||||
"start": "node scripts/http.js"
|
||||
|
||||
@@ -13,7 +13,7 @@ function isValidSecret(secret: string): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
function dropsToXrp(drops: string | BigNumber): string {
|
||||
function dropsToXrp(drops: BigNumber.Value): string {
|
||||
if (typeof drops === 'string') {
|
||||
if (!drops.match(/^-?[0-9]*\.?[0-9]*$/)) {
|
||||
throw new ValidationError(`dropsToXrp: invalid value '${drops}',` +
|
||||
@@ -47,7 +47,7 @@ function dropsToXrp(drops: string | BigNumber): string {
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString(10)
|
||||
}
|
||||
|
||||
function xrpToDrops(xrp: string | BigNumber): string {
|
||||
function xrpToDrops(xrp: BigNumber.Value): string {
|
||||
if (typeof xrp === 'string') {
|
||||
if (!xrp.match(/^-?[0-9]*\.?[0-9]*$/)) {
|
||||
throw new ValidationError(`xrpToDrops: invalid value '${xrp}',` +
|
||||
|
||||
476
test/api-test.ts
476
test/api-test.ts
@@ -31,7 +31,7 @@ function checkResult(expected, schemaName, response) {
|
||||
assert(response.tx_json);
|
||||
assert.deepEqual(response.tx_json, expected.tx_json);
|
||||
}
|
||||
assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON'), _.omit(response, 'tx_json'), _.omit(response, 'tx_json'));
|
||||
assert.deepEqual(_.omit(response, ['txJSON', 'tx_json']), _.omit(expected, ['txJSON', 'tx_json']))
|
||||
if (schemaName) {
|
||||
schemaValidator.schemaValidate(schemaName, response);
|
||||
}
|
||||
@@ -50,110 +50,6 @@ describe('RippleAPI', function () {
|
||||
assert.strictEqual(error.inspect(), '[RippleError(mess, { data: 1 })]');
|
||||
});
|
||||
|
||||
describe('xrpToDrops', function () {
|
||||
it('works with a typical amount', function () {
|
||||
const drops = this.api.xrpToDrops('2')
|
||||
assert.strictEqual(drops, '2000000', '2 XRP equals 2 million drops')
|
||||
})
|
||||
|
||||
it('works with fractions', function () {
|
||||
let drops = this.api.xrpToDrops('3.456789')
|
||||
assert.strictEqual(drops, '3456789', '3.456789 XRP equals 3,456,789 drops')
|
||||
|
||||
drops = this.api.xrpToDrops('3.400000')
|
||||
assert.strictEqual(drops, '3400000', '3.400000 XRP equals 3,400,000 drops')
|
||||
|
||||
drops = this.api.xrpToDrops('0.000001')
|
||||
assert.strictEqual(drops, '1', '0.000001 XRP equals 1 drop')
|
||||
|
||||
drops = this.api.xrpToDrops('0.0000010')
|
||||
assert.strictEqual(drops, '1', '0.0000010 XRP equals 1 drop')
|
||||
})
|
||||
|
||||
it('works with zero', function () {
|
||||
let drops = this.api.xrpToDrops('0')
|
||||
assert.strictEqual(drops, '0', '0 XRP equals 0 drops')
|
||||
|
||||
// negative zero is equivalent to zero
|
||||
drops = this.api.xrpToDrops('-0')
|
||||
assert.strictEqual(drops, '0', '-0 XRP equals 0 drops')
|
||||
|
||||
drops = this.api.xrpToDrops('0.000000')
|
||||
assert.strictEqual(drops, '0', '0.000000 XRP equals 0 drops')
|
||||
|
||||
drops = this.api.xrpToDrops('0.0000000')
|
||||
assert.strictEqual(drops, '0', '0.0000000 XRP equals 0 drops')
|
||||
})
|
||||
|
||||
it('works with a negative value', function () {
|
||||
const drops = this.api.xrpToDrops('-2')
|
||||
assert.strictEqual(drops, '-2000000', '-2 XRP equals -2 million drops')
|
||||
})
|
||||
|
||||
it('works with a value ending with a decimal point', function () {
|
||||
let drops = this.api.xrpToDrops('2.')
|
||||
assert.strictEqual(drops, '2000000', '2. XRP equals 2000000 drops')
|
||||
|
||||
drops = this.api.xrpToDrops('-2.')
|
||||
assert.strictEqual(drops, '-2000000', '-2. XRP equals -2000000 drops')
|
||||
})
|
||||
|
||||
it('works with BigNumber objects', function () {
|
||||
let drops = this.api.xrpToDrops(new BigNumber(2))
|
||||
assert.strictEqual(drops, '2000000', '(BigNumber) 2 XRP equals 2 million drops')
|
||||
|
||||
drops = this.api.xrpToDrops(new BigNumber(-2))
|
||||
assert.strictEqual(drops, '-2000000', '(BigNumber) -2 XRP equals -2 million drops')
|
||||
})
|
||||
|
||||
it('works with a number', function() {
|
||||
// This is not recommended. Use strings or BigNumber objects to avoid precision errors.
|
||||
|
||||
let drops = this.api.xrpToDrops(2)
|
||||
assert.strictEqual(drops, '2000000', '(number) 2 XRP equals 2 million drops')
|
||||
|
||||
drops = this.api.xrpToDrops(-2)
|
||||
assert.strictEqual(drops, '-2000000', '(number) -2 XRP equals -2 million drops')
|
||||
})
|
||||
|
||||
it('throws with an amount with too many decimal places', function () {
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('1.1234567')
|
||||
}, /has too many decimal places/)
|
||||
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('0.0000001')
|
||||
}, /has too many decimal places/)
|
||||
})
|
||||
|
||||
it('throws with an invalid value', function () {
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('FOO')
|
||||
}, /invalid value/)
|
||||
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('1e-7')
|
||||
}, /invalid value/)
|
||||
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('2,0')
|
||||
}, /invalid value/)
|
||||
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('.')
|
||||
}, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./)
|
||||
})
|
||||
|
||||
it('throws with an amount more than one decimal point', function () {
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('1.0.0')
|
||||
}, /xrpToDrops: invalid value '1\.0\.0'/)
|
||||
|
||||
assert.throws(() => {
|
||||
this.api.xrpToDrops('...')
|
||||
}, /xrpToDrops: invalid value '\.\.\.'/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('dropsToXrp', function () {
|
||||
it('works with a typical amount', function () {
|
||||
@@ -1684,159 +1580,6 @@ describe('RippleAPI', function () {
|
||||
}
|
||||
});
|
||||
|
||||
it('prepareSettings', function () {
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings.domain, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flags, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - no maxLedgerVersion', function () {
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings.domain, { maxLedgerVersion: null }).then(
|
||||
_.partial(checkResult, responses.prepareSettings.noMaxLedgerVersion,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - no instructions', function () {
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings.domain).then(
|
||||
_.partial(
|
||||
checkResult,
|
||||
responses.prepareSettings.noInstructions,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - regularKey', function () {
|
||||
const regularKey = { regularKey: 'rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD' };
|
||||
return this.api.prepareSettings(address, regularKey, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.regularKey, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - remove regularKey', function () {
|
||||
const regularKey = { regularKey: null };
|
||||
return this.api.prepareSettings(address, regularKey, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.removeRegularKey,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - flag set', function () {
|
||||
const settings = { requireDestinationTag: true };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flagSet, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - flag clear', function () {
|
||||
const settings = { requireDestinationTag: false };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flagClear, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - set depositAuth flag', function () {
|
||||
const settings = { depositAuth: true };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flagSetDepositAuth, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - clear depositAuth flag', function () {
|
||||
const settings = { depositAuth: false };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flagClearDepositAuth, 'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - integer field clear', function () {
|
||||
const settings = { transferRate: null };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset)
|
||||
.then(data => {
|
||||
assert(data);
|
||||
assert.strictEqual(JSON.parse(data.txJSON).TransferRate, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('prepareSettings - set transferRate', function () {
|
||||
const settings = { transferRate: 1 };
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.setTransferRate,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - set signers', function () {
|
||||
const settings = requests.prepareSettings.signers.normal;
|
||||
return this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(
|
||||
_.partial(checkResult, responses.prepareSettings.signers,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - signers no threshold', function (done) {
|
||||
const settings = requests.prepareSettings.signers.noThreshold;
|
||||
try {
|
||||
this.api.prepareSettings(address, settings, instructionsWithMaxLedgerVersionOffset).then(prepared => {
|
||||
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
|
||||
}).catch(err => {
|
||||
assert.strictEqual(err.name, 'ValidationError');
|
||||
assert.strictEqual(err.message, 'instance.settings.signers requires property "threshold"');
|
||||
done();
|
||||
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
|
||||
} catch (err) {
|
||||
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
|
||||
}
|
||||
});
|
||||
|
||||
it('prepareSettings - signers no weights', function () {
|
||||
const settings = requests.prepareSettings.signers.noWeights;
|
||||
const localInstructions = _.defaults({
|
||||
signersCount: 1
|
||||
}, instructionsWithMaxLedgerVersionOffset);
|
||||
return this.api.prepareSettings(
|
||||
address, settings, localInstructions).then(
|
||||
_.partial(checkResult, responses.prepareSettings.noWeights,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - fee for multisign', function () {
|
||||
const localInstructions = _.defaults({
|
||||
signersCount: 4
|
||||
}, instructionsWithMaxLedgerVersionOffset);
|
||||
return this.api.prepareSettings(
|
||||
address, requests.prepareSettings.domain, localInstructions).then(
|
||||
_.partial(checkResult, responses.prepareSettings.flagsMultisign,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - no signer list', function () {
|
||||
const settings = requests.prepareSettings.noSignerEntries;
|
||||
const localInstructions = _.defaults({
|
||||
signersCount: 1
|
||||
}, instructionsWithMaxLedgerVersionOffset);
|
||||
return this.api.prepareSettings(
|
||||
address, settings, localInstructions).then(
|
||||
_.partial(checkResult, responses.prepareSettings.noSignerList,
|
||||
'prepare'));
|
||||
});
|
||||
|
||||
it('prepareSettings - invalid', function (done) {
|
||||
// domain must be a string
|
||||
const settings = Object.assign({},
|
||||
requests.prepareSettings.domain,
|
||||
{domain: 123});
|
||||
|
||||
const localInstructions = _.defaults({
|
||||
signersCount: 4
|
||||
}, instructionsWithMaxLedgerVersionOffset);
|
||||
|
||||
try {
|
||||
this.api.prepareSettings(
|
||||
address, settings, localInstructions).then(prepared => {
|
||||
done(new Error('Expected method to reject. Prepared transaction: ' + JSON.stringify(prepared)));
|
||||
}).catch(err => {
|
||||
assert.strictEqual(err.name, 'ValidationError');
|
||||
assert.strictEqual(err.message, 'instance.settings.domain is not of a type(s) string');
|
||||
done();
|
||||
}).catch(done); // Finish test with assertion failure immediately instead of waiting for timeout.
|
||||
} catch (err) {
|
||||
done(new Error('Expected method to reject, but method threw. Thrown: ' + err));
|
||||
}
|
||||
});
|
||||
|
||||
it('prepareEscrowCreation', function () {
|
||||
const localInstructions = _.defaults({
|
||||
maxFee: '0.000012'
|
||||
@@ -4227,145 +3970,6 @@ describe('RippleAPI', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths', function () {
|
||||
return this.api.getPaths(requests.getPaths.normal).then(
|
||||
_.partial(checkResult, responses.getPaths.XrpToUsd, 'getPaths'));
|
||||
});
|
||||
|
||||
it('getPaths - result path has source_amount in drops', function () {
|
||||
return this.api.getPaths({
|
||||
source: {
|
||||
address: 'rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx',
|
||||
amount: {
|
||||
value: this.api.dropsToXrp(1000000),
|
||||
currency: 'XRP'
|
||||
}
|
||||
},
|
||||
destination: {
|
||||
address: 'rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5',
|
||||
amount: {
|
||||
counterparty: 'rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u',
|
||||
currency: 'EUR'
|
||||
}
|
||||
}
|
||||
}).then(
|
||||
_.partial(checkResult, [
|
||||
{
|
||||
"source": {
|
||||
"address": "rB2NTuTTS3eNCsWxZYzJ4wqRqxNLZqA9Vx",
|
||||
"amount": {
|
||||
"currency": "XRP",
|
||||
"value": "1"
|
||||
}
|
||||
},
|
||||
"destination": {
|
||||
"address": "rhpJkBfZGQyT1xeDbwtKEuSrSXw3QZSAy5",
|
||||
"minAmount": {
|
||||
"currency": "EUR",
|
||||
"value": "1",
|
||||
"counterparty": "rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u"
|
||||
}
|
||||
},
|
||||
"paths": "[[{\"currency\":\"USD\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"},{\"currency\":\"EUR\",\"issuer\":\"rGpGaj4sxEZGenW1prqER25EUi7x4fqK9u\"}]]"
|
||||
}
|
||||
], 'getPaths'));
|
||||
});
|
||||
|
||||
it('getPaths - queuing', function () {
|
||||
return Promise.all([
|
||||
this.api.getPaths(requests.getPaths.normal),
|
||||
this.api.getPaths(requests.getPaths.UsdToUsd),
|
||||
this.api.getPaths(requests.getPaths.XrpToXrp)
|
||||
]).then(results => {
|
||||
checkResult(responses.getPaths.XrpToUsd, 'getPaths', results[0]);
|
||||
checkResult(responses.getPaths.UsdToUsd, 'getPaths', results[1]);
|
||||
checkResult(responses.getPaths.XrpToXrp, 'getPaths', results[2]);
|
||||
});
|
||||
});
|
||||
|
||||
// @TODO
|
||||
// need decide what to do with currencies/XRP:
|
||||
// if add 'XRP' in currencies, then there will be exception in
|
||||
// xrpToDrops function (called from toRippledAmount)
|
||||
it('getPaths USD 2 USD', function () {
|
||||
return this.api.getPaths(requests.getPaths.UsdToUsd).then(
|
||||
_.partial(checkResult, responses.getPaths.UsdToUsd, 'getPaths'));
|
||||
});
|
||||
|
||||
it('getPaths XRP 2 XRP', function () {
|
||||
return this.api.getPaths(requests.getPaths.XrpToXrp).then(
|
||||
_.partial(checkResult, responses.getPaths.XrpToXrp, 'getPaths'));
|
||||
});
|
||||
|
||||
it('getPaths - source with issuer', function () {
|
||||
return this.api.getPaths(requests.getPaths.issuer).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - XRP 2 XRP - not enough', function () {
|
||||
return this.api.getPaths(requests.getPaths.XrpToXrpNotEnough).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - invalid PathFind', function () {
|
||||
assert.throws(() => {
|
||||
this.api.getPaths(requests.getPaths.invalid);
|
||||
}, /Cannot specify both source.amount/);
|
||||
});
|
||||
|
||||
it('getPaths - does not accept currency', function () {
|
||||
return this.api.getPaths(requests.getPaths.NotAcceptCurrency).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - no paths', function () {
|
||||
return this.api.getPaths(requests.getPaths.NoPaths).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - no paths source amount', function () {
|
||||
return this.api.getPaths(requests.getPaths.NoPathsSource).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('getPaths - no paths with source currencies', function () {
|
||||
const pathfind = requests.getPaths.NoPathsWithCurrencies;
|
||||
return this.api.getPaths(pathfind).then(() => {
|
||||
assert(false, 'Should throw NotFoundError');
|
||||
}).catch(error => {
|
||||
assert(error instanceof this.api.errors.NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - error: srcActNotFound', function () {
|
||||
const pathfind = _.assign({}, requests.getPaths.normal,
|
||||
{ source: { address: addresses.NOTFOUND } });
|
||||
return this.api.getPaths(pathfind).catch(error => {
|
||||
assert(error instanceof this.api.errors.RippleError);
|
||||
});
|
||||
});
|
||||
|
||||
it('getPaths - send all', function () {
|
||||
return this.api.getPaths(requests.getPaths.sendAll).then(
|
||||
_.partial(checkResult, responses.getPaths.sendAll, 'getPaths'));
|
||||
});
|
||||
|
||||
it('getLedgerVersion', function (done) {
|
||||
this.api.getLedgerVersion().then(ver => {
|
||||
assert.strictEqual(ver, 8819951);
|
||||
@@ -4387,84 +3991,6 @@ describe('RippleAPI', function () {
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('getLedger', function () {
|
||||
return this.api.getLedger().then(
|
||||
_.partial(checkResult, responses.getLedger.header, 'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - by hash', function () {
|
||||
return this.api.getLedger({ ledgerHash: '15F20E5FA6EA9770BBFFDBD62787400960B04BE32803B20C41F117F41C13830D' }).then(
|
||||
_.partial(checkResult, responses.getLedger.headerByHash, 'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - future ledger version', function () {
|
||||
return this.api.getLedger({ ledgerVersion: 14661789 }).then(response => {
|
||||
assert(response)
|
||||
})
|
||||
});
|
||||
|
||||
it('getLedger - with state as hashes', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: false,
|
||||
includeState: true,
|
||||
ledgerVersion: 6
|
||||
};
|
||||
return this.api.getLedger(request).then(
|
||||
_.partial(checkResult, responses.getLedger.withStateAsHashes,
|
||||
'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - with settings transaction', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 4181996
|
||||
};
|
||||
return this.api.getLedger(request).then(
|
||||
_.partial(checkResult, responses.getLedger.withSettingsTx, 'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - with partial payment', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 22420574
|
||||
};
|
||||
return this.api.getLedger(request).then(
|
||||
_.partial(checkResult, responses.getLedger.withPartial, 'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - pre 2014 with partial payment', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 100001
|
||||
};
|
||||
return this.api.getLedger(request).then(
|
||||
_.partial(checkResult,
|
||||
responses.getLedger.pre2014withPartial,
|
||||
'getLedger'));
|
||||
});
|
||||
|
||||
it('getLedger - full, then computeLedgerHash', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeState: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 38129
|
||||
};
|
||||
return this.api.getLedger(request).then(
|
||||
_.partial(checkResult, responses.getLedger.full, 'getLedger'))
|
||||
.then(response => {
|
||||
const ledger = _.assign({}, response,
|
||||
{ parentCloseTime: response.closeTime });
|
||||
const hash = this.api.computeLedgerHash(ledger, {computeTreeHashes: true});
|
||||
assert.strictEqual(hash,
|
||||
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
|
||||
});
|
||||
});
|
||||
|
||||
it('computeLedgerHash - given corrupt data - should fail', function () {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
|
||||
91
test/api/getLedger/index.ts
Normal file
91
test/api/getLedger/index.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import assert from 'assert-diff'
|
||||
import { assertResultMatch, TestSuite } from '../utils'
|
||||
import responses from '../../fixtures/responses'
|
||||
const { getLedger: RESPONSE_FIXTURES } = responses
|
||||
|
||||
/**
|
||||
* Every test suite exports their tests in the default object.
|
||||
* - Check out the "TestSuite" type for documentation on the interface.
|
||||
* - Check out "test/api/index.ts" for more information about the test runner.
|
||||
*/
|
||||
export default <TestSuite>{
|
||||
'simple test': async api => {
|
||||
const response = await api.getLedger()
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.header, 'getLedger')
|
||||
},
|
||||
'by hash': async api => {
|
||||
const response = await api.getLedger({
|
||||
ledgerHash:
|
||||
'15F20E5FA6EA9770BBFFDBD62787400960B04BE32803B20C41F117F41C13830D'
|
||||
})
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.headerByHash, 'getLedger')
|
||||
},
|
||||
'future ledger version': async api => {
|
||||
const response = await api.getLedger({ ledgerVersion: 14661789 })
|
||||
assert(!!response)
|
||||
},
|
||||
'with state as hashes': async api => {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: false,
|
||||
includeState: true,
|
||||
ledgerVersion: 6
|
||||
}
|
||||
const response = await api.getLedger(request)
|
||||
assertResultMatch(
|
||||
response,
|
||||
RESPONSE_FIXTURES.withStateAsHashes,
|
||||
'getLedger'
|
||||
)
|
||||
},
|
||||
'with settings transaction': async api => {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 4181996
|
||||
}
|
||||
const response = await api.getLedger(request)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.withSettingsTx, 'getLedger')
|
||||
},
|
||||
'with partial payment': async api => {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 22420574
|
||||
}
|
||||
const response = await api.getLedger(request)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.withPartial, 'getLedger')
|
||||
},
|
||||
'pre 2014 with partial payment': async api => {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 100001
|
||||
}
|
||||
const response = await api.getLedger(request)
|
||||
assertResultMatch(
|
||||
response,
|
||||
RESPONSE_FIXTURES.pre2014withPartial,
|
||||
'getLedger'
|
||||
)
|
||||
},
|
||||
'full, then computeLedgerHash': async api => {
|
||||
const request = {
|
||||
includeTransactions: true,
|
||||
includeState: true,
|
||||
includeAllData: true,
|
||||
ledgerVersion: 38129
|
||||
}
|
||||
const response = await api.getLedger(request)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.full, 'getLedger')
|
||||
const ledger = {
|
||||
...response,
|
||||
parentCloseTime: response.closeTime
|
||||
}
|
||||
const hash = api.computeLedgerHash(ledger, { computeTreeHashes: true })
|
||||
assert.strictEqual(
|
||||
hash,
|
||||
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E'
|
||||
)
|
||||
}
|
||||
}
|
||||
95
test/api/getPaths/index.ts
Normal file
95
test/api/getPaths/index.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import assert from 'assert-diff'
|
||||
import { assertResultMatch, assertRejects, TestSuite } from '../utils'
|
||||
import responses from '../../fixtures/responses'
|
||||
import requests from '../../fixtures/requests'
|
||||
import addresses from '../../fixtures/addresses.json'
|
||||
const { getPaths: REQUEST_FIXTURES } = requests
|
||||
const { getPaths: RESPONSE_FIXTURES } = responses
|
||||
|
||||
/**
|
||||
* Every test suite exports their tests in the default object.
|
||||
* - Check out the "TestSuite" type for documentation on the interface.
|
||||
* - Check out "test/api/index.ts" for more information about the test runner.
|
||||
*/
|
||||
export default <TestSuite>{
|
||||
'simple test': async api => {
|
||||
const response = await api.getPaths(REQUEST_FIXTURES.normal)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.XrpToUsd, 'getPaths')
|
||||
},
|
||||
'queuing': async api => {
|
||||
const [normalResult, usdOnlyResult, xrpOnlyResult] = await Promise.all([
|
||||
api.getPaths(REQUEST_FIXTURES.normal),
|
||||
api.getPaths(REQUEST_FIXTURES.UsdToUsd),
|
||||
api.getPaths(REQUEST_FIXTURES.XrpToXrp)
|
||||
])
|
||||
assertResultMatch(normalResult, RESPONSE_FIXTURES.XrpToUsd, 'getPaths')
|
||||
assertResultMatch(usdOnlyResult, RESPONSE_FIXTURES.UsdToUsd, 'getPaths')
|
||||
assertResultMatch(xrpOnlyResult, RESPONSE_FIXTURES.XrpToXrp, 'getPaths')
|
||||
},
|
||||
// @TODO
|
||||
// need decide what to do with currencies/XRP:
|
||||
// if add 'XRP' in currencies, then there will be exception in
|
||||
// xrpToDrops function (called from toRippledAmount)
|
||||
'getPaths USD 2 USD': async api => {
|
||||
const response = await api.getPaths(REQUEST_FIXTURES.UsdToUsd)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.UsdToUsd, 'getPaths')
|
||||
},
|
||||
'getPaths XRP 2 XRP': async api => {
|
||||
const response = await api.getPaths(REQUEST_FIXTURES.XrpToXrp)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.XrpToXrp, 'getPaths')
|
||||
},
|
||||
'source with issuer': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.issuer),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'XRP 2 XRP - not enough': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.XrpToXrpNotEnough),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'invalid PathFind': async api => {
|
||||
assert.throws(() => {
|
||||
api.getPaths(REQUEST_FIXTURES.invalid)
|
||||
}, /Cannot specify both source.amount/)
|
||||
},
|
||||
'does not accept currency': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.NotAcceptCurrency),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'no paths': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.NoPaths),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'no paths source amount': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.NoPathsSource),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'no paths with source currencies': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths(REQUEST_FIXTURES.NoPathsWithCurrencies),
|
||||
api.errors.NotFoundError
|
||||
)
|
||||
},
|
||||
'error: srcActNotFound': async api => {
|
||||
return assertRejects(
|
||||
api.getPaths({
|
||||
...REQUEST_FIXTURES.normal,
|
||||
source: { address: addresses.NOTFOUND }
|
||||
}),
|
||||
api.errors.RippleError
|
||||
)
|
||||
},
|
||||
'send all': async api => {
|
||||
const response = await api.getPaths(REQUEST_FIXTURES.sendAll)
|
||||
assertResultMatch(response, RESPONSE_FIXTURES.sendAll, 'getPaths')
|
||||
}
|
||||
}
|
||||
67
test/api/index.ts
Normal file
67
test/api/index.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import setupAPI from '../setup-api'
|
||||
import { RippleAPI } from 'ripple-api'
|
||||
import addresses from '../fixtures/addresses.json'
|
||||
import { getAllPublicMethods, loadTestSuite } from './utils'
|
||||
|
||||
/**
|
||||
* RippleAPI Test Runner
|
||||
*
|
||||
* Background: "test/api-test.ts" had hit 4000+ lines of test code and 300+
|
||||
* individual tests. Additionally, a new address format was added which
|
||||
* forced us to copy-paste duplicate the test file to test both the old forms
|
||||
* of address. This added a significant maintenance burden.
|
||||
*
|
||||
* This test runner allows us to split our tests by RippleAPI method, and
|
||||
* automatically load, validate, and run them. Each tests accepts arguments to
|
||||
* test with, which allows us to re-run tests across different data
|
||||
* (ex: different address styles).
|
||||
*
|
||||
* Additional benefits:
|
||||
* - Throw errors when we detect the absence of tests.
|
||||
* - Type the API object under test and catch typing issues (currently untyped).
|
||||
* - Sets the stage for more cleanup, like moving test-specific fixtures closer to their tests.
|
||||
*/
|
||||
describe('RippleAPI [Test Runner]', function() {
|
||||
beforeEach(setupAPI.setup)
|
||||
afterEach(setupAPI.teardown)
|
||||
|
||||
// Collect all the tests:
|
||||
const allPublicMethods = getAllPublicMethods(new RippleAPI())
|
||||
const allTestSuites = allPublicMethods.map(loadTestSuite)
|
||||
|
||||
// TODO: Once migration is complete, remove this filter so that missing tests are reported.
|
||||
const filteredTestSuites = allTestSuites.filter(({ isMissing }) => !isMissing)
|
||||
|
||||
// Run all the tests:
|
||||
for (const { name: suiteName, tests, isMissing } of filteredTestSuites) {
|
||||
describe(suiteName, () => {
|
||||
// Check that tests exist as expected, and report any errors if they don't.
|
||||
it('has valid test suite', () => {
|
||||
if (isMissing) {
|
||||
throw new Error(
|
||||
`Test file not found! Create file "test/api/${suiteName}/index.ts".`
|
||||
)
|
||||
}
|
||||
if (tests.length === 0) {
|
||||
throw new Error(`No tests found! Is your test file set up properly?`)
|
||||
}
|
||||
})
|
||||
// Run each test with the original-style address.
|
||||
describe(`1. Original Address Style`, () => {
|
||||
for (const [testName, fn] of tests) {
|
||||
it(testName, function() {
|
||||
return fn(this.api, addresses.ACCOUNT)
|
||||
})
|
||||
}
|
||||
})
|
||||
// Run each test with the newer, x-address style.
|
||||
describe(`2. X-Address Style`, () => {
|
||||
for (const [testName, fn] of tests) {
|
||||
it(testName, function() {
|
||||
return fn(this.api, addresses.ACCOUNT_X)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
238
test/api/prepareSettings/index.ts
Normal file
238
test/api/prepareSettings/index.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
import assert from 'assert-diff'
|
||||
import requests from '../../fixtures/requests'
|
||||
import responses from '../../fixtures/responses'
|
||||
import { assertResultMatch, TestSuite } from '../utils'
|
||||
const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }
|
||||
|
||||
/**
|
||||
* Every test suite exports their tests in the default object.
|
||||
* - Check out the "TestSuite" type for documentation on the interface.
|
||||
* - Check out "test/api/index.ts" for more information about the test runner.
|
||||
*/
|
||||
export default <TestSuite>{
|
||||
'simple test': async (api, address) => {
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
requests.prepareSettings.domain,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.flags, 'prepare')
|
||||
},
|
||||
'no maxLedgerVersion': async (api, address) => {
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
requests.prepareSettings.domain,
|
||||
{
|
||||
maxLedgerVersion: null
|
||||
}
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.noMaxLedgerVersion,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'no instructions': async (api, address) => {
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
requests.prepareSettings.domain
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.noInstructions,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'regularKey': async (api, address) => {
|
||||
const regularKey = { regularKey: 'rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD' }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
regularKey,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.regularKey, 'prepare')
|
||||
},
|
||||
'remove regularKey': async (api, address) => {
|
||||
const regularKey = { regularKey: null }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
regularKey,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.removeRegularKey,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'flag set': async (api, address) => {
|
||||
const settings = { requireDestinationTag: true }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.flagSet, 'prepare')
|
||||
},
|
||||
'flag clear': async (api, address) => {
|
||||
const settings = { requireDestinationTag: false }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.flagClear, 'prepare')
|
||||
},
|
||||
'set depositAuth flag': async (api, address) => {
|
||||
const settings = { depositAuth: true }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.flagSetDepositAuth,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'clear depositAuth flag': async (api, address) => {
|
||||
const settings = { depositAuth: false }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.flagClearDepositAuth,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'integer field clear': async (api, address) => {
|
||||
const settings = { transferRate: null }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assert(response)
|
||||
assert.strictEqual(JSON.parse(response.txJSON).TransferRate, 0)
|
||||
},
|
||||
'set transferRate': async (api, address) => {
|
||||
const settings = { transferRate: 1 }
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.setTransferRate,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'set signers': async (api, address) => {
|
||||
const settings = requests.prepareSettings.signers.normal
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.signers, 'prepare')
|
||||
},
|
||||
'signers no threshold': async (api, address) => {
|
||||
const settings = requests.prepareSettings.signers.noThreshold
|
||||
try {
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
instructionsWithMaxLedgerVersionOffset
|
||||
)
|
||||
throw new Error(
|
||||
'Expected method to reject. Prepared transaction: ' +
|
||||
JSON.stringify(response)
|
||||
)
|
||||
} catch (err) {
|
||||
assert.strictEqual(
|
||||
err.message,
|
||||
'instance.settings.signers requires property "threshold"'
|
||||
)
|
||||
assert.strictEqual(err.name, 'ValidationError')
|
||||
}
|
||||
},
|
||||
'signers no weights': async (api, address) => {
|
||||
const settings = requests.prepareSettings.signers.noWeights
|
||||
const localInstructions = {
|
||||
signersCount: 1,
|
||||
...instructionsWithMaxLedgerVersionOffset
|
||||
}
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
localInstructions
|
||||
)
|
||||
assertResultMatch(response, responses.prepareSettings.noWeights, 'prepare')
|
||||
},
|
||||
'fee for multisign': async (api, address) => {
|
||||
const localInstructions = {
|
||||
signersCount: 4,
|
||||
...instructionsWithMaxLedgerVersionOffset
|
||||
}
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
requests.prepareSettings.domain,
|
||||
localInstructions
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.flagsMultisign,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'no signer list': async (api, address) => {
|
||||
const settings = requests.prepareSettings.noSignerEntries
|
||||
const localInstructions = {
|
||||
signersCount: 1,
|
||||
...instructionsWithMaxLedgerVersionOffset
|
||||
}
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
localInstructions
|
||||
)
|
||||
assertResultMatch(
|
||||
response,
|
||||
responses.prepareSettings.noSignerList,
|
||||
'prepare'
|
||||
)
|
||||
},
|
||||
'invalid': async (api, address) => {
|
||||
// domain must be a string
|
||||
const settings = Object.assign({}, requests.prepareSettings.domain, {
|
||||
domain: 123
|
||||
})
|
||||
const localInstructions = {
|
||||
signersCount: 4,
|
||||
...instructionsWithMaxLedgerVersionOffset
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.prepareSettings(
|
||||
address,
|
||||
settings,
|
||||
localInstructions
|
||||
)
|
||||
throw new Error(
|
||||
'Expected method to reject. Prepared transaction: ' +
|
||||
JSON.stringify(response)
|
||||
)
|
||||
} catch (err) {
|
||||
assert.strictEqual(
|
||||
err.message,
|
||||
'instance.settings.domain is not of a type(s) string'
|
||||
)
|
||||
assert.strictEqual(err.name, 'ValidationError')
|
||||
}
|
||||
}
|
||||
}
|
||||
103
test/api/utils.ts
Normal file
103
test/api/utils.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import _ from 'lodash'
|
||||
import { RippleAPI } from 'ripple-api'
|
||||
import assert from 'assert-diff'
|
||||
const { schemaValidator } = RippleAPI._PRIVATE
|
||||
|
||||
/**
|
||||
* The test function. It takes a RippleAPI object and then some other data to
|
||||
* test (currently: an address). May be called multiple times with different
|
||||
* arguments, to test different types of data.
|
||||
*/
|
||||
export type TestFn = (
|
||||
api: RippleAPI,
|
||||
address: string
|
||||
) => void | PromiseLike<void>
|
||||
|
||||
/**
|
||||
* A suite of tests to run. Maps the test name to the test function.
|
||||
*/
|
||||
export interface TestSuite {
|
||||
[testName: string]: TestFn
|
||||
}
|
||||
|
||||
/**
|
||||
* When the test suite is loaded, we represent it with the following
|
||||
* data structure containing tests and metadata about the suite.
|
||||
* If no test suite exists, we return this object with `isMissing: true`
|
||||
* so that we can report it.
|
||||
*/
|
||||
interface LoadedTestSuite {
|
||||
name: string
|
||||
tests: [string, TestFn][]
|
||||
isMissing: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the response against the expected result. Optionally validate
|
||||
* that response against a given schema as well.
|
||||
*/
|
||||
export function assertResultMatch(
|
||||
response: any,
|
||||
expected: any,
|
||||
schemaName?: string
|
||||
) {
|
||||
if (expected.txJSON) {
|
||||
assert(response.txJSON)
|
||||
assert.deepEqual(
|
||||
JSON.parse(response.txJSON),
|
||||
JSON.parse(expected.txJSON),
|
||||
'checkResult: txJSON must match'
|
||||
)
|
||||
}
|
||||
if (expected.tx_json) {
|
||||
assert(response.tx_json)
|
||||
assert.deepEqual(
|
||||
response.tx_json,
|
||||
expected.tx_json,
|
||||
'checkResult: tx_json must match'
|
||||
)
|
||||
}
|
||||
assert.deepEqual(
|
||||
_.omit(response, ['txJSON', 'tx_json']),
|
||||
_.omit(expected, ['txJSON', 'tx_json'])
|
||||
)
|
||||
if (schemaName) {
|
||||
schemaValidator.schemaValidate(schemaName, response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the promise rejects with an expected error instance.
|
||||
*/
|
||||
export async function assertRejects(
|
||||
promise: PromiseLike<any>,
|
||||
instanceOf: any
|
||||
) {
|
||||
try {
|
||||
await promise
|
||||
assert(false, 'Expected an error to be thrown')
|
||||
} catch (error) {
|
||||
assert(error instanceof instanceOf)
|
||||
}
|
||||
}
|
||||
|
||||
export function getAllPublicMethods(api: RippleAPI) {
|
||||
return Object.keys(api).filter(key => !key.startsWith('_'))
|
||||
}
|
||||
|
||||
export function loadTestSuite(methodName: string): LoadedTestSuite | null {
|
||||
try {
|
||||
const testSuite = require(`./${methodName}`)
|
||||
return {
|
||||
isMissing: false,
|
||||
name: methodName,
|
||||
tests: Object.entries(testSuite.default || {}),
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
isMissing: true,
|
||||
name: methodName,
|
||||
tests: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
104
test/api/xrpToDrops/index.ts
Normal file
104
test/api/xrpToDrops/index.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import assert from 'assert-diff'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { TestSuite } from '../utils'
|
||||
|
||||
/**
|
||||
* Every test suite exports their tests in the default object.
|
||||
* - Check out the "TestSuite" type for documentation on the interface.
|
||||
* - Check out "test/api/index.ts" for more information about the test runner.
|
||||
*/
|
||||
export default <TestSuite>{
|
||||
'works with a typical amount': function(api) {
|
||||
const drops = api.xrpToDrops('2')
|
||||
assert.strictEqual(drops, '2000000', '2 XRP equals 2 million drops')
|
||||
},
|
||||
'works with fractions': function(api) {
|
||||
let drops = api.xrpToDrops('3.456789')
|
||||
assert.strictEqual(drops, '3456789', '3.456789 XRP equals 3,456,789 drops')
|
||||
drops = api.xrpToDrops('3.400000')
|
||||
assert.strictEqual(drops, '3400000', '3.400000 XRP equals 3,400,000 drops')
|
||||
drops = api.xrpToDrops('0.000001')
|
||||
assert.strictEqual(drops, '1', '0.000001 XRP equals 1 drop')
|
||||
drops = api.xrpToDrops('0.0000010')
|
||||
assert.strictEqual(drops, '1', '0.0000010 XRP equals 1 drop')
|
||||
},
|
||||
'works with zero': function(api) {
|
||||
let drops = api.xrpToDrops('0')
|
||||
assert.strictEqual(drops, '0', '0 XRP equals 0 drops')
|
||||
drops = api.xrpToDrops('-0') // negative zero is equivalent to zero
|
||||
assert.strictEqual(drops, '0', '-0 XRP equals 0 drops')
|
||||
drops = api.xrpToDrops('0.000000')
|
||||
assert.strictEqual(drops, '0', '0.000000 XRP equals 0 drops')
|
||||
drops = api.xrpToDrops('0.0000000')
|
||||
assert.strictEqual(drops, '0', '0.0000000 XRP equals 0 drops')
|
||||
},
|
||||
'works with a negative value': function(api) {
|
||||
const drops = api.xrpToDrops('-2')
|
||||
assert.strictEqual(drops, '-2000000', '-2 XRP equals -2 million drops')
|
||||
},
|
||||
'works with a value ending with a decimal point': function(api) {
|
||||
let drops = api.xrpToDrops('2.')
|
||||
assert.strictEqual(drops, '2000000', '2. XRP equals 2000000 drops')
|
||||
drops = api.xrpToDrops('-2.')
|
||||
assert.strictEqual(drops, '-2000000', '-2. XRP equals -2000000 drops')
|
||||
},
|
||||
'works with BigNumber objects': function(api) {
|
||||
let drops = api.xrpToDrops(new BigNumber(2))
|
||||
assert.strictEqual(
|
||||
drops,
|
||||
'2000000',
|
||||
'(BigNumber) 2 XRP equals 2 million drops'
|
||||
)
|
||||
drops = api.xrpToDrops(new BigNumber(-2))
|
||||
assert.strictEqual(
|
||||
drops,
|
||||
'-2000000',
|
||||
'(BigNumber) -2 XRP equals -2 million drops'
|
||||
)
|
||||
},
|
||||
'works with a number': function(api) {
|
||||
// This is not recommended. Use strings or BigNumber objects to avoid precision errors.
|
||||
let drops = api.xrpToDrops(2)
|
||||
assert.strictEqual(
|
||||
drops,
|
||||
'2000000',
|
||||
'(number) 2 XRP equals 2 million drops'
|
||||
)
|
||||
drops = api.xrpToDrops(-2)
|
||||
assert.strictEqual(
|
||||
drops,
|
||||
'-2000000',
|
||||
'(number) -2 XRP equals -2 million drops'
|
||||
)
|
||||
},
|
||||
'throws with an amount with too many decimal places': function(api) {
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('1.1234567')
|
||||
}, /has too many decimal places/)
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('0.0000001')
|
||||
}, /has too many decimal places/)
|
||||
},
|
||||
'throws with an invalid value': function(api) {
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('FOO')
|
||||
}, /invalid value/)
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('1e-7')
|
||||
}, /invalid value/)
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('2,0')
|
||||
}, /invalid value/)
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('.')
|
||||
}, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./)
|
||||
},
|
||||
'throws with an amount more than one decimal point': function(api) {
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('1.0.0')
|
||||
}, /xrpToDrops: invalid value '1\.0\.0'/)
|
||||
assert.throws(() => {
|
||||
api.xrpToDrops('...')
|
||||
}, /xrpToDrops: invalid value '\.\.\.'/)
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
--timeout 5000
|
||||
--slow 500
|
||||
--require ts-node/register
|
||||
--require source-map-support/register
|
||||
./test/*.{ts,js}
|
||||
--watch-extensions ts
|
||||
./test/*.{ts,js} ./test/api/index.ts
|
||||
@@ -4236,14 +4236,6 @@ source-map-resolve@^0.5.0:
|
||||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@0.5.12:
|
||||
version "0.5.12"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
|
||||
integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@^0.5.6, source-map-support@~0.5.12:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||
|
||||
Reference in New Issue
Block a user