mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-consumer.git
synced 2026-09-22 09:12:03 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8faadfc5c1 | ||
|
|
fe0ad56395 | ||
|
|
5a05a95876 | ||
|
|
163e5f5f10 | ||
|
|
ff371a79b9 | ||
|
|
487b72bfa2 | ||
|
|
7d5715be39 | ||
|
|
fc99cafb1d | ||
|
|
0e51dc7f15 | ||
|
|
c0e0e42fc6 | ||
|
|
932110698c | ||
|
|
59ed8d9e7a | ||
|
|
883f9aca67 | ||
|
|
9b88d7f40c | ||
|
|
18ea03a4d6 | ||
|
|
3d911d1062 |
+1
-1
@@ -4,7 +4,7 @@ import development from './env/development.js'
|
||||
import production from './env/production.js'
|
||||
import test from './env/test.js'
|
||||
|
||||
const env = process.env.SVC_ENV || 'development'
|
||||
const env = process.env.CONSUMER_ENV || 'development'
|
||||
console.log(`Loading config for this environment: ${env}`)
|
||||
|
||||
let config = development
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"email": "system@system.com",
|
||||
"name": "admin",
|
||||
"password": "O52nYamPmP7zE9Jfwgxo",
|
||||
"password": "c9JjJxZmTs5bWmWC6adQ",
|
||||
"type": "admin",
|
||||
"id": "684246cf4e94f2261caf9848",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY4NDI0NmNmNGU5NGYyMjYxY2FmOTg0OCIsImlhdCI6MTc0OTE3NDAyMX0.9GAS6q_xFz5Bwi7RwIqrqM3Q48DFlz_A-S0_r_L2pTQ"
|
||||
"id": "68d47521e6060ba7332301b1",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY4ZDQ3NTIxZTYwNjBiYTczMzIzMDFiMSIsImlhdCI6MTc2MDY0MzI5NH0.SgoWnrP0YZZtPZ2V_C7HsfKoRHphfoIODN3-pltsGbo"
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"password": "RCJqq5FjgYzvTXOyS1vo",
|
||||
"email": "system@system.com",
|
||||
"id": "645e59c19d49119bbb8329e7",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY0NWU1OWMxOWQ0OTExOWJiYjgzMjllNyIsImlhdCI6MTY4MzkwNDk2MX0.2yi-hkY31nkgMm_S1QrPs4dIm5DBnJ4GsJEPiSPYHDA"
|
||||
"name": "admin",
|
||||
"password": "UdbCjMgm7T8efeyUfcdN",
|
||||
"type": "admin",
|
||||
"id": "68daea62e9b47af49f86dae9",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY4ZGFlYTYyZTliNDdhZjQ5Zjg2ZGFlOSIsImlhdCI6MTc1OTE3NzMxNH0.-mFCzyDri0OLMz-oM03qyYPj7srEH_6HFLGzgCf_JLI"
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export DBURL=mongodb://172.17.0.1:5558/ipfs-bch-consumer-prod
|
||||
export PORT=5015
|
||||
|
||||
# Production settings using external go-ipfs node.
|
||||
export SVC_ENV=prod
|
||||
export CONSUMER_ENV=prod
|
||||
export IPFS_HOST=172.17.0.1
|
||||
export IPFS_API_PORT=5001
|
||||
export IPFS_TCP_PORT=4101
|
||||
|
||||
@@ -110,6 +110,9 @@ class BchAdapter {
|
||||
// Choose the BCH wallet service to use.
|
||||
async selectProvider (providerId) {
|
||||
try {
|
||||
if (!providerId || typeof providerId !== 'string') {
|
||||
throw new Error('providerId must be a string!')
|
||||
}
|
||||
this.ipfs.ipfsCoordAdapter.config.preferredProvider = providerId
|
||||
|
||||
return true
|
||||
|
||||
@@ -119,6 +119,10 @@ class IpfsFilesAdapter {
|
||||
// Choose the ipfs-file-pin-service to use.
|
||||
async selectProvider (providerId) {
|
||||
try {
|
||||
if (!providerId || typeof providerId !== 'string') {
|
||||
throw new Error('providerId must be a string!')
|
||||
}
|
||||
|
||||
this.ipfs.ipfsCoordAdapter.config.selectedIpfsFileProvider = providerId
|
||||
|
||||
return true
|
||||
@@ -228,6 +232,10 @@ class IpfsFilesAdapter {
|
||||
// Returns a promise that resolves to data when the RPC response is recieved.
|
||||
async waitForRPCResponse (rpcId) {
|
||||
try {
|
||||
if (!rpcId) {
|
||||
throw new Error('rpcId can not be false or undefined')
|
||||
}
|
||||
|
||||
// Initialize variables for tracking the return data.
|
||||
let dataFound = false
|
||||
let cnt = 0
|
||||
|
||||
@@ -219,9 +219,10 @@ class IpfsCoordAdapter {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Error in pollForP2wdbServices()', err)
|
||||
// catch and handle known failure mode.
|
||||
if (
|
||||
err.message.includes("Cannot read property 'peerList' of undefined")
|
||||
err.message.includes('Cannot read')
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -276,6 +277,7 @@ class IpfsCoordAdapter {
|
||||
// Persist the config setting, so it can be used by other commands.
|
||||
// _this.conf.set('selectedService', thisPeer)
|
||||
console.log(`---->BCH wallet service selected: ${thisPeer}`)
|
||||
console.log('preferredProvider: ', _this.config.preferredProvider)
|
||||
}
|
||||
|
||||
// console.log('preferredProvider: ', _this.config.preferredProvider)
|
||||
@@ -286,8 +288,12 @@ class IpfsCoordAdapter {
|
||||
_this.config.preferredProvider &&
|
||||
thisPeer === _this.config.preferredProvider
|
||||
) {
|
||||
// console.log('preferredProvider: ', _this.config.preferredProvider)
|
||||
// console.log('thisPeer: ', thisPeer)
|
||||
// console.log('selectedServiceProvider: ', _this.state.selectedServiceProvider)
|
||||
if (_this.state.selectedServiceProvider !== thisPeer) {
|
||||
console.log(`---->BCH wallet service switched to preferred peer: ${thisPeer}`)
|
||||
console.log('preferredProvider: ', _this.config.preferredProvider)
|
||||
}
|
||||
|
||||
_this.state.selectedServiceProvider = thisPeer
|
||||
@@ -310,7 +316,7 @@ class IpfsCoordAdapter {
|
||||
} catch (err) {
|
||||
// catch and handle known failure mode.
|
||||
if (
|
||||
err.message.includes("Cannot read property 'peerList' of undefined")
|
||||
err.message.includes('Cannot read')
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -366,6 +372,7 @@ class IpfsCoordAdapter {
|
||||
// Persist the config setting, so it can be used by other commands.
|
||||
// _this.conf.set('selectedService', thisPeer)
|
||||
console.log(`---->IPFS File service selected: ${thisPeer}`)
|
||||
console.log('preferredIpfsFileProvider: ', _this.config.preferredIpfsFileProvider)
|
||||
}
|
||||
|
||||
// console.log('preferredProvider: ', _this.config.preferredProvider)
|
||||
@@ -400,7 +407,7 @@ class IpfsCoordAdapter {
|
||||
} catch (err) {
|
||||
// catch and handle known failure mode.
|
||||
if (
|
||||
err.message.includes("Cannot read property 'peerList' of undefined")
|
||||
err.message.includes('Cannot read')
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ class P2wdbAdapter {
|
||||
// Choose the BCH wallet service to use.
|
||||
async selectProvider (providerId) {
|
||||
try {
|
||||
if (!providerId || typeof providerId !== 'string') {
|
||||
throw new Error('providerId must be a string!')
|
||||
}
|
||||
this.ipfs.ipfsCoordAdapter.config.preferredP2wdbProvider = providerId
|
||||
|
||||
return true
|
||||
@@ -215,6 +218,10 @@ class P2wdbAdapter {
|
||||
// Returns a promise that resolves to data when the RPC response is recieved.
|
||||
async waitForRPCResponse (rpcId) {
|
||||
try {
|
||||
if (!rpcId) {
|
||||
throw new Error('rpcId can not be false or undefined')
|
||||
}
|
||||
|
||||
// Initialize variables for tracking the return data.
|
||||
let dataFound = false
|
||||
let cnt = 0
|
||||
|
||||
@@ -107,7 +107,7 @@ class JSONRPC {
|
||||
|
||||
// Default return string
|
||||
let retObj = _this.defaultResponse()
|
||||
|
||||
console.log('parsedData ', parsedData)
|
||||
// Forward data on to bch adapter if this is the response of a BCH query.
|
||||
try {
|
||||
if (parsedData.payload.result.method === 'bch') {
|
||||
|
||||
@@ -26,6 +26,7 @@ class TimerControllers {
|
||||
// Constants
|
||||
this.cleanUsageInterval = 60000 * 60 // 1 hour
|
||||
this.backupUsageInterval = 60000 * 10 // 10 minutes
|
||||
this.rebootInterval = 60000 * 60 * 12 // 12 hours
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.config = config
|
||||
@@ -33,6 +34,7 @@ class TimerControllers {
|
||||
// Bind 'this' object to all subfunctions.
|
||||
this.cleanUsage = this.cleanUsage.bind(this)
|
||||
this.backupUsage = this.backupUsage.bind(this)
|
||||
this.autoReboot = this.autoReboot.bind(this)
|
||||
}
|
||||
|
||||
// Start all the time-based controllers.
|
||||
@@ -42,6 +44,11 @@ class TimerControllers {
|
||||
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
|
||||
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
|
||||
|
||||
// Periodically reboot this app. Helia has a slight memory leak, and occasionally
|
||||
// runs into unrecoverable network issues. Rebooting is one way to overcome these
|
||||
// black-box issues.
|
||||
this.rebootHandle = setInterval(this.autoReboot, this.rebootInterval)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -98,6 +105,15 @@ class TimerControllers {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// This timer is used to auto-reboot the processes. If this is being run in Docker container
|
||||
// (the target for production), the Docker container should automatically restart the timer.
|
||||
// This is a temporary fix to the IPFS node stalling occasionally until a better fix can be
|
||||
// found.
|
||||
autoReboot () {
|
||||
console.log('Rebooting service.')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
export default TimerControllers
|
||||
|
||||
@@ -155,7 +155,8 @@ class IpfsUseCases {
|
||||
// Periodically re-validate the write-price (by re-instantiating the
|
||||
// PSFFPP library) in case it's changed.
|
||||
const now = new Date()
|
||||
const sixHours = now.getTime() * 1000 * 60 * 60 * 6
|
||||
const sixHours = 1000 * 60 * 60 * 6
|
||||
|
||||
if (this.lastWritePriceUpdate + sixHours < now.getTime()) {
|
||||
this.psffpp = new PSFFPP({ wallet })
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ class UsageUseCases {
|
||||
restCalls = restCalls.filter(x => x.timestamp > twentyFourHoursAgo)
|
||||
console.log('cleanUsage() restCalls.length after filtering: ', restCalls.length)
|
||||
|
||||
if (!restCalls) restCalls = []
|
||||
|
||||
return restCalls
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/cleanUsage()')
|
||||
@@ -128,6 +130,7 @@ class UsageUseCases {
|
||||
// Delete this code after debugging
|
||||
const usage = await this.UsageModel.find({})
|
||||
console.log('clearUsage() usage: ', usage)
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/clearUsage()')
|
||||
throw err
|
||||
@@ -150,6 +153,7 @@ class UsageUseCases {
|
||||
const usage = new this.UsageModel(usageData)
|
||||
await usage.save()
|
||||
}
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/saveUsage()')
|
||||
throw err
|
||||
@@ -163,8 +167,12 @@ class UsageUseCases {
|
||||
// console.log('usage: ', usage)
|
||||
|
||||
restCalls = usage
|
||||
if (!restCalls) restCalls = []
|
||||
|
||||
return usage
|
||||
} catch (err) {
|
||||
console.error('Error in usage-use-cases.js/loadUsage(): ', err)
|
||||
return false
|
||||
// throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,21 @@ describe('#adapters', () => {
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
it('should not start ipfs on test enviroment', async () => {
|
||||
// Mock dependencies
|
||||
uut.config.getJwtAtStartup = true
|
||||
uut.config.useIpfs = true
|
||||
uut.config.env = 'test'
|
||||
|
||||
sandbox.stub(uut.fullStackJwt, 'getJWT').resolves()
|
||||
sandbox.stub(uut.fullStackJwt, 'instanceBchjs').resolves()
|
||||
const ipfsSpy = sandbox.stub(uut.ipfs, 'start').resolves(null)
|
||||
|
||||
const result = await uut.start()
|
||||
|
||||
assert.isTrue(ipfsSpy.notCalled)
|
||||
assert.equal(result, true)
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
|
||||
@@ -19,16 +19,17 @@ describe('Admin', () => {
|
||||
|
||||
if (!config.noMongo) {
|
||||
describe('loginAdmin()', () => {
|
||||
// it('should login admin', async () => {
|
||||
// try {
|
||||
// sandbox.stub(uut.axios, 'request').resolves(true)
|
||||
it('should login admin', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'pass' })
|
||||
sandbox.stub(uut.axios, 'request').resolves(true)
|
||||
|
||||
// const result = await uut.loginAdmin()
|
||||
// assert.isTrue(result)
|
||||
// } catch (err) {
|
||||
// assert(false, 'Unexpected result')
|
||||
// }
|
||||
// })
|
||||
const result = await uut.loginAdmin()
|
||||
assert.isTrue(result)
|
||||
} catch (err) {
|
||||
assert(false, 'Unexpected result')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle axios error', async () => {
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@ import cloneDeep from 'lodash.clonedeep'
|
||||
import BchAdapter from '../../../src/adapters/bch/index.js'
|
||||
import adapters from '../mocks/adapters/index.js'
|
||||
import mockDataLib from '../mocks/use-cases/rest-api-mocks.js'
|
||||
import ipfsCoordMocks from '../mocks/adapters/ipfs-coord-mocks.js'
|
||||
|
||||
const eventEmitter = new EventEmitter()
|
||||
|
||||
@@ -91,7 +92,30 @@ describe('#bch-use-case', () => {
|
||||
assert.property(result, 'balances')
|
||||
assert.isArray(result.balances)
|
||||
})
|
||||
it('should return false if data is not found', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock data.
|
||||
const rpcId = '123'
|
||||
// Fill the queue with false values.
|
||||
for (let i = 0; i < 10; i++) {
|
||||
uut.rpcDataQueue.push({ payload: { id: '1234567890' } })
|
||||
}
|
||||
sandbox.stub(uut, 'sleep').resolves()
|
||||
|
||||
const result = await uut.waitForRPCResponse(rpcId)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.isFalse(result.success)
|
||||
})
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
await uut.waitForRPCResponse()
|
||||
@@ -114,12 +138,46 @@ describe('#bch-use-case', () => {
|
||||
|
||||
uut.rpcHandler(data)
|
||||
})
|
||||
it('should skip errors', async () => {
|
||||
try {
|
||||
sandbox.stub(uut, 'rpcDataQueue').throws(new Error('test error'))
|
||||
await uut.rpcHandler()
|
||||
} catch (err) {
|
||||
assert.fail('Unexpected code path')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getStatus', () => {
|
||||
it('should get the status from ipfs-coord', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.serviceProviders = ipfsCoordMocks.peers
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode.peerData = ipfsCoordMocks.peerData
|
||||
const result = await uut.getStatus()
|
||||
console.log('result: ', result)
|
||||
assert.isObject(result)
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode = null
|
||||
await uut.getStatus()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Cannot read')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#selectProvider', () => {
|
||||
it('should select provider', async () => {
|
||||
await uut.selectProvider('providerId to select')
|
||||
assert.equal(uut.ipfs.ipfsCoordAdapter.config.preferredProvider, 'providerId to select')
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
await uut.selectProvider()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'providerId must be a string!')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -154,6 +212,18 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
await uut.getBalances()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getUtxos', () => {
|
||||
@@ -184,6 +254,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'addr required when calling getUtxos')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const addr = 'addr'
|
||||
|
||||
await uut.getUtxos(addr)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getUtxosBulk', () => {
|
||||
@@ -230,6 +313,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'addresses parameter must not exceed 20 elements')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const addrs = ['addr']
|
||||
|
||||
await uut.getUtxosBulk(addrs)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#broadcast', () => {
|
||||
@@ -260,6 +356,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'hex required when calling broadcast')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const hex = 'abc123'
|
||||
|
||||
await uut.broadcast(hex)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTransactions', () => {
|
||||
@@ -290,6 +399,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'address required when calling getTransactions()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const addr = 'abc123'
|
||||
|
||||
await uut.getTransactions(addr)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTransaction', () => {
|
||||
@@ -320,6 +442,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'txids required when calling getTransaction()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const txid = 'abc123'
|
||||
|
||||
await uut.getTransaction(txid)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getPubKey', () => {
|
||||
@@ -350,6 +485,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'address required when calling getPubKey()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const addr = 'abc123'
|
||||
|
||||
await uut.getPubKey(addr)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#utxoIsValid', () => {
|
||||
@@ -380,6 +528,18 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'utxo required when calling utxoIsValid()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const utxo = { a: 'b' }
|
||||
await uut.utxoIsValid(utxo)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTokenData', () => {
|
||||
@@ -410,6 +570,19 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'tokenId required when calling getTokenData()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const tokenId = 'blah'
|
||||
|
||||
await uut.getTokenData(tokenId)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTokenData2', () => {
|
||||
@@ -440,5 +613,18 @@ describe('#bch-use-case', () => {
|
||||
assert.equal(err.message, 'tokenId required when calling getTokenData2()')
|
||||
}
|
||||
})
|
||||
it('should throw an error if selected provider is not defined', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedServiceProvider = null
|
||||
|
||||
const tokenId = 'blah'
|
||||
|
||||
await uut.getTokenData2(tokenId)
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
assert.equal(err.message, 'No BCH Wallet Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -151,7 +151,21 @@ describe('#IPFS', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#subscribeToChat', () => {
|
||||
it('should subscribe to the chat channel', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
adapters: {
|
||||
pubsub: {
|
||||
subscribeToPubsubChannel: async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await uut.subscribeToChat()
|
||||
})
|
||||
})
|
||||
describe('#pollForBchServices', () => {
|
||||
it('should find and select the wallet service', () => {
|
||||
uut.ipfsCoord = {
|
||||
@@ -169,46 +183,194 @@ describe('#IPFS', () => {
|
||||
'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2'
|
||||
)
|
||||
})
|
||||
it('should use preferredProvider if set', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
// Define already selected service provider.
|
||||
uut.state.serviceProviders = [mockData.peers[2]]
|
||||
uut.state.selectedServiceProvider = mockData.peers[2]
|
||||
// Define preferred provider.
|
||||
uut.config.preferredProvider = mockData.peers[0]
|
||||
sandbox.stub(uut.semver, 'gt').returns(true)
|
||||
|
||||
it('should catch and report errors', () => {
|
||||
uut.pollForBchServices()
|
||||
await uut.pollForBchServices()
|
||||
|
||||
assert.equal(uut.state.selectedServiceProvider, uut.config.preferredProvider)
|
||||
})
|
||||
|
||||
it('should log unknown errors', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'gt').throws(new Error('test error'))
|
||||
|
||||
await uut.pollForBchServices()
|
||||
|
||||
assert.equal(uut.state.selectedServiceProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
it('should handle ipfsCoord errors', async () => {
|
||||
uut.ipfsCoord = {
|
||||
}
|
||||
|
||||
await uut.pollForBchServices()
|
||||
|
||||
assert.equal(uut.state.selectedServiceProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
})
|
||||
|
||||
// describe('#peerInputHandler', () => {
|
||||
// it('should emit an event trigger', () => {
|
||||
// const data = 'some data'
|
||||
//
|
||||
// uut.peerInputHandler(data)
|
||||
//
|
||||
// assert.isOk(true, 'Not throwing an error is a success')
|
||||
// })
|
||||
//
|
||||
// it('should catch and report errors', () => {
|
||||
// // Force an error
|
||||
// sandbox.stub(uut.eventEmitter, 'emit').throws(new Error('test error'))
|
||||
//
|
||||
// uut.peerInputHandler()
|
||||
//
|
||||
// assert.isOk(true, 'Not throwing an error is a success.')
|
||||
// })
|
||||
// })
|
||||
|
||||
describe('#subscribeToChat', () => {
|
||||
it('should subscribe to the chat channel', async () => {
|
||||
describe('#pollForP2wdbServices', () => {
|
||||
it('should poll for P2WDB services', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
adapters: {
|
||||
pubsub: {
|
||||
subscribeToPubsubChannel: async () => {
|
||||
}
|
||||
}
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'gt').returns(true)
|
||||
|
||||
await uut.pollForP2wdbServices()
|
||||
|
||||
assert.equal(uut.state.selectedP2wdbProvider, mockData.peers[2])
|
||||
})
|
||||
it('should use preferredP2wdbProvider if set', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
|
||||
await uut.subscribeToChat()
|
||||
uut.config.preferredP2wdbProvider = mockData.peers[2]
|
||||
sandbox.stub(uut.semver, 'gt').returns(true)
|
||||
|
||||
await uut.pollForP2wdbServices()
|
||||
|
||||
assert.equal(uut.state.selectedP2wdbProvider, uut.config.preferredP2wdbProvider)
|
||||
})
|
||||
it('should handle a peer that does not match the protocol', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'gt').returns(false)
|
||||
|
||||
await uut.pollForP2wdbServices()
|
||||
|
||||
assert.equal(uut.state.selectedP2wdbProvider, '')
|
||||
})
|
||||
it('should log unknown errors', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'gt').throws(new Error('test error'))
|
||||
|
||||
await uut.pollForP2wdbServices()
|
||||
|
||||
assert.equal(uut.state.selectedP2wdbProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
it('should handle ipfsCoord errors', async () => {
|
||||
uut.ipfsCoord = {
|
||||
}
|
||||
|
||||
await uut.pollForP2wdbServices()
|
||||
|
||||
assert.equal(uut.state.selectedP2wdbProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#pollForIpfsFileServices', () => {
|
||||
it('should poll for IPFS File services', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'gt').returns(true)
|
||||
|
||||
await uut.pollForIpfsFileServices()
|
||||
|
||||
assert.equal(uut.state.selectedIpfsFileProvider, mockData.peers[3])
|
||||
})
|
||||
it('should use preferredIpfsFileProvider if set', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
// Define already selected service provider.
|
||||
uut.state.ipfsFileProviders = [mockData.peers[0]]
|
||||
uut.state.selectedIpfsFileProvider = mockData.peers[0]
|
||||
|
||||
uut.config.preferredIpfsFileProvider = mockData.peers[3]
|
||||
sandbox.stub(uut.semver, 'satisfies').returns(true)
|
||||
|
||||
await uut.pollForIpfsFileServices()
|
||||
|
||||
assert.equal(uut.state.selectedIpfsFileProvider, uut.config.preferredIpfsFileProvider)
|
||||
})
|
||||
it('should handle a peer that does not match the protocol', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'satisfies').returns(false)
|
||||
|
||||
await uut.pollForIpfsFileServices()
|
||||
|
||||
assert.equal(uut.state.selectedIpfsFileProvider, '')
|
||||
})
|
||||
it('should log unknown errors', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfsCoord = {
|
||||
thisNode: {
|
||||
peerList: mockData.peers,
|
||||
peerData: mockData.peerData
|
||||
}
|
||||
}
|
||||
sandbox.stub(uut.semver, 'satisfies').throws(new Error('test error'))
|
||||
|
||||
await uut.pollForIpfsFileServices()
|
||||
|
||||
assert.equal(uut.state.selectedIpfsFileProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
it('should handle ipfsCoord errors', async () => {
|
||||
uut.ipfsCoord = {
|
||||
}
|
||||
|
||||
await uut.pollForIpfsFileServices()
|
||||
|
||||
assert.equal(uut.state.selectedIpfsFileProvider, '')
|
||||
assert.isOk(true, 'Not throwing an error is a success.')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
Unit tests for the IPFS Files Adapter.
|
||||
*/
|
||||
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import adapters from '../mocks/adapters/index.js'
|
||||
import IPFSFilesAdapter from '../../../src/adapters/ipfs-files/index.js'
|
||||
// import IPFSMock from '../mocks/ipfs-mock.js'
|
||||
|
||||
import mockDataLib from '../mocks/adapters/ipfs-coord-mocks.js'
|
||||
import mockDataRPC from '../mocks/use-cases/rest-api-mocks.js'
|
||||
|
||||
describe('#IPFS-Files', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
let mockData
|
||||
|
||||
beforeEach(() => {
|
||||
const ipfs = adapters.ipfs
|
||||
uut = new IPFSFilesAdapter({ ipfs })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
mockData = cloneDeep(mockDataLib)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore()
|
||||
|
||||
clearInterval(uut.pollBchServiceInterval)
|
||||
clearInterval(uut.pollP2wdbServiceInterval)
|
||||
})
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if ipfs instance is not included', () => {
|
||||
try {
|
||||
uut = new IPFSFilesAdapter()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'An instance of IPFS must be passed when instantiating the IPFS Files Adapter library.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#rpcHandler', () => {
|
||||
it('should add RPC data to queue', () => {
|
||||
const data = {
|
||||
payload: {
|
||||
id: '123'
|
||||
}
|
||||
}
|
||||
|
||||
uut.rpcHandler(data)
|
||||
})
|
||||
it('should skip errors', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.rpcDataQueue, 'push').throws(new Error('test error'))
|
||||
await uut.rpcHandler()
|
||||
} catch (err) {
|
||||
assert.fail('Unexpected code path')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getStatus', () => {
|
||||
it('should get the status from ipfs-coord', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.ipfsFileProviders = mockData.peers
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode = { peerData: mockData.peerData }
|
||||
|
||||
await uut.getStatus()
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode = null
|
||||
await uut.getStatus()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Cannot read')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#selectProvider', () => {
|
||||
it('should select provider', async () => {
|
||||
await uut.selectProvider('providerId to select')
|
||||
assert.equal(uut.ipfs.ipfsCoordAdapter.config.selectedIpfsFileProvider, 'providerId to select')
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
await uut.selectProvider()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'providerId must be a string!')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getFileMetadata', () => {
|
||||
it('should get file metadata', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = mockData.peers[0]
|
||||
sandbox.stub(uut, 'waitForRPCResponse').resolves({
|
||||
success: true
|
||||
})
|
||||
const result = await uut.getFileMetadata({ cid: 'cid to get' })
|
||||
assert.equal(result.success, true)
|
||||
})
|
||||
it('should handle error if no cid is provided', async () => {
|
||||
try {
|
||||
await uut.getFileMetadata()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'getFileMetadata() cid input hash must be a string.')
|
||||
}
|
||||
})
|
||||
it('should handle error if no provider is selected', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = null
|
||||
await uut.getFileMetadata({ cid: 'cid to get' })
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'No IPFS File Pin Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getPins', () => {
|
||||
it('should get pins', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = mockData.peers[0]
|
||||
sandbox.stub(uut, 'waitForRPCResponse').resolves({
|
||||
success: true
|
||||
})
|
||||
const result = await uut.getPins()
|
||||
assert.equal(result.success, true)
|
||||
})
|
||||
it('should handle error if no provider is selected', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = null
|
||||
await uut.getPins()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'No IPFS File Pin Service provider available yet.')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#waitForRPCResponse', () => {
|
||||
it('should resolve when data is received', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock data.
|
||||
const rpcId = '123'
|
||||
uut.rpcDataQueue.push(mockDataRPC.rpcData)
|
||||
|
||||
const result = await uut.waitForRPCResponse(rpcId)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, true)
|
||||
assert.property(result, 'balances')
|
||||
assert.isArray(result.balances)
|
||||
})
|
||||
it('should return false if data is not found', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock data.
|
||||
const rpcId = '123'
|
||||
// Fill the queue with false values.
|
||||
for (let i = 0; i < 10; i++) {
|
||||
uut.rpcDataQueue.push({ payload: { id: '1234567890' } })
|
||||
}
|
||||
sandbox.stub(uut.ipfs.ipfsCoordAdapter.bchjs.Util, 'sleep').resolves()
|
||||
|
||||
const result = await uut.waitForRPCResponse(rpcId)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.isFalse(result.success)
|
||||
})
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await uut.waitForRPCResponse()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('error: ', err)
|
||||
assert.include(err.message, 'rpcId can not be false or undefined')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#pinClaim', () => {
|
||||
it('should process pinClaim', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = mockData.peers[0]
|
||||
sandbox.stub(uut, 'waitForRPCResponse').resolves({
|
||||
success: true
|
||||
})
|
||||
const result = await uut.pinClaim({
|
||||
proofOfBurnTxid: 'proofOfBurnTxid to pin',
|
||||
cid: 'cid to pin',
|
||||
claimTxid: 'claimTxid to pin',
|
||||
filename: 'filename to pin',
|
||||
address: 'address to pin'
|
||||
})
|
||||
assert.equal(result.success, true)
|
||||
})
|
||||
it('should handle error if no provider is selected', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedIpfsFileProvider = null
|
||||
await uut.pinClaim({
|
||||
proofOfBurnTxid: 'proofOfBurnTxid to pin',
|
||||
cid: 'cid to pin',
|
||||
claimTxid: 'claimTxid to pin',
|
||||
filename: 'filename to pin',
|
||||
address: 'address to pin'
|
||||
})
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'No IPFS File Provider Service is available yet. Try again in a few seconds.')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Unit tests for P2WDB Adapter.
|
||||
*/
|
||||
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import adapters from '../mocks/adapters/index.js'
|
||||
import P2WDBAdapter from '../../../src/adapters/p2wdb/index.js'
|
||||
// import IPFSMock from '../mocks/ipfs-mock.js'
|
||||
|
||||
import mockDataLib from '../mocks/adapters/ipfs-coord-mocks.js'
|
||||
import mockDataRPC from '../mocks/use-cases/rest-api-mocks.js'
|
||||
|
||||
describe('#P2WDB Adapter', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
let mockData
|
||||
|
||||
beforeEach(() => {
|
||||
const ipfs = adapters.ipfs
|
||||
uut = new P2WDBAdapter({ ipfs })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
mockData = cloneDeep(mockDataLib)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore()
|
||||
|
||||
clearInterval(uut.pollBchServiceInterval)
|
||||
clearInterval(uut.pollP2wdbServiceInterval)
|
||||
})
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if ipfs instance is not included', () => {
|
||||
try {
|
||||
uut = new P2WDBAdapter()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'An instance of IPFS must be passed when instantiating the P2WDB Adapter library.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#rpcHandler', () => {
|
||||
it('should add RPC data to queue', () => {
|
||||
const data = {
|
||||
payload: {
|
||||
id: '123'
|
||||
}
|
||||
}
|
||||
|
||||
uut.rpcHandler(data)
|
||||
})
|
||||
it('should skip errors', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.rpcDataQueue, 'push').throws(new Error('test error'))
|
||||
await uut.rpcHandler()
|
||||
} catch (err) {
|
||||
assert.fail('Unexpected code path')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getStatus', () => {
|
||||
it('should get the status from ipfs-coord', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.p2wdbProviders = mockData.peers
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode = { peerData: mockData.peerData }
|
||||
|
||||
await uut.getStatus()
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.ipfsCoord.thisNode = null
|
||||
await uut.getStatus()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Cannot read')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#selectProvider', () => {
|
||||
it('should select provider', async () => {
|
||||
await uut.selectProvider('providerId to select')
|
||||
assert.equal(uut.ipfs.ipfsCoordAdapter.config.preferredP2wdbProvider, 'providerId to select')
|
||||
})
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
await uut.selectProvider()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'providerId must be a string!')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#waitForRPCResponse', () => {
|
||||
it('should resolve when data is received', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock data.
|
||||
const rpcId = '123'
|
||||
uut.rpcDataQueue.push(mockDataRPC.rpcData)
|
||||
|
||||
const result = await uut.waitForRPCResponse(rpcId)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, true)
|
||||
assert.property(result, 'balances')
|
||||
assert.isArray(result.balances)
|
||||
})
|
||||
it('should return false if data is not found', async () => {
|
||||
// Mock dependencies
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock data.
|
||||
const rpcId = '123'
|
||||
// Fill the queue with false values.
|
||||
for (let i = 0; i < 10; i++) {
|
||||
uut.rpcDataQueue.push({ payload: { id: '1234567890' } })
|
||||
}
|
||||
sandbox.stub(uut.ipfs.ipfsCoordAdapter.bchjs.Util, 'sleep').resolves()
|
||||
|
||||
const result = await uut.waitForRPCResponse(rpcId)
|
||||
// console.log('result: ', result)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.isFalse(result.success)
|
||||
})
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.wallet = {
|
||||
bchjs: {
|
||||
Util: {
|
||||
sleep: () => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await uut.waitForRPCResponse()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
// console.log('error: ', err)
|
||||
assert.include(err.message, 'rpcId can not be false or undefined')
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#writeEntry', () => {
|
||||
it('should handle error if no provider is selected', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedP2wdbProvider = null
|
||||
await uut.writeEntry({
|
||||
txid: 'txid to write',
|
||||
signature: 'signature to write',
|
||||
message: 'message to write',
|
||||
data: 'data to write'
|
||||
})
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'No P2WDB Service provider available yet.')
|
||||
}
|
||||
})
|
||||
it('should process writeEntry', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedP2wdbProvider = mockData.peers[0]
|
||||
sandbox.stub(uut, 'waitForRPCResponse').resolves({
|
||||
success: true
|
||||
})
|
||||
const result = await uut.writeEntry({
|
||||
txid: 'txid to write',
|
||||
signature: 'signature to write',
|
||||
message: 'message to write',
|
||||
data: 'data to write'
|
||||
})
|
||||
assert.equal(result.success, true)
|
||||
})
|
||||
})
|
||||
describe('#getEntryByHash', () => {
|
||||
it('should handle error if hash is not provided', async () => {
|
||||
try {
|
||||
await uut.getEntryByHash()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'getEntry() input hash must be a string.')
|
||||
}
|
||||
})
|
||||
it('should handle error if no provider is selected', async () => {
|
||||
try {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedP2wdbProvider = null
|
||||
await uut.getEntryByHash('hash to get')
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'No P2WDB Service provider available yet.')
|
||||
}
|
||||
})
|
||||
it('should process getEntryByHash', async () => {
|
||||
uut.ipfs.ipfsCoordAdapter.state.selectedP2wdbProvider = mockData.peers[0]
|
||||
sandbox.stub(uut, 'waitForRPCResponse').resolves({
|
||||
success: true
|
||||
})
|
||||
const result = await uut.getEntryByHash('hash to get')
|
||||
assert.equal(result.success, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -41,5 +41,17 @@ describe('#passport.js', () => {
|
||||
assert.include(err.message, 'cant auth user')
|
||||
}
|
||||
})
|
||||
it('should authenticate user', async () => {
|
||||
const ctx = {}
|
||||
const errMock = null
|
||||
const userMock = {
|
||||
_id: '123',
|
||||
email: 'test@test.com'
|
||||
}
|
||||
sandbox.stub(uut.passport, 'authenticate').yields(errMock, userMock)
|
||||
const user = await uut.authUser(ctx)
|
||||
assert.equal(user._id, userMock._id)
|
||||
assert.equal(user.email, userMock.email)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -54,6 +54,13 @@ describe('#User-Adapter', () => {
|
||||
|
||||
assert.notEqual(testuser.password, 'password')
|
||||
})
|
||||
it('should ignore password encrption if password property is not provided', async () => {
|
||||
const lastPassword = testuser.password
|
||||
await testuser.save()
|
||||
// console.log('testuser: ', testuser)
|
||||
|
||||
assert.equal(testuser.password, lastPassword)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#validatePassword', () => {
|
||||
|
||||
@@ -38,4 +38,25 @@ describe('#Controllers', () => {
|
||||
await uut.attachControllers(app)
|
||||
})
|
||||
})
|
||||
describe('#attachRESTControllers', () => {
|
||||
it('should attach the controllers', async () => {
|
||||
const app = {
|
||||
use: () => {}
|
||||
}
|
||||
|
||||
await uut.attachRESTControllers(app)
|
||||
})
|
||||
})
|
||||
describe('#initAdapters', () => {
|
||||
it('should attach the controllers', async () => {
|
||||
sandbox.stub(uut.adapters, 'start').resolves({})
|
||||
await uut.initAdapters()
|
||||
})
|
||||
})
|
||||
describe('#initUseCases', () => {
|
||||
it('should attach the controllers', async () => {
|
||||
sandbox.stub(uut.useCases, 'start').resolves({})
|
||||
await uut.initUseCases()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -162,6 +162,40 @@ describe('#JSON RPC', () => {
|
||||
assert.equal(obj.result.method, 'auth')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
it('should route to bch handler on success payload', async () => {
|
||||
const id = uid()
|
||||
const json = jsonrpc.success(id, { method: 'bch' })
|
||||
const str = JSON.stringify(json)
|
||||
|
||||
// Mock the controller.
|
||||
sandbox.stub(uut.adapters.bch, 'rpcHandler').resolves('true')
|
||||
|
||||
const result = await uut.router(str, 'peerA')
|
||||
// console.log(result)
|
||||
|
||||
const obj = JSON.parse(result.retStr)
|
||||
// console.log('obj: ', obj)
|
||||
|
||||
assert.equal(obj.result.value, 'true')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
it('should route to bch handler on success payload', async () => {
|
||||
const id = uid()
|
||||
const json = jsonrpc.success(id, { method: 'file-pin' })
|
||||
const str = JSON.stringify(json)
|
||||
|
||||
// Mock the controller.
|
||||
sandbox.stub(uut.adapters.ipfsFiles, 'rpcHandler').resolves('true')
|
||||
|
||||
const result = await uut.router(str, 'peerA')
|
||||
// console.log(result)
|
||||
|
||||
const obj = JSON.parse(result.retStr)
|
||||
// console.log('obj: ', obj)
|
||||
|
||||
assert.equal(obj.result.value, 'true')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
|
||||
it('should route to about handler', async () => {
|
||||
const id = uid()
|
||||
@@ -188,6 +222,31 @@ describe('#JSON RPC', () => {
|
||||
assert.equal(obj.result.method, 'about')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
it('should route to bch handler', async () => {
|
||||
const id = uid()
|
||||
const userCall = jsonrpc.request(id, 'bch', { endpoint: 'getAll' })
|
||||
const jsonStr = JSON.stringify(userCall, null, 2)
|
||||
|
||||
// Mock the controller.
|
||||
sandbox.stub(uut.adapters.bch, 'rpcHandler').resolves('true')
|
||||
|
||||
// Force ipfs-coord communication.
|
||||
uut.ipfsCoord.ipfs = {
|
||||
orbitdb: {
|
||||
sendToDb: () => {}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await uut.router(jsonStr, 'peerA')
|
||||
// console.log(result)
|
||||
|
||||
const obj = JSON.parse(result.retStr)
|
||||
// console.log('obj: ', obj)
|
||||
|
||||
assert.equal(obj.result.value, 'true')
|
||||
assert.equal(obj.result.method, 'bch')
|
||||
assert.equal(obj.id, id)
|
||||
})
|
||||
|
||||
it('should exit quietly for duplicate RPC message', async () => {
|
||||
const id = uid()
|
||||
|
||||
@@ -79,11 +79,22 @@ describe('#Auth-REST-Router', () => {
|
||||
await uut.authUser(ctx)
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
it('should catch and throw passport error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox.stub(uut.passport, 'authUser').rejects('test error')
|
||||
|
||||
await uut.authUser(ctx)
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
assert.include(err.message, 'Unauthorized')
|
||||
}
|
||||
})
|
||||
it('should handle error if user is not found!', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox.stub(uut.passport, 'authUser').resolves(null)
|
||||
|
||||
await uut.authUser(ctx)
|
||||
} catch (err) {
|
||||
// console.log('err: ', err)
|
||||
|
||||
@@ -62,6 +62,18 @@ describe('#BCH-REST-Controller', () => {
|
||||
})
|
||||
|
||||
describe('#handleError', () => {
|
||||
it('should pass an error message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 422,
|
||||
message: 'Unprocessable Entity'
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Unprocessable Entity')
|
||||
}
|
||||
})
|
||||
it('should still throw error if there is no message', () => {
|
||||
try {
|
||||
const err = {
|
||||
@@ -467,4 +479,67 @@ describe('#BCH-REST-Controller', () => {
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getService', () => {
|
||||
it('should return 422 status on arbitrary error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter, 'state').value(null)
|
||||
ctx.request.body = {
|
||||
service: 'blah'
|
||||
}
|
||||
|
||||
await uut.getService(ctx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'Cannot read')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.adapters.ipfs.ipfsCoordAdapter, 'state').value({ selectedServiceProvider: 'selected service' })
|
||||
ctx.request.body = {
|
||||
service: 'selected service'
|
||||
}
|
||||
|
||||
await uut.getService(ctx)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#postProvider', () => {
|
||||
it('should return 422 status on arbitrary error', async () => {
|
||||
try {
|
||||
uut.config.freezeProvider = true
|
||||
ctx.request.body = {
|
||||
providerId: 'selected provider id'
|
||||
}
|
||||
|
||||
await uut.postProvider(ctx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'Consumer has preferredProvider set in environment variable. Refusing to switch providers.')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
uut.config.freezeProvider = false
|
||||
ctx.request.body = {
|
||||
providerId: 'selected provider id'
|
||||
}
|
||||
|
||||
sandbox.stub(uut.adapters.bch, 'selectProvider').resolves(true)
|
||||
await uut.postProvider(ctx)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -18,7 +18,7 @@ let sandbox
|
||||
|
||||
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||
|
||||
describe('#Users-REST-Router', () => {
|
||||
describe('#BCH-REST-Router', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -75,4 +75,108 @@ describe('#Users-REST-Router', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getStatus', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'getStatus').resolves(true)
|
||||
|
||||
await uut.getStatus()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postProvider', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'postProvider').resolves(true)
|
||||
|
||||
await uut.postProvider()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postBalance', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'balance').resolves(true)
|
||||
|
||||
await uut.postBalance()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postUtxos', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'utxos').resolves(true)
|
||||
|
||||
await uut.postUtxos()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postUtxosBulk', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'utxosBulk').resolves(true)
|
||||
|
||||
await uut.postUtxosBulk()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postBroadcast', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'broadcast').resolves(true)
|
||||
|
||||
await uut.postBroadcast()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postTxHistory', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'txHistory').resolves(true)
|
||||
|
||||
await uut.postTxHistory()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postTxData', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'txData').resolves(true)
|
||||
|
||||
await uut.postTxData()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postPubKey', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'pubKey').resolves(true)
|
||||
|
||||
await uut.postPubKey()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#utxoIsValid', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'utxoIsValid').resolves(true)
|
||||
|
||||
await uut.utxoIsValid()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#getTokenData', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'getTokenData').resolves(true)
|
||||
|
||||
await uut.getTokenData()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#getTokenData2', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'getTokenData2').resolves(true)
|
||||
|
||||
await uut.getTokenData2()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#getService', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.bchRESTController, 'getService').resolves(true)
|
||||
|
||||
await uut.getService()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Unit tests for the REST API handler for the /p2wdb endpoints.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
|
||||
// Local support libraries
|
||||
import adapters from '../../../mocks/adapters/index.js'
|
||||
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||
|
||||
import P2wdbController from '../../../../../src/controllers/rest-api/p2wdb/controller.js'
|
||||
import { context } from '../../../mocks/ctx-mock.js'
|
||||
// import blah '../../../../unit/mocks/ctx-mock.js'
|
||||
// console.log('blah: ', blah)
|
||||
let uut
|
||||
let sandbox
|
||||
let ctx
|
||||
|
||||
describe('#P2WDB-REST-Controller', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new P2wdbController({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
ctx = context()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new P2wdbController()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating /p2wdb REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new P2wdbController({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating /p2wdb REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#handleError', () => {
|
||||
it('should pass an error message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 422,
|
||||
message: 'Unprocessable Entity'
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Unprocessable Entity')
|
||||
}
|
||||
})
|
||||
it('should still throw error if there is no message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 404
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Not Found')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getStatus', () => {
|
||||
it('should return 422 status on arbitrary biz logic error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.adapters.p2wdb, 'getStatus')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
await uut.getStatus(ctx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.adapters.p2wdb, 'getStatus').resolves('p2wdb')
|
||||
|
||||
await uut.getStatus(ctx)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
|
||||
// Assert that expected properties exist in the returned data.
|
||||
assert.equal(ctx.response.body.status, 'p2wdb')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#postProvider', () => {
|
||||
it('should return 422 status on arbitrary error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.adapters.p2wdb, 'selectProvider')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
ctx.request.body = {
|
||||
addresses: 'blah'
|
||||
}
|
||||
|
||||
await uut.postProvider(ctx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.adapters.p2wdb, 'selectProvider').resolves({ status: 200 })
|
||||
|
||||
ctx.request.body = {
|
||||
addresses: 'blah'
|
||||
}
|
||||
|
||||
await uut.postProvider(ctx)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
describe('#getEntryByHash', () => {
|
||||
it('should return 422 status on arbitrary error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.adapters.p2wdb, 'getEntryByHash')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
ctx.request.body = {
|
||||
hash: 'blah'
|
||||
}
|
||||
|
||||
await uut.getEntryByHash(ctx)
|
||||
} catch (err) {
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.adapters.p2wdb, 'getEntryByHash').resolves({ status: 200 })
|
||||
|
||||
ctx.request.body = {
|
||||
hash: 'blah'
|
||||
}
|
||||
|
||||
await uut.getEntryByHash(ctx)
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#writeEntry', () => {
|
||||
it('should return 422 status on arbitrary error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.adapters.p2wdb, 'writeEntry')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
ctx.request.body = {
|
||||
txid: 'blah',
|
||||
signature: 'blah',
|
||||
message: 'blah',
|
||||
data: 'blah'
|
||||
}
|
||||
|
||||
await uut.writeEntry(ctx)
|
||||
} catch (err) {
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.adapters.p2wdb, 'writeEntry').resolves({ status: 200 })
|
||||
|
||||
ctx.request.body = {
|
||||
txid: 'blah',
|
||||
signature: 'blah',
|
||||
message: 'blah',
|
||||
data: 'blah'
|
||||
}
|
||||
|
||||
await uut.writeEntry(ctx)
|
||||
assert.equal(ctx.status, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Unit tests for the REST API handler for the /users endpoints.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
|
||||
// Local support libraries
|
||||
import adapters from '../../../mocks/adapters/index.js'
|
||||
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||
// const app = require('../../../mocks/app-mock')
|
||||
|
||||
import P2wdbRouter from '../../../../../src/controllers/rest-api/p2wdb/index.js'
|
||||
let uut
|
||||
let sandbox
|
||||
// let ctx
|
||||
|
||||
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||
|
||||
describe('#P2WDB-REST-Router', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new P2wdbRouter({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
// ctx = mockContext()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new P2wdbRouter()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating P2WDB REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new P2wdbRouter({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating P2WDB REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attach', () => {
|
||||
it('should throw an error if app is not passed in.', () => {
|
||||
try {
|
||||
uut.attach()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Must pass app object when attaching REST API controllers.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getStatus', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.p2wdbRESTController, 'getStatus').resolves(true)
|
||||
|
||||
await uut.getStatus()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#postProvider', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.p2wdbRESTController, 'postProvider').resolves(true)
|
||||
|
||||
await uut.postProvider()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#entryFromHash', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.p2wdbRESTController, 'getEntryByHash').resolves(true)
|
||||
|
||||
await uut.entryFromHash()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#write', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.p2wdbRESTController, 'writeEntry').resolves(true)
|
||||
|
||||
await uut.write()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Unit tests for the REST API handler for the /price endpoints.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
|
||||
// Local support libraries
|
||||
import adapters from '../../../mocks/adapters/index.js'
|
||||
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||
|
||||
import PriceController from '../../../../../src/controllers/rest-api/price/controller.js'
|
||||
import { context } from '../../../mocks/ctx-mock.js'
|
||||
// import blah '../../../../unit/mocks/ctx-mock.js'
|
||||
// console.log('blah: ', blah)
|
||||
let uut
|
||||
let sandbox
|
||||
let ctx
|
||||
|
||||
describe('#PRICE-REST-Controller', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new PriceController({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
ctx = context()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new PriceController()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating /price REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new PriceController({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating /price REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#handleError', () => {
|
||||
it('should pass an error message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 422,
|
||||
message: 'Unprocessable Entity'
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Unprocessable Entity')
|
||||
}
|
||||
})
|
||||
it('should still throw error if there is no message', () => {
|
||||
try {
|
||||
const err = {
|
||||
status: 404
|
||||
}
|
||||
|
||||
uut.handleError(ctx, err)
|
||||
} catch (err) {
|
||||
assert.include(err.message, 'Not Found')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getUSD', () => {
|
||||
it('should return 422 status on arbitrary biz logic error', async () => {
|
||||
try {
|
||||
// Force an error
|
||||
sandbox
|
||||
.stub(uut.axios, 'request')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
await uut.getUSD(ctx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
console.log('err: ', err)
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.axios, 'request').resolves({ data: { data: { rates: { USD: 1.00 } } } })
|
||||
|
||||
await uut.getUSD(ctx)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
|
||||
// Assert that expected properties exist in the returned data.
|
||||
assert.equal(ctx.response.body.usd, 1.00)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getXecPrice', () => {
|
||||
it('should return 422 status on arbitrary biz logic error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.axios, 'request').rejects(new Error('test error'))
|
||||
await uut.getXecPrice(ctx)
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.axios, 'request').resolves({ data: { data: { ticker: { last: 1.00 } } } })
|
||||
await uut.getXecPrice(ctx)
|
||||
assert.equal(ctx.status, 200)
|
||||
assert.equal(ctx.response.body.usd, 1.00)
|
||||
})
|
||||
})
|
||||
describe('#getPsffppWritePrice', () => {
|
||||
it('should return 200 status on success', async () => {
|
||||
sandbox.stub(uut.useCases.ipfs, 'getWritePrice').resolves(1.00)
|
||||
await uut.getPsffppWritePrice(ctx)
|
||||
assert.equal(ctx.status, 200)
|
||||
assert.equal(ctx.response.body.psfPrice, 1.00)
|
||||
})
|
||||
it('should return 422 status on arbitrary biz logic error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.useCases.ipfs, 'getWritePrice').rejects(new Error('test error'))
|
||||
await uut.getPsffppWritePrice(ctx)
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
assert.equal(err.status, 422)
|
||||
assert.include(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Unit tests for the REST API handler for the /users endpoints.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
|
||||
// Local support libraries
|
||||
import adapters from '../../../mocks/adapters/index.js'
|
||||
import UseCasesMock from '../../../mocks/use-cases/index.js'
|
||||
// const app = require('../../../mocks/app-mock')
|
||||
|
||||
import PriceRouter from '../../../../../src/controllers/rest-api/price/index.js'
|
||||
let uut
|
||||
let sandbox
|
||||
// let ctx
|
||||
|
||||
// const mockContext = require('../../../../unit/mocks/ctx-mock').context
|
||||
|
||||
describe('#Price-REST-Router', () => {
|
||||
// const testUser = {}
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
uut = new PriceRouter({ adapters, useCases })
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
|
||||
// Mock the context object.
|
||||
// ctx = mockContext()
|
||||
})
|
||||
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe('#constructor', () => {
|
||||
it('should throw an error if adapters are not passed in', () => {
|
||||
try {
|
||||
uut = new PriceRouter()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Adapters library required when instantiating Price REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error if useCases are not passed in', () => {
|
||||
try {
|
||||
uut = new PriceRouter({ adapters })
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Instance of Use Cases library required when instantiating Price REST Controller.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attach', () => {
|
||||
it('should throw an error if app is not passed in.', () => {
|
||||
try {
|
||||
uut.attach()
|
||||
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (err) {
|
||||
assert.include(
|
||||
err.message,
|
||||
'Must pass app object when attaching REST API controllers.'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#getPrice', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.priceRESTController, 'getUSD').resolves(true)
|
||||
|
||||
await uut.getPrice()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getXecPrice', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.priceRESTController, 'getXecPrice').resolves(true)
|
||||
|
||||
await uut.getXecPrice()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#getPsffppWritePrice', () => {
|
||||
it('should route to controller', async () => {
|
||||
const spy = sandbox.stub(uut.priceRESTController, 'getPsffppWritePrice').resolves(true)
|
||||
await uut.getPsffppWritePrice()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -20,7 +20,7 @@ describe('#RESTControllers', () => {
|
||||
let sandbox
|
||||
// let ctx
|
||||
|
||||
before(async () => {})
|
||||
before(async () => { })
|
||||
|
||||
beforeEach(() => {
|
||||
const useCases = new UseCasesMock()
|
||||
@@ -64,4 +64,19 @@ describe('#RESTControllers', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#attachRESTControllers', () => {
|
||||
it('should attach controllers without mongo service', () => {
|
||||
uut.config.noMongo = true
|
||||
|
||||
const app = { use: () => {} }
|
||||
uut.attachRESTControllers(app)
|
||||
})
|
||||
it('should attach controllers with mongo service', () => {
|
||||
uut.config.noMongo = false
|
||||
|
||||
const app = { use: () => {} }
|
||||
uut.attachRESTControllers(app)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -153,6 +153,20 @@ describe('#Users-REST-Controller', () => {
|
||||
// Assert that expected properties exist in the returned data.
|
||||
assert.property(ctx.response.body, 'user')
|
||||
})
|
||||
it('should run next function if it exists', async () => {
|
||||
// Mock dependencies
|
||||
const nextSpy = sandbox.spy()
|
||||
sandbox.stub(uut.useCases.user, 'getUser').resolves({ _id: '123' })
|
||||
|
||||
await uut.getUser(ctx, nextSpy)
|
||||
|
||||
// Assert the expected HTTP response
|
||||
assert.equal(ctx.status, 200)
|
||||
|
||||
// Assert that expected properties exist in the returned data.
|
||||
assert.property(ctx.response.body, 'user')
|
||||
assert.isTrue(nextSpy.calledOnce)
|
||||
})
|
||||
|
||||
it('should return other error status passed by biz logic', async () => {
|
||||
try {
|
||||
|
||||
@@ -107,4 +107,42 @@ describe('#Users-REST-Router', () => {
|
||||
assert.isTrue(validationSpy.calledOnce, 'Admin validator should be called')
|
||||
})
|
||||
})
|
||||
describe('#getAll', () => {
|
||||
it('should route to controller', async () => {
|
||||
sandbox.stub(uut.validators, 'ensureUser').resolves(true)
|
||||
const spy = sandbox.stub(uut.userRESTController, 'getUsers').resolves(true)
|
||||
|
||||
await uut.getAll()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#getById', () => {
|
||||
it('should route to controller', async () => {
|
||||
sandbox.stub(uut.validators, 'ensureUser').resolves(true)
|
||||
const spy = sandbox.stub(uut.userRESTController, 'getUser').resolves(true)
|
||||
|
||||
await uut.getById()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#updateUser', () => {
|
||||
it('should route to controller', async () => {
|
||||
sandbox.stub(uut.validators, 'ensureTargetUserOrAdmin').resolves(true)
|
||||
sandbox.stub(uut.userRESTController, 'getUser').resolves(true)
|
||||
const spy = sandbox.stub(uut.userRESTController, 'updateUser').resolves(true)
|
||||
|
||||
await uut.updateUser()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
describe('#deleteUser', () => {
|
||||
it('should route to controller', async () => {
|
||||
sandbox.stub(uut.validators, 'ensureTargetUserOrAdmin').resolves(true)
|
||||
sandbox.stub(uut.userRESTController, 'getUser').resolves(true)
|
||||
const spy = sandbox.stub(uut.userRESTController, 'deleteUser').resolves(true)
|
||||
|
||||
await uut.deleteUser()
|
||||
assert.isTrue(spy.calledOnce)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -9,12 +9,12 @@ let currentEnv
|
||||
describe('#config', () => {
|
||||
before(() => {
|
||||
// Backup the current environment setting.
|
||||
currentEnv = process.env.SVC_ENV
|
||||
currentEnv = process.env.CONSUMER_ENV
|
||||
})
|
||||
|
||||
after(() => {
|
||||
// Restore the environment setting before starting these tests.
|
||||
process.env.SVC_ENV = currentEnv
|
||||
process.env.CONSUMER_ENV = currentEnv
|
||||
})
|
||||
|
||||
it('Should return development environment config by default', async () => {
|
||||
@@ -29,7 +29,7 @@ describe('#config', () => {
|
||||
// Hack to dynamically import a library multiple times:
|
||||
// https://github.com/denoland/deno/issues/6946
|
||||
|
||||
process.env.SVC_ENV = 'test'
|
||||
process.env.CONSUMER_ENV = 'test'
|
||||
|
||||
const importedConfig2 = await import('../../../config/index.js?foo=bar1')
|
||||
const config = importedConfig2.default
|
||||
@@ -39,7 +39,7 @@ describe('#config', () => {
|
||||
})
|
||||
|
||||
it('Should return prod environment config', async () => {
|
||||
process.env.SVC_ENV = 'prod'
|
||||
process.env.CONSUMER_ENV = 'prod'
|
||||
|
||||
process.env.WALLET_INTERFACE = 'web2'
|
||||
process.env.APISERVER = 'https://api.fullstack.cash/v5/'
|
||||
|
||||
@@ -34,6 +34,12 @@ describe('#passport', () => {
|
||||
|
||||
passportCallback(id, 'password', done)
|
||||
})
|
||||
it('should handle not found user', () => {
|
||||
// Mock Users model.
|
||||
sandbox.stub(User, 'findOne').resolves(null)
|
||||
|
||||
passportCallback(id, 'password', done)
|
||||
})
|
||||
|
||||
it('should return if password is validated', () => {
|
||||
// Mock Users model.
|
||||
@@ -41,6 +47,15 @@ describe('#passport', () => {
|
||||
|
||||
passportCallback(id, 'password', done)
|
||||
})
|
||||
it('should handle error on password validation', () => {
|
||||
// Mock Users model.
|
||||
const userMock = {
|
||||
validatePassword: () => false
|
||||
}
|
||||
sandbox.stub(User, 'findOne').resolves(userMock)
|
||||
|
||||
passportCallback(id, 'password', done)
|
||||
})
|
||||
|
||||
it('should catch a high-level error', () => {
|
||||
// Force an error
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('#server', () => {
|
||||
sandbox.stub(uut.adminLib, 'createSystemUser').resolves(true)
|
||||
sandbox.stub(uut.controllers, 'attachControllers').resolves()
|
||||
uut.config.env = 'dev'
|
||||
|
||||
uut.config.port = 5040
|
||||
const result = await uut.startServer()
|
||||
// console.log('result: ', result)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class IpfsAdapter {
|
||||
|
||||
class IpfsCoordAdapter {
|
||||
constructor () {
|
||||
|
||||
this.config = {}
|
||||
this.ipfsCoord = {
|
||||
adapters: {
|
||||
ipfs: {
|
||||
@@ -97,6 +97,39 @@ const localdb = {
|
||||
}
|
||||
},
|
||||
|
||||
Usage: class Usage {
|
||||
static findById () {}
|
||||
static find () {}
|
||||
static findOne () {
|
||||
return {
|
||||
validatePassword: localdb.validatePassword
|
||||
}
|
||||
}
|
||||
|
||||
async save () {
|
||||
return {}
|
||||
}
|
||||
|
||||
generateToken () {
|
||||
return '123'
|
||||
}
|
||||
|
||||
toJSON () {
|
||||
return {}
|
||||
}
|
||||
|
||||
async remove () {
|
||||
return true
|
||||
}
|
||||
|
||||
async validatePassword () {
|
||||
return true
|
||||
}
|
||||
static async deleteMany(){
|
||||
return true
|
||||
}
|
||||
},
|
||||
|
||||
validatePassword: () => {
|
||||
return true
|
||||
}
|
||||
@@ -154,6 +187,9 @@ class BchUseCaseMock {
|
||||
async waitForRPCResponse () {
|
||||
return {}
|
||||
}
|
||||
async selectProvider (){
|
||||
return true
|
||||
}
|
||||
}
|
||||
const bch = new BchUseCaseMock()
|
||||
const wallet = {
|
||||
@@ -179,6 +215,18 @@ const ipfsFiles = {
|
||||
success: true,
|
||||
message: 'Pins'
|
||||
}
|
||||
},
|
||||
rpcHandler: () => {
|
||||
return {
|
||||
success: true,
|
||||
message: 'RPC handler'
|
||||
}
|
||||
}
|
||||
}
|
||||
export default { ipfs, localdb, bch, wallet, ipfsFiles }
|
||||
const p2wdb = {
|
||||
getStatus: async () => {},
|
||||
selectProvider: async () => {},
|
||||
getEntryByHash: async () => {},
|
||||
writeEntry: async () => {}
|
||||
}
|
||||
export default { ipfs, localdb, bch, wallet, ipfsFiles, p2wdb }
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
const peers = [
|
||||
'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'QmQqjVVD3CS6zaJmoSdt6GwX1c1tD5T9FZas4qxLbru8xN'
|
||||
'QmQqjVVD3CS6zaJmoSdt6GwX1c1tD5T9FZas4qxLbru8xN',
|
||||
'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mT3',
|
||||
'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mD4'
|
||||
]
|
||||
|
||||
const peerData = [
|
||||
@@ -110,7 +112,113 @@ const peerData = [
|
||||
},
|
||||
updatedAt: '2021-08-24T23:13:20.411Z'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
from: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mT3',
|
||||
channel: 'psf-ipfs-coordination-001',
|
||||
data: {
|
||||
apiName: 'ipfs-coord-announce',
|
||||
apiVersion: '1.3.2',
|
||||
apiInfo:
|
||||
'You should put an IPFS hash or web URL here to your documentation.',
|
||||
ipfsId: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
type: 'node.js',
|
||||
ipfsMultiaddrs: [
|
||||
'/ip4/127.0.0.1/tcp/5701/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/127.0.0.1/tcp/5702/ws/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/192.168.0.2/tcp/5701/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/192.168.0.2/tcp/5702/ws/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2'
|
||||
],
|
||||
orbitdb:
|
||||
'/orbitdb/zdpuAntCMCcmZuFy2hq5F7kpcti3yHa34LLZHzyVqorkoSpAJ/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ221082417',
|
||||
circuitRelays: [],
|
||||
isCircuitRelay: false,
|
||||
cryptoAddresses: [
|
||||
{
|
||||
blockchain: 'BCH',
|
||||
type: 'cashAddr',
|
||||
address: 'bitcoincash:qru6kq3p4tv6z2lmy0n560lyhh3z2feay5gjzggc37'
|
||||
},
|
||||
{
|
||||
blockchain: 'BCH',
|
||||
type: 'slpAddr',
|
||||
address: 'simpleledger:qru6kq3p4tv6z2lmy0n560lyhh3z2feay5yffnac0q'
|
||||
}
|
||||
],
|
||||
encryptPubKey:
|
||||
'021db6e97650659653ba61dd493dc348a7429cdcbafd4fb73b08b1223bf5bd98df',
|
||||
jsonLd: {
|
||||
'@context': 'https://schema.org/',
|
||||
'@type': 'WebAPI',
|
||||
name: 'trout-bch-wallet-service-dev',
|
||||
version: '1.11.12',
|
||||
protocol: 'p2wdb',
|
||||
description:
|
||||
'IPFS service providing BCH blockchain access needed by a wallet.',
|
||||
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
|
||||
provider: {
|
||||
'@type': 'Organization',
|
||||
name: 'Permissionless Software Foundation',
|
||||
url: 'https://PSFoundation.cash'
|
||||
},
|
||||
identifier: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2'
|
||||
},
|
||||
updatedAt: '2021-08-24T23:13:19.306Z'
|
||||
}
|
||||
},
|
||||
{
|
||||
from: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mD4',
|
||||
channel: 'psf-ipfs-coordination-001',
|
||||
data: {
|
||||
apiName: 'ipfs-coord-announce',
|
||||
apiVersion: '1.3.2',
|
||||
apiInfo:
|
||||
'You should put an IPFS hash or web URL here to your documentation.',
|
||||
ipfsId: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
type: 'node.js',
|
||||
ipfsMultiaddrs: [
|
||||
'/ip4/127.0.0.1/tcp/5701/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/127.0.0.1/tcp/5702/ws/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/192.168.0.2/tcp/5701/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2',
|
||||
'/ip4/192.168.0.2/tcp/5702/ws/p2p/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2'
|
||||
],
|
||||
orbitdb:
|
||||
'/orbitdb/zdpuAntCMCcmZuFy2hq5F7kpcti3yHa34LLZHzyVqorkoSpAJ/QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ221082417',
|
||||
circuitRelays: [],
|
||||
isCircuitRelay: false,
|
||||
cryptoAddresses: [
|
||||
{
|
||||
blockchain: 'BCH',
|
||||
type: 'cashAddr',
|
||||
address: 'bitcoincash:qru6kq3p4tv6z2lmy0n560lyhh3z2feay5gjzggc37'
|
||||
},
|
||||
{
|
||||
blockchain: 'BCH',
|
||||
type: 'slpAddr',
|
||||
address: 'simpleledger:qru6kq3p4tv6z2lmy0n560lyhh3z2feay5yffnac0q'
|
||||
}
|
||||
],
|
||||
encryptPubKey:
|
||||
'021db6e97650659653ba61dd493dc348a7429cdcbafd4fb73b08b1223bf5bd98df',
|
||||
jsonLd: {
|
||||
'@context': 'https://schema.org/',
|
||||
'@type': 'WebAPI',
|
||||
name: 'trout-bch-wallet-service-dev',
|
||||
version: '1.11.12',
|
||||
protocol: 'ipfs-file-pin-service',
|
||||
description:
|
||||
'IPFS service providing BCH blockchain access needed by a wallet.',
|
||||
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
|
||||
provider: {
|
||||
'@type': 'Organization',
|
||||
name: 'Permissionless Software Foundation',
|
||||
url: 'https://PSFoundation.cash'
|
||||
},
|
||||
identifier: 'QmWkjYRRTaxVEuGK8ip2X3trVyJShFs6U9g1h9x6fK5mZ2'
|
||||
},
|
||||
updatedAt: '2021-08-24T23:13:19.306Z'
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
// module.exports = {
|
||||
|
||||
@@ -95,6 +95,10 @@ class IpfsUseCaseMock {
|
||||
async pinClaim() {
|
||||
return {}
|
||||
}
|
||||
|
||||
async getWritePrice() {
|
||||
return 1.00
|
||||
}
|
||||
}
|
||||
|
||||
class UseCasesMock {
|
||||
|
||||
@@ -14,7 +14,6 @@ import sinon from 'sinon'
|
||||
import UseCases from '../../../src/use-cases/ipfs-use-cases.js'
|
||||
|
||||
import adapters from '../mocks/adapters/index.js'
|
||||
|
||||
describe('#ipfs-use-cases', () => {
|
||||
let uut
|
||||
let sandbox
|
||||
@@ -92,15 +91,28 @@ describe('#ipfs-use-cases', () => {
|
||||
const result = await uut.getWritePrice()
|
||||
assert.isNumber(result)
|
||||
})
|
||||
it('should re-instantiate psffpp instance', async () => {
|
||||
const psffppMock = {}
|
||||
uut.psffpp = psffppMock
|
||||
const lastWritePriceUpdate = new Date()
|
||||
lastWritePriceUpdate.setHours(lastWritePriceUpdate.getHours() - 10)
|
||||
uut.lastWritePriceUpdate = lastWritePriceUpdate.getTime()
|
||||
const result = await uut.getWritePrice()
|
||||
assert.isNumber(result)
|
||||
assert.notEqual(uut.lastWritePriceUpdate, lastWritePriceUpdate.getTime())
|
||||
assert.notEqual(uut.psffpp, psffppMock)
|
||||
})
|
||||
|
||||
it('should handle error ', async () => {
|
||||
try {
|
||||
uut.lastWritePriceUpdate = new Date().getTime()
|
||||
uut.psffpp = {
|
||||
getMcWritePrice: () => {
|
||||
throw new Error('test error')
|
||||
}
|
||||
}
|
||||
await uut.getWritePrice()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.include(error.message, 'test error')
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('#usage-use-case', () => {
|
||||
sandbox = sinon.createSandbox()
|
||||
uut = new UsageUseCases({ adapters })
|
||||
|
||||
console.log('restCalls: ', restCalls)
|
||||
// Set as empty array
|
||||
restCalls.splice(0, restCalls.length)
|
||||
|
||||
@@ -255,4 +256,67 @@ describe('#usage-use-case', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('#clearUsage', () => {
|
||||
it('should clear the usage database data', async () => {
|
||||
const res = await uut.clearUsage()
|
||||
assert.isTrue(res)
|
||||
})
|
||||
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
sandbox.stub(uut.UsageModel, 'deleteMany').throws(new Error('uut error'))
|
||||
await uut.clearUsage()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
assert.equal(error.message, 'uut error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#saveUsage', () => {
|
||||
it('should save usage', async () => {
|
||||
// Set mock data
|
||||
restCalls.push({
|
||||
timestamp: new Date().getTime(),
|
||||
ip: 'localhost',
|
||||
url: 'fakeUrl',
|
||||
method: 'unit test'
|
||||
})
|
||||
const res = await uut.saveUsage()
|
||||
assert.isTrue(res)
|
||||
})
|
||||
|
||||
it('should handle error', async () => {
|
||||
try {
|
||||
restCalls.push(null)
|
||||
await uut.saveUsage()
|
||||
assert.fail('Unexpected code path')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
assert.include(error.message, 'Cannot read properties')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#loadUsage', () => {
|
||||
it('should load usage', async () => {
|
||||
// Set mock data
|
||||
const mockObj = {
|
||||
timestamp: new Date().getTime(),
|
||||
ip: 'localhost',
|
||||
url: 'fakeUrl',
|
||||
method: 'unit test'
|
||||
}
|
||||
sandbox.stub(uut.UsageModel, 'find').returns(new Array(10).fill(null).map((_, i) => (mockObj)))
|
||||
const res = await uut.loadUsage()
|
||||
assert.equal(restCalls.length, 10)
|
||||
assert.equal(res.length, 10)
|
||||
})
|
||||
|
||||
it('should skip error', async () => {
|
||||
sandbox.stub(uut.UsageModel, 'find').throws(new Error('uut error'))
|
||||
const res = await uut.loadUsage()
|
||||
assert.isFalse(res)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user