mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-18 03:05:48 +00:00
154 lines
3.8 KiB
TypeScript
154 lines
3.8 KiB
TypeScript
import net from 'net'
|
|
import _ from 'lodash'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
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][]
|
|
config: {
|
|
/** Set to true to skip re-running tests with an X-address. */
|
|
skipXAddress?: 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.
|
|
*/
|
|
export async function assertRejects(
|
|
promise: PromiseLike<any>,
|
|
instanceOf: any,
|
|
message?: string | RegExp
|
|
) {
|
|
try {
|
|
await promise
|
|
assert(false, 'Expected an error to be thrown')
|
|
} catch (error) {
|
|
assert(error instanceof instanceOf, error.message)
|
|
if (typeof message === 'string') {
|
|
assert.strictEqual(error.message, message)
|
|
} else if (message instanceof RegExp) {
|
|
assert(message.test(error.message))
|
|
}
|
|
}
|
|
}
|
|
|
|
// using a free port instead of a constant port enables parallelization
|
|
export function getFreePort() {
|
|
return new Promise((resolve, reject) => {
|
|
const server = net.createServer()
|
|
let port
|
|
server.on('listening', function() {
|
|
port = (server.address() as any).port
|
|
server.close()
|
|
})
|
|
server.on('close', function() {
|
|
resolve(port)
|
|
})
|
|
server.on('error', function(error) {
|
|
reject(error)
|
|
})
|
|
server.listen(0)
|
|
})
|
|
}
|
|
|
|
export function getAllPublicMethods(api: RippleAPI) {
|
|
return Array.from(
|
|
new Set([
|
|
...Object.getOwnPropertyNames(api),
|
|
...Object.getOwnPropertyNames(RippleAPI.prototype)
|
|
])
|
|
).filter(key => !key.startsWith('_'))
|
|
}
|
|
|
|
export function loadTestSuites(): LoadedTestSuite[] {
|
|
const allTests = fs.readdirSync(path.join(__dirname, 'api'), {
|
|
encoding: 'utf8'
|
|
})
|
|
return allTests
|
|
.map(methodName => {
|
|
if (methodName.startsWith('.DS_Store')) {
|
|
return null
|
|
}
|
|
const testSuite = require(`./api/${methodName}`)
|
|
return {
|
|
name: methodName,
|
|
config: testSuite.config || {},
|
|
tests: Object.entries(testSuite.default || {})
|
|
} as LoadedTestSuite
|
|
})
|
|
.filter(Boolean)
|
|
}
|
|
|
|
/**
|
|
* Ignore WebSocket DisconnectErrors. Useful for making requests where we don't
|
|
* care about the response and plan to teardown the test before the response
|
|
* has come back.
|
|
*/
|
|
export function ignoreWebSocketDisconnect(error: Error): void {
|
|
if (error.message === 'websocket was closed') {
|
|
return
|
|
}
|
|
throw error
|
|
}
|