diff --git a/package.json b/package.json index 216fc76085..09e22b9547 100644 --- a/package.json +++ b/package.json @@ -173,7 +173,7 @@ "pull-defer": "~0.2.3", "pull-file": "^1.1.0", "pull-mplex": "~0.1.1", - "pull-ndjson": "~0.1.1", + "pull-ndjson": "^0.2.0", "pull-pushable": "^2.2.0", "pull-sort": "^1.0.1", "pull-stream": "^3.6.14", diff --git a/src/core/components/pubsub.js b/src/core/components/pubsub.js index fff4435844..8c5916b906 100644 --- a/src/core/components/pubsub.js +++ b/src/core/components/pubsub.js @@ -33,7 +33,11 @@ module.exports = function pubsub (self) { return } - checkOnlineAndEnabled() + try { + checkOnlineAndEnabled() + } catch (err) { + return Promise.reject(err) + } return self.libp2p.pubsub.subscribe(topic, handler, options) }, @@ -50,7 +54,11 @@ module.exports = function pubsub (self) { return } - checkOnlineAndEnabled() + try { + checkOnlineAndEnabled() + } catch (err) { + return Promise.reject(err) + } return self.libp2p.pubsub.unsubscribe(topic, handler) }, diff --git a/src/http/api/resources/files-regular.js b/src/http/api/resources/files-regular.js index ea711cfc18..4aadc8f041 100644 --- a/src/http/api/resources/files-regular.js +++ b/src/http/api/resources/files-regular.js @@ -336,6 +336,12 @@ exports.refs = { const unique = request.query.unique const maxDepth = request.query['max-depth'] + // have to do this here otherwise the validation error appears in the stream tail and + // this doesn't work in browsers: https://github.com/ipfs/js-ipfs/issues/2519 + if (edges && format !== Format.default) { + throw Boom.badRequest('Cannot set edges to true and also specify format') + } + const source = ipfs.refsPullStream(key, { recursive, format, edges, unique, maxDepth }) return sendRefsReplyStream(request, h, `refs for ${key}`, source) } diff --git a/test/cli/daemon.js b/test/cli/daemon.js index 0bee3e507e..7dbe89f9d8 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -104,14 +104,12 @@ describe('daemon', () => { } }) - try { - await daemon - throw new Error('Did not kill process') - } catch (err) { - expect(err.killed).to.be.true() - - expect(stdout).to.include('Daemon is ready') - } + await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true + }) + .and.to.have.property('stdout').that.includes('Daemon is ready') }) it('should allow bind to multiple addresses for API and Gateway', async function () { @@ -142,15 +140,14 @@ describe('daemon', () => { } }) - try { - await daemon - throw new Error('Did not kill process') - } catch (err) { - expect(err.killed).to.be.true() + const err = await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true + }) - apiAddrs.forEach(addr => expect(err.stdout).to.include(`API listening on ${addr.slice(0, -2)}`)) - gatewayAddrs.forEach(addr => expect(err.stdout).to.include(`Gateway (read only) listening on ${addr.slice(0, -2)}`)) - } + apiAddrs.forEach(addr => expect(err.stdout).to.include(`API listening on ${addr.slice(0, -2)}`)) + gatewayAddrs.forEach(addr => expect(err.stdout).to.include(`Gateway (read only) listening on ${addr.slice(0, -2)}`)) }) it('should allow no bind addresses for API and Gateway', async function () { @@ -171,15 +168,12 @@ describe('daemon', () => { } }) - try { - await daemon - throw new Error('Did not kill process') - } catch (err) { - expect(err.killed).to.be.true() - - expect(err.stdout).to.not.include('API listening on') - expect(err.stdout).to.not.include('Gateway (read only) listening on') - } + await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true + }) + .and.have.property('stdout').that.does.not.include(/(API|Gateway \(read only\)) listening on/g) }) skipOnWindows('should handle SIGINT gracefully', async function () { @@ -211,32 +205,17 @@ describe('daemon', () => { await ipfs('init') const daemon = ipfs('daemon --silent') - const stop = async (err) => { - daemon.kill() - if (err) { - throw err - } + setTimeout(() => { + daemon.kill('SIGKILL') + }, 5 * 1000) - try { - await daemon - } catch (err) { - if (!err.killed) { - throw err - } - } - } - - return new Promise((resolve, reject) => { - daemon.stdout.on('data', (data) => { - reject(new Error('Output was received ' + data.toString('utf8'))) + await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true, + stdout: '' }) - - setTimeout(() => { - resolve() - }, 5 * 1000) - }) - .then(stop, stop) }) it('should present ipfs path help when option help is received', async function () { @@ -262,16 +241,15 @@ describe('daemon', () => { } }) - try { - await daemon - throw new Error('Did not kill process') - } catch (err) { - expect(err.killed).to.be.true() + const err = await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true + }) - expect(err.stdout).to.include(`js-ipfs version: ${pkg.version}`) - expect(err.stdout).to.include(`System version: ${os.arch()}/${os.platform()}`) - expect(err.stdout).to.include(`Node.js version: ${process.versions.node}`) - } + expect(err.stdout).to.include(`js-ipfs version: ${pkg.version}`) + expect(err.stdout).to.include(`System version: ${os.arch()}/${os.platform()}`) + expect(err.stdout).to.include(`Node.js version: ${process.versions.node}`) }) it('should init by default', async function () { @@ -290,12 +268,11 @@ describe('daemon', () => { } }) - try { - await daemon - throw new Error('Did not kill process') - } catch (err) { - expect(err.killed).to.be.true() - } + await expect(daemon) + .to.eventually.be.rejected() + .and.to.include({ + killed: true + }) expect(fs.existsSync(repoPath)).to.be.true() }) diff --git a/test/cli/init.js b/test/cli/init.js index 97bb486fbc..d3614a18f1 100644 --- a/test/cli/init.js +++ b/test/cli/init.js @@ -83,11 +83,9 @@ describe('init', function () { it('profile non-existent', async function () { this.timeout(40 * 1000) - try { - await ipfs('init --profile doesnt-exist') - } catch (err) { - expect(err.stdout).includes('Could not find profile') - } + await expect(ipfs('init --profile doesnt-exist')) + .to.eventually.be.rejected() + .and.to.have.property('stdout').that.includes('Could not find profile') }) it('should present ipfs path help when option help is received', async function () { diff --git a/test/core/create-node.spec.js b/test/core/create-node.spec.js index 7d77fc7ded..a59a0e9b0f 100644 --- a/test/core/create-node.spec.js +++ b/test/core/create-node.spec.js @@ -171,20 +171,14 @@ describe('create node', function () { expect(ipfs.isOnline()).to.be.false() - try { - await ipfs.ready - } catch (err) { - expect(ipfs.isOnline()).to.be.false() - - // After the error has occurred, it should still reject - try { - await ipfs.ready - } catch (_) { - return - } - } + await expect(ipfs.ready) + .to.eventually.be.rejected() + + expect(ipfs.isOnline()).to.be.false() - throw new Error('ready promise did not reject') + // After the error has occurred, it should still reject + await expect(ipfs.ready) + .to.eventually.be.rejected() }) it('should create a ready node with IPFS.create', async () => { diff --git a/test/core/dht.spec.js b/test/core/dht.spec.js index d8fde46d18..b2e5c2d04a 100644 --- a/test/core/dht.spec.js +++ b/test/core/dht.spec.js @@ -74,16 +74,10 @@ describe.skip('dht', () => { }) describe('put', () => { - it('should callback with error for DHT not available', async () => { - let res - try { - res = await ipfs.dht.put(Buffer.from('a'), Buffer.from('b')) - } catch (err) { - expect(err).to.exist() - expect(err.code).to.equal('ERR_DHT_DISABLED') - } - - expect(res).to.not.exist() + it('should error when DHT not available', async () => { + await expect(ipfs.dht.put(Buffer.from('a'), Buffer.from('b'))) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_DHT_DISABLED') }) }) }) diff --git a/test/core/gc.spec.js b/test/core/gc.spec.js index 42022f3fed..fef9c208bb 100644 --- a/test/core/gc.spec.js +++ b/test/core/gc.spec.js @@ -7,7 +7,6 @@ const IPFSFactory = require('ipfsd-ctl') const pEvent = require('p-event') const env = require('ipfs-utils/src/env') const IPFS = require('../../src/core') -const { Errors } = require('interface-datastore') // We need to detect when a readLock or writeLock is requested for the tests // so we override the Mutex class to emit an event @@ -189,11 +188,11 @@ describe('gc', function () { await rm1 // Second rm should fail because GC has already removed that block - try { - await rm2 - } catch (err) { - expect(err.code).eql(Errors.dbDeleteFailedError().code) - } + const results = await rm2 + const result = results + .filter(result => result.hash === cid2.toString()) + .pop() + expect(result).to.have.property('error').that.contains('block not found') // Confirm second block has been removed const localRefs = (await ipfs.refs.local()).map(r => r.ref) diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index f159db7a02..139729dc36 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -11,7 +11,6 @@ const Multiplex = require('pull-mplex') const SECIO = require('libp2p-secio') const KadDHT = require('libp2p-kad-dht') const Libp2p = require('libp2p') -const isNode = require('detect-node') const libp2pComponent = require('../../src/core/components/libp2p') @@ -315,40 +314,5 @@ describe('libp2p customization', function () { done() }) }) - - it('select floodsub as pubsub router if node', (done) => { - const ipfs = { - _repo: { - datastore - }, - _peerInfo: peerInfo, - _peerBook: peerBook, - // eslint-disable-next-line no-console - _print: console.log, - _options: {} - } - const customConfig = { - ...testConfig, - Pubsub: { - Router: 'floodsub' - } - } - - try { - _libp2p = libp2pComponent(ipfs, customConfig) - } catch (err) { - if (!isNode) { - expect(err).to.exist() - expect(err.code).to.eql('ERR_NOT_SUPPORTED') - done() - } - } - - _libp2p.start((err) => { - expect(err).to.not.exist() - expect(_libp2p._modules.pubsub).to.eql(require('libp2p-floodsub')) - done() - }) - }) }) }) diff --git a/test/core/name-pubsub.js b/test/core/name-pubsub.js index 0e5fdd59ad..9d886d461a 100644 --- a/test/core/name-pubsub.js +++ b/test/core/name-pubsub.js @@ -106,8 +106,9 @@ describe('name-pubsub', function () { const keys = ipns.getIdKeys(fromB58String(idA.id)) const topic = `${namespace}${base64url.encode(keys.routingKey.toBuffer())}` - await nodeB.name.resolve(idA.id) - .then(() => expect.fail('should not have been able to resolve idA.id'), (err) => expect(err).to.exist()) + await expect(nodeB.name.resolve(idA.id)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_NO_RECORD_FOUND') await waitForPeerToSubscribe(nodeA, topic) await nodeB.pubsub.subscribe(topic, checkMessage) @@ -128,11 +129,9 @@ describe('name-pubsub', function () { const resolvesEmpty = await nodeB.name.resolve(idB.id) expect(resolvesEmpty).to.be.eq(emptyDirCid) - try { - await nodeA.name.resolve(idB.id) - } catch (error) { - expect(error).to.exist() - } + await expect(nodeA.name.resolve(idB.id)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_NO_RECORD_FOUND') const publish = await nodeB.name.publish(path) expect(publish).to.be.eql({ diff --git a/test/core/name.spec.js b/test/core/name.spec.js index f1da264e9d..edad61d17e 100644 --- a/test/core/name.spec.js +++ b/test/core/name.spec.js @@ -209,127 +209,109 @@ describe('name', function () { }) it('should error to publish if does not receive private key', function () { - return node._ipns.publisher.publish(null, ipfsRef) - .then(() => expect.fail('should have thrown when private key was missing'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_INVALID_PRIVATE_KEY') - }) + return expect(node._ipns.publisher.publish(null, ipfsRef)) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_PRIVATE_KEY') }) it('should error to publish if an invalid private key is received', function () { - return node._ipns.publisher.publish({ bytes: 'not that valid' }, ipfsRef) - .then(() => expect.fail('should have thrown when private key was invalid'), (err) => { - expect(err).to.exist() - }) + return expect(node._ipns.publisher.publish({ bytes: 'not that valid' }, ipfsRef)) + .to.eventually.be.rejected() + // .that.eventually.has.property('code', 'ERR_INVALID_PRIVATE_KEY') TODO: libp2p-crypto needs to throw err-code }) - it('should error to publish if _updateOrCreateRecord fails', function () { - const stub = sinon.stub(node._ipns.publisher, '_updateOrCreateRecord').callsArgWith(4, 'error') + it('should error to publish if _updateOrCreateRecord fails', async function () { + const err = new Error('error') + const stub = sinon.stub(node._ipns.publisher, '_updateOrCreateRecord').rejects(err) - return node.name.publish(ipfsRef, { resolve: false }) - .then(() => expect.fail('should have thrown when _updateOrCreateRecord fails'), (err) => { - expect(err).to.exist() + await expect(node.name.publish(ipfsRef, { resolve: false })) + .to.eventually.be.rejectedWith(err) - stub.restore() - }) + stub.restore() }) it('should error to publish if _putRecordToRouting receives an invalid peer id', function () { - return node._ipns.publisher._putRecordToRouting(undefined, undefined) - .then(() => expect.fail('should have thrown if peer id was invalid'), (err) => { - expect(err).to.exist() - }) + return expect(node._ipns.publisher._putRecordToRouting(undefined, undefined)) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_PEER_ID') }) - it('should error to publish if receives an invalid datastore key', function () { + it('should error to publish if receives an invalid datastore key', async function () { const stub = sinon.stub(Key, 'isKey').returns(false) - return node.name.publish(ipfsRef, { resolve: false }) - .then(() => expect.fail('should have thrown if datastore key was invalid'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_INVALID_DATASTORE_KEY') + await expect(node.name.publish(ipfsRef, { resolve: false })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_DATASTORE_KEY') - stub.restore() - }) + stub.restore() }) - it('should error to publish if we receive a unexpected error getting from datastore', function () { - const stub = sinon.stub(node._ipns.publisher._datastore, 'get').callsArgWith(1, 'error-unexpected') + it('should error to publish if we receive a unexpected error getting from datastore', async function () { + const stub = sinon.stub(node._ipns.publisher._datastore, 'get').throws(new Error('error-unexpected')) - return node.name.publish(ipfsRef, { resolve: false }) - .then(() => expect.fail('should have thrown if an unexpected error was received when getting from the datastore'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_DETERMINING_PUBLISHED_RECORD') + await expect(node.name.publish(ipfsRef, { resolve: false })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_DETERMINING_PUBLISHED_RECORD') - stub.restore() - }) + stub.restore() }) - it('should error to publish if we receive a unexpected error putting to datastore', function () { - const stub = sinon.stub(node._ipns.publisher._datastore, 'put').callsArgWith(2, 'error-unexpected') + it('should error to publish if we receive a unexpected error putting to datastore', async function () { + const stub = sinon.stub(node._ipns.publisher._datastore, 'put').throws(new Error('error-unexpected')) - return node.name.publish(ipfsRef, { resolve: false }) - .then(() => expect.fail('should have thrown if an unexpected error was received when putting to the datastore'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_STORING_IN_DATASTORE') + await expect(node.name.publish(ipfsRef, { resolve: false })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_STORING_IN_DATASTORE') - stub.restore() - }) + stub.restore() }) it('should error to resolve if the received name is not a string', function () { - return node._ipns.resolver.resolve(false) - .then(() => expect.fail('should have thrown if the received name is not a string'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_INVALID_NAME') - }) + return expect(node._ipns.resolver.resolve(false)) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_NAME') }) it('should error to resolve if receives an invalid ipns path', function () { - return node._ipns.resolver.resolve('ipns/') - .then(() => expect.fail('should have thrown if the IPNS path was invalid'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_INVALID_NAME') - }) + return expect(node._ipns.resolver.resolve('ipns/')) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_NAME') }) it('should publish and then fail to resolve if receive error getting from datastore', async function () { - const stub = sinon.stub(node._ipns.resolver._routing, 'get').callsArgWith(1, 'error-unexpected') + const stub = sinon.stub(node._ipns.resolver._routing, 'get').throws(new Error('error-unexpected')) await node.name.publish(ipfsRef, { resolve: false }) - return node.name.resolve(nodeId, { nocache: true }) - .then(() => expect.fail('should have thrown when an invalid response was received from the datastore'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_UNEXPECTED_ERROR_GETTING_RECORD') - stub.restore() - }) + await expect(node.name.resolve(nodeId, { nocache: true })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_UNEXPECTED_ERROR_GETTING_RECORD') + + stub.restore() }) it('should publish and then fail to resolve if does not find the record', async function () { - const stub = sinon.stub(node._ipns.resolver._routing, 'get').callsArgWith(1, { code: Errors.notFoundError().code }) + const stub = sinon.stub(node._ipns.resolver._routing, 'get').throws(Errors.notFoundError()) await node.name.publish(ipfsRef, { resolve: false }) - return node.name.resolve(nodeId, { nocache: true }) - .then(() => expect.fail('should have thrown when failing to find the record after publish'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_UNEXPECTED_ERROR_GETTING_RECORD') - stub.restore() - }) + await expect(node.name.resolve(nodeId, { nocache: true })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_NO_RECORD_FOUND') + + stub.restore() }) it('should publish and then fail to resolve if does not receive a buffer', async function () { - const stub = sinon.stub(node._ipns.resolver._routing, 'get').callsArgWith(1, undefined, 'data') + const stub = sinon.stub(node._ipns.resolver._routing, 'get').resolves('not-a-buffer') await node.name.publish(ipfsRef, { resolve: false }) - return node.name.resolve(nodeId, { nocache: true }) - .then(() => expect.fail('should have thrown if a buffer was not recieved'), (err) => { - expect(err).to.exist() - expect(err.code).to.equal('ERR_UNEXPECTED_ERROR_GETTING_RECORD') - stub.restore() - }) + await expect(node.name.resolve(nodeId, { nocache: true })) + .to.eventually.be.rejected() + .with.property('code', 'ERR_INVALID_RECORD_RECEIVED') + + stub.restore() }) }) diff --git a/test/core/pubsub.spec.js b/test/core/pubsub.spec.js index 1fc46623bc..32d4d89427 100644 --- a/test/core/pubsub.spec.js +++ b/test/core/pubsub.spec.js @@ -48,14 +48,12 @@ describe('pubsub disabled', () => { }) it('should not allow subscribe if disabled (promised)', async () => { - try { - const topic = hat() - const handler = () => { throw new Error('unexpected message') } - await ipfs.pubsub.subscribe(topic, handler) - } catch (err) { - return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') - } - throw new Error('expected error to be thrown') + const topic = hat() + const handler = () => { throw new Error('unexpected message') } + + await expect(ipfs.pubsub.subscribe(topic, handler)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_PUBSUB_DISABLED') }) it('should not allow unsubscribe if disabled', done => { @@ -69,14 +67,12 @@ describe('pubsub disabled', () => { }) it('should not allow unsubscribe if disabled (promised)', async () => { - try { - const topic = hat() - const handler = () => { throw new Error('unexpected message') } - await ipfs.pubsub.unsubscribe(topic, handler) - } catch (err) { - return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') - } - throw new Error('expected error to be thrown') + const topic = hat() + const handler = () => { throw new Error('unexpected message') } + + await expect(ipfs.pubsub.unsubscribe(topic, handler)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_PUBSUB_DISABLED') }) it('should not allow publish if disabled', done => { @@ -90,14 +86,12 @@ describe('pubsub disabled', () => { }) it('should not allow publish if disabled (promised)', async () => { - try { - const topic = hat() - const msg = Buffer.from(hat()) - await ipfs.pubsub.publish(topic, msg) - } catch (err) { - return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') - } - throw new Error('expected error to be thrown') + const topic = hat() + const msg = Buffer.from(hat()) + + await expect(ipfs.pubsub.publish(topic, msg)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_PUBSUB_DISABLED') }) it('should not allow ls if disabled', done => { @@ -109,12 +103,9 @@ describe('pubsub disabled', () => { }) it('should not allow ls if disabled (promised)', async () => { - try { - await ipfs.pubsub.ls() - } catch (err) { - return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') - } - throw new Error('expected error to be thrown') + await expect(ipfs.pubsub.ls()) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_PUBSUB_DISABLED') }) it('should not allow peers if disabled', done => { @@ -127,18 +118,16 @@ describe('pubsub disabled', () => { }) it('should not allow peers if disabled (promised)', async () => { - try { - const topic = hat() - await ipfs.pubsub.peers(topic) - } catch (err) { - return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') - } - throw new Error('expected error to be thrown') + const topic = hat() + + await expect(ipfs.pubsub.peers(topic)) + .to.eventually.be.rejected() + .and.to.have.property('code', 'ERR_PUBSUB_DISABLED') }) - it('should not allow setMaxListeners if disabled', async () => { + it('should not allow setMaxListeners if disabled', () => { try { - await ipfs.pubsub.setMaxListeners(100) + ipfs.pubsub.setMaxListeners(100) } catch (err) { return expect(err.code).to.equal('ERR_PUBSUB_DISABLED') } diff --git a/test/core/utils.js b/test/core/utils.js index a4d00e329f..f4cb6d78ff 100644 --- a/test/core/utils.js +++ b/test/core/utils.js @@ -53,11 +53,7 @@ describe('utils', () => { }) it('normalize path with no ipfs path, nor ipns path nor cid should throw an exception', function () { - try { - utils.normalizePath(`/${rootHash}/`) - } catch (err) { - expect(err).to.exist() - } + expect(() => utils.normalizePath(`/${rootHash}/`)).to.throw() }) it('normalize path should return an ipfs path, when an ipfs path is provided', function () { @@ -162,17 +158,15 @@ describe('utils', () => { }) it('should error on invalid hashes', () => { - return utils.resolvePath(node.object, '/ipfs/asdlkjahsdfkjahsdfd') - .then(() => expect.fail('should have errored'), (err) => expect(err).to.exist()) + return expect(utils.resolvePath(node.object, '/ipfs/asdlkjahsdfkjahsdfd')) + .to.be.rejected() }) it('should error when a link doesn\'t exist', () => { - return utils.resolvePath(node.object, `${aboutPath}/fusion`) - .then(() => expect.fail('should have errored'), (err) => { - expect(err.message).to.include( - 'no link named "fusion" under QmbJCNKXJqVK8CzbjpNFz2YekHwh3CSHpBA86uqYg3sJ8q' - ) - }) + return expect(utils.resolvePath(node.object, `${aboutPath}/fusion`)) + .to.be.rejected() + .and.eventually.have.property('message') + .that.includes('no link named "fusion" under QmbJCNKXJqVK8CzbjpNFz2YekHwh3CSHpBA86uqYg3sJ8q') }) }) })