From fa984e0fa6692487411033a97043f4fee6650e23 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 21 May 2020 19:16:15 -0700 Subject: [PATCH] fix(ipfs): Improved functions and unit tests, addded e2e test --- src/ipfs.js | 43 ++++---- test/e2e/ipfs/ipfs-e2e.js | 24 +++++ test/unit/fixtures/ipfs-mock.js | 3 +- test/unit/ipfs.js | 168 ++++++++++++++------------------ 4 files changed, 116 insertions(+), 122 deletions(-) create mode 100644 test/e2e/ipfs/ipfs-e2e.js diff --git a/src/ipfs.js b/src/ipfs.js index 8fec092..eb44600 100644 --- a/src/ipfs.js +++ b/src/ipfs.js @@ -55,12 +55,18 @@ class IPFS { // DEPRECATED // Upload a file to the FullStack.cash IPFS server. If successful, it will // return an object with an ID, a BCH address, and an amount of BCH to pay. - async uploadFile(path) { + async uploadFile(path, modelId) { try { // Ensure the file exists. if (!_this.fs.existsSync(path)) throw new Error(`Could not find this file: ${path}`) + if (!modelId) { + throw new Error( + `Must include a file model ID in order to upload a file.` + ) + } + // Read in the file. const fileBuf = _this.fs.readFileSync(path) @@ -68,33 +74,32 @@ class IPFS { const splitPath = path.split("/") const fileName = splitPath[splitPath.length - 1] + // Prepare the upload object. Get a file ID from Uppy. const id = _this.uppy.addFile({ name: fileName, data: fileBuf, source: "Local", isRemote: false }) + // console.log(`id: ${JSON.stringify(id, null, 2)}`) - console.log(`id: ${JSON.stringify(id, null, 2)}`) + // Add the model ID, required to be allowed to upload the file. + _this.uppy.setFileMeta(id, { fileModelId: modelId }) + // Upload the file to the server. const upData = await _this.uppy.upload() - // console.log(` - // Files Successful : ${upData.successful.length} - // Files Failed : ${upData.failed.length} - // `) - if (upData.failed.length) throw new Error("The file could not be uploaded") if (upData.successful.length) { delete upData.successful[0].data - console.log(`upData: ${JSON.stringify(upData, null, 2)}`) + // console.log(`upData: ${JSON.stringify(upData, null, 2)}`) const fileObj = { schemaVersion: 1, size: upData.successful[0].progress.bytesTotal, - fileId: upData.successful[0].id, + fileId: upData.successful[0].meta.fileModelId, fileName: upData.successful[0].name, fileExtension: upData.successful[0].extension } @@ -111,22 +116,9 @@ class IPFS { } } - // DEPRECATED - // Call this after uploadFile(). - async getPaymentInfo(fileObj) { - try { - const fileData = await _this.axios.post(`${this.IPFS_API}/files`, { - file: fileObj - }) - // console.log(`fileData.data: ${JSON.stringify(fileData.data, null, 2)}`) - - return fileData.data - } catch (err) { - console.error(`Error in getPaymentInfo()`) - throw err - } - } - + // Creates a new model on the server. If successful, will return an object + // with file data. That object contains a BCH address, payment amount, and + // _id required to be able to upload a file. async createFileModel(path) { try { // Ensure the file exists. @@ -150,7 +142,6 @@ class IPFS { const fileObj = { schemaVersion: 1, size: fileBuf.length, - // fileId: upData.successful[0].id, fileName: fileName, fileExtension: fileExt } diff --git a/test/e2e/ipfs/ipfs-e2e.js b/test/e2e/ipfs/ipfs-e2e.js new file mode 100644 index 0000000..7111a5e --- /dev/null +++ b/test/e2e/ipfs/ipfs-e2e.js @@ -0,0 +1,24 @@ +/* + An end-to-end test for testing the functionality of uploading a file to + IPFS is working. +*/ + +process.env.IPFS_API = `http://localhost:5001` +// process.env.IPFS_API = `https://ipfs-api.fullstack.cash` + +const BCHJS = require("../../../src/bch-js") +const bchjs = new BCHJS() + +describe(`#IPFS`, () => { + it("should upload a file to the server", async () => { + const path = `${__dirname}/ipfs-e2e.js` + + const fileModel = await bchjs.IPFS.createFileModel(path) + console.log(`fileModel: ${JSON.stringify(fileModel, null, 2)}`) + + const fileId = fileModel.file._id + + const fileObj = await bchjs.IPFS.uploadFile(path, fileId) + console.log(`fileObj: ${JSON.stringify(fileObj, null, 2)}`) + }).timeout(30000) +}) diff --git a/test/unit/fixtures/ipfs-mock.js b/test/unit/fixtures/ipfs-mock.js index b87621d..0a04e24 100644 --- a/test/unit/fixtures/ipfs-mock.js +++ b/test/unit/fixtures/ipfs-mock.js @@ -12,7 +12,8 @@ const uploadData = { meta: { test: "avatar", name: "ipfs.js", - type: "application/octet-stream" + type: "application/octet-stream", + fileModelId: "5ec562319bfacc745e8d8a52" }, type: "application/octet-stream", progress: { diff --git a/test/unit/ipfs.js b/test/unit/ipfs.js index b8835bc..11f5604 100644 --- a/test/unit/ipfs.js +++ b/test/unit/ipfs.js @@ -24,103 +24,9 @@ describe(`#IPFS`, () => { describe("#initUppy", () => { it("should initialize uppy", () => { bchjs.IPFS.initUppy() - - // console.log(`bchjs.IPFS.uppy: `, bchjs.IPFS.uppy) }) }) - // describe("#uploadFile", () => { - // it("should throw an error if file does not exist", async () => { - // try { - // const path = "/non-existant-file" - // - // await bchjs.IPFS.uploadFile(path) - // - // assert.equal(true, false, "Unexpected result") - // } catch (err) { - // //console.log(`err.message: ${err.message}`) - // assert.include(err.message, `Could not find this file`) - // } - // }) - // - // it("Should throw error if the file was not uploaded", async () => { - // try { - // const mock = { - // successful: [], - // failed: [ - // { - // id: "file id" - // } - // ] - // } - // sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mock) - // - // const path = `${__dirname}/ipfs.js` - // await bchjs.IPFS.uploadFile(path) - // - // assert.equal(true, false, "Unexpected result") - // } catch (err) { - // //console.log(err) - // assert.include(err.message, `The file could not be uploaded`) - // } - // }) - // - // it("should return file object if the file is uploaded", async () => { - // try { - // sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mockData.uploadData) - // - // const path = `${__dirname}/ipfs.js` - // const result = await bchjs.IPFS.uploadFile(path) - // // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // - // assert.property(result, "schemaVersion") - // assert.property(result, "size") - // assert.property(result, "fileId") - // assert.property(result, "fileName") - // assert.property(result, "fileExtension") - // } catch (err) { - // //console.log(err) - // assert.equal(true, false, "Unexpected result") - // } - // }) - // }) - - // describe("#getPaymentInfo", () => { - // it("should return payment information", async () => { - // sandbox - // .stub(bchjs.IPFS.axios, "post") - // .resolves({ data: mockData.paymentInfo }) - // - // const fileObj = { - // schemaVersion: 1, - // size: 2374, - // fileId: "uppy-ipfs/js-1e-application/octet-stream", - // fileName: "ipfs.js", - // fileExtension: "js" - // } - // - // const result = await bchjs.IPFS.getPaymentInfo(fileObj) - // // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // - // assert.property(result, "success") - // assert.property(result, "hostingCostBCH") - // assert.property(result, "hostingCostUSD") - // assert.property(result, "file") - // assert.property(result.file, "payloadLink") - // assert.property(result.file, "hasBeenPaid") - // assert.property(result.file, "_id") - // assert.property(result.file, "schemaVersion") - // assert.property(result.file, "size") - // assert.property(result.file, "fileId") - // assert.property(result.file, "fileName") - // assert.property(result.file, "fileExtension") - // assert.property(result.file, "createdTimestamp") - // assert.property(result.file, "hostingCost") - // assert.property(result.file, "walletIndex") - // assert.property(result.file, "bchAddr") - // }) - // }) - describe("#createFileModel", () => { it("should throw an error if file does not exist", async () => { try { @@ -143,7 +49,7 @@ describe(`#IPFS`, () => { .resolves({ data: mockData.mockNewFileModel }) const result = await bchjs.IPFS.createFileModel(path) - console.log(`result: ${JSON.stringify(result, null, 2)}`) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.property(result, "success") assert.equal(result.success, true) @@ -165,4 +71,76 @@ describe(`#IPFS`, () => { assert.property(result.file, "bchAddr") }) }) + + describe("#uploadFile", () => { + it("should throw an error if file does not exist", async () => { + try { + const path = "/non-existant-file" + + await bchjs.IPFS.uploadFile(path) + + assert.equal(true, false, "Unexpected result") + } catch (err) { + //console.log(`err.message: ${err.message}`) + assert.include(err.message, `Could not find this file`) + } + }) + + it("should throw an error if modelId is not included", async () => { + try { + const path = `${__dirname}/ipfs.js` + + await bchjs.IPFS.uploadFile(path) + + assert.equal(true, false, "Unexpected result") + } catch (err) { + //console.log(`err.message: ${err.message}`) + assert.include(err.message, `Must include a file model ID`) + } + }) + + it("Should throw error if the file was not uploaded", async () => { + try { + const mock = { + successful: [], + failed: [ + { + id: "file id" + } + ] + } + sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mock) + + const path = `${__dirname}/ipfs.js` + await bchjs.IPFS.uploadFile(path, "5ec562319bfacc745e8d8a52") + + assert.equal(true, false, "Unexpected result") + } catch (err) { + //console.log(err) + assert.include(err.message, `The file could not be uploaded`) + } + }) + + it("should return file object if the file is uploaded", async () => { + try { + sandbox.stub(bchjs.IPFS.uppy, "upload").resolves(mockData.uploadData) + + const path = `${__dirname}/ipfs.js` + const result = await bchjs.IPFS.uploadFile( + path, + "5ec562319bfacc745e8d8a52" + ) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, "schemaVersion") + assert.property(result, "size") + assert.property(result, "fileId") + assert.property(result, "fileName") + assert.property(result, "fileExtension") + } catch (err) { + //console.log(err) + assert.equal(true, false, "Unexpected result") + } + }) + }) })