diff --git a/js/src/index.js b/js/src/index.js index 9da38f20..81b9eb96 100644 --- a/js/src/index.js +++ b/js/src/index.js @@ -10,6 +10,7 @@ exports.files = require('./files') exports.key = require('./key') exports.ls = require('./ls') exports.miscellaneous = require('./miscellaneous') +exports.name = require('./name') exports.object = require('./object') exports.pin = require('./pin') exports.ping = require('./ping') diff --git a/js/src/name/index.js b/js/src/name/index.js new file mode 100644 index 00000000..a11b2969 --- /dev/null +++ b/js/src/name/index.js @@ -0,0 +1,9 @@ +'use strict' +const { createSuite } = require('../utils/suite') + +const tests = { + publish: require('./publish'), + resolve: require('./resolve') +} + +module.exports = createSuite(tests) diff --git a/js/src/name/publish.js b/js/src/name/publish.js new file mode 100644 index 00000000..3a0485c7 --- /dev/null +++ b/js/src/name/publish.js @@ -0,0 +1,103 @@ +/* eslint-env mocha */ +'use strict' + +const hat = require('hat') + +const { fixture } = require('./utils') +const { spawnNodeWithId } = require('../utils/spawn') +const { getDescribe, getIt, expect } = require('../utils/mocha') + +module.exports = (createCommon, options) => { + const describe = getDescribe(options) + const it = getIt(options) + const common = createCommon() + + describe('.name.publish', function () { + const keyName = hat() + let ipfs + let nodeId + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) + + common.setup((err, factory) => { + expect(err).to.not.exist() + + spawnNodeWithId(factory, (err, node) => { + expect(err).to.not.exist() + + ipfs = node + nodeId = node.peerId.id + + ipfs.files.add(fixture.data, { pin: false }, done) + }) + }) + }) + + after((done) => common.teardown(done)) + + it('should publish an IPNS record with the default params', function (done) { + this.timeout(50 * 1000) + + const value = fixture.cid + + ipfs.name.publish(value, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res.name).to.equal(nodeId) + expect(res.value).to.equal(`/ipfs/${value}`) + + done() + }) + }) + + it('should publish correctly when the file was not added but resolve is disabled', function (done) { + this.timeout(50 * 1000) + + const value = 'QmPFVLPmp9zv5Z5KUqLhe2EivAGccQW2r7M7jhVJGLZoZU' + + const options = { + resolve: false, + lifetime: '1m', + ttl: '10s', + key: 'self' + } + + ipfs.name.publish(value, options, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res.name).to.equal(nodeId) + expect(res.value).to.equal(`/ipfs/${value}`) + + done() + }) + }) + + it('should publish with a key received as param, instead of using the key of the node', function (done) { + this.timeout(90 * 1000) + + const value = fixture.cid + const options = { + resolve: false, + lifetime: '24h', + ttl: '10s', + key: keyName + } + + ipfs.key.gen(keyName, { type: 'rsa', size: 2048 }, function (err, key) { + expect(err).to.not.exist() + + ipfs.name.publish(value, options, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res.name).to.equal(key.id) + expect(res.value).to.equal(`/ipfs/${value}`) + + done() + }) + }) + }) + }) +} diff --git a/js/src/name/resolve.js b/js/src/name/resolve.js new file mode 100644 index 00000000..067f4422 --- /dev/null +++ b/js/src/name/resolve.js @@ -0,0 +1,137 @@ +/* eslint max-nested-callbacks: ["error", 6] */ +/* eslint-env mocha */ +'use strict' + +const hat = require('hat') + +const { fixture } = require('./utils') +const { spawnNodeWithId } = require('../utils/spawn') +const { getDescribe, getIt, expect } = require('../utils/mocha') + +module.exports = (createCommon, options) => { + const describe = getDescribe(options) + const it = getIt(options) + const common = createCommon() + + describe('.name.resolve', function () { + const keyName = hat() + let ipfs + let nodeId + let keyId + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) + + common.setup((err, factory) => { + expect(err).to.not.exist() + + spawnNodeWithId(factory, (err, node) => { + expect(err).to.not.exist() + + ipfs = node + nodeId = node.peerId.id + + ipfs.files.add(fixture.data, { pin: false }, done) + }) + }) + }) + + after((done) => common.teardown(done)) + + it('should resolve a record with the default params after a publish', function (done) { + this.timeout(50 * 1000) + + const value = fixture.cid + + ipfs.name.publish(value, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + + ipfs.name.resolve(nodeId, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res.path).to.equal(`/ipfs/${value}`) + + done() + }) + }) + }) + + it('should not get the entry if its validity time expired', function (done) { + this.timeout(50 * 1000) + + const value = fixture.cid + const publishOptions = { + resolve: true, + lifetime: '1ms', + ttl: '10s', + key: 'self' + } + + ipfs.name.publish(value, publishOptions, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + + // guarantee that the record has an expired validity. + setTimeout(function () { + ipfs.name.resolve(nodeId, (err, res) => { + expect(err).to.exist() + expect(err.message).to.equal('record has expired') + expect(res).to.not.exist() + + done() + }) + }, 1) + }) + }) + + it('should recursively resolve to an IPFS hash', function (done) { + this.timeout(100 * 1000) + + const value = fixture.cid + const publishOptions = { + resolve: false, + lifetime: '24h', + ttl: '10s', + key: 'self' + } + + // Generate new key + ipfs.key.gen(keyName, { type: 'rsa', size: 2048 }, (err, key) => { + expect(err).to.not.exist() + + keyId = key.id + + // publish ipfs + ipfs.name.publish(value, publishOptions, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + + publishOptions.key = keyName + + // publish ipns with the generated key + ipfs.name.publish(`/ipns/${nodeId}`, publishOptions, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + + const resolveOptions = { + nocache: false, + recursive: true + } + + // recursive resolve (will get ipns first, and will resolve again to find the ipfs) + ipfs.name.resolve(keyId, resolveOptions, (err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res.path).to.equal(`/ipfs/${value}`) + + done() + }) + }) + }) + }) + }) + }) +} diff --git a/js/src/name/utils.js b/js/src/name/utils.js new file mode 100644 index 00000000..61bcdcba --- /dev/null +++ b/js/src/name/utils.js @@ -0,0 +1,8 @@ +'use strict' + +const loadFixture = require('aegir/fixtures') + +exports.fixture = Object.freeze({ + data: loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core'), + cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' +})