diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js index 67b36de906..13a443d861 100644 --- a/spec/FilesController.spec.js +++ b/spec/FilesController.spec.js @@ -1,29 +1,33 @@ var FilesController = require('../src/Controllers/FilesController').FilesController; var GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter; +var S3Adapter = require("../src/Adapters/Files/S3Adapter").S3Adapter; var Config = require("../src/Config"); +var FCTestFactory = require("./FilesControllerTestFactory"); + + // Small additional tests to improve overall coverage describe("FilesController",()=>{ - it("should properly expand objects", (done) => { - var config = new Config(Parse.applicationId); - var adapter = new GridStoreAdapter(); - var filesController = new FilesController(adapter); - var result = filesController.expandFilesInObject(config, function(){}); + // Test the grid store adapter + var gridStoreAdapter = new GridStoreAdapter(); + FCTestFactory.testAdapter("GridStoreAdapter", gridStoreAdapter); + + if (process.env.S3_ACCESS_KEY && process.env.S3_SECRET_KEY) { + + // Test the S3 Adapter + var s3Adapter = new S3Adapter(process.env.S3_ACCESS_KEY, process.env.S3_SECRET_KEY, 'parse.server.tests'); - expect(result).toBeUndefined(); + FCTestFactory.testAdapter("S3Adapter",s3Adapter); - var fullFile = { - type: '__type', - url: "http://an.url" - } + // Test S3 with direct access + var s3DirectAccessAdapter = new S3Adapter(process.env.S3_ACCESS_KEY, process.env.S3_SECRET_KEY, 'parse.server.tests', { + directAccess: true + }); - var anObject = { - aFile: fullFile - } - filesController.expandFilesInObject(config, anObject); - expect(anObject.aFile.url).toEqual("http://an.url"); + FCTestFactory.testAdapter("S3AdapterDirect", s3DirectAccessAdapter); - done(); - }) -}) \ No newline at end of file + } else if (!process.env.TRAVIS) { + console.log("set S3_ACCESS_KEY and S3_SECRET_KEY to test S3Adapter") + } +}); diff --git a/spec/FilesControllerTestFactory.js b/spec/FilesControllerTestFactory.js new file mode 100644 index 0000000000..217a383a16 --- /dev/null +++ b/spec/FilesControllerTestFactory.js @@ -0,0 +1,73 @@ + +var FilesController = require('../src/Controllers/FilesController').FilesController; +var Config = require("../src/Config"); + +var testAdapter = function(name, adapter) { + // Small additional tests to improve overall coverage + + var config = new Config(Parse.applicationId); + var filesController = new FilesController(adapter); + + describe("FilesController with "+name,()=>{ + + it("should properly expand objects", (done) => { + + var result = filesController.expandFilesInObject(config, function(){}); + + expect(result).toBeUndefined(); + + var fullFile = { + type: '__type', + url: "http://an.url" + } + + var anObject = { + aFile: fullFile + } + filesController.expandFilesInObject(config, anObject); + expect(anObject.aFile.url).toEqual("http://an.url"); + + done(); + }) + + it("should properly create, read, delete files", (done) => { + var filename; + filesController.createFile(config, "file.txt", "hello world").then( (result) => { + ok(result.url); + ok(result.name); + filename = result.name; + expect(result.name.match(/file.txt/)).not.toBe(null); + return filesController.getFileData(config, filename); + }, (err) => { + fail("The adapter should create the file"); + console.error(err); + done(); + }).then((result) => { + expect(result instanceof Buffer).toBe(true); + expect(result.toString('utf-8')).toEqual("hello world"); + return filesController.deleteFile(config, filename); + }, (err) => { + fail("The adapter should get the file"); + console.error(err); + done(); + }).then((result) => { + + filesController.getFileData(config, filename).then((res) => { + fail("the file should be deleted"); + done(); + }, (err) => { + done(); + }); + + }, (err) => { + fail("The adapter should delete the file"); + console.error(err); + done(); + }); + }, 5000); // longer tests + }); +} + +module.exports = { + testAdapter: testAdapter +} diff --git a/src/Adapters/Files/S3Adapter.js b/src/Adapters/Files/S3Adapter.js index 0732fbfeb9..af6683ecda 100644 --- a/src/Adapters/Files/S3Adapter.js +++ b/src/Adapters/Files/S3Adapter.js @@ -33,6 +33,22 @@ export class S3Adapter extends FilesAdapter { }; AWS.config._region = this._region; this._s3Client = new AWS.S3(s3Options); + this._hasBucket = false; + } + + createBucket() { + var promise; + if (this._hasBucket) { + promise = Promise.resolve(); + } else { + promise = new Promise((resolve, reject) => { + this._s3Client.createBucket(() => { + this._hasBucket = true; + resolve(); + }); + }); + } + return promise; } // For a given config object, filename, and data, store a file in S3 @@ -45,26 +61,30 @@ export class S3Adapter extends FilesAdapter { if (this._directAccess) { params.ACL = "public-read" } - return new Promise((resolve, reject) => { - this._s3Client.upload(params, (err, data) => { - if (err !== null) { - return reject(err); - } - resolve(data); + return this.createBucket().then(() => { + return new Promise((resolve, reject) => { + this._s3Client.upload(params, (err, data) => { + if (err !== null) { + return reject(err); + } + resolve(data); + }); }); }); } deleteFile(config, filename) { - return new Promise((resolve, reject) => { - let params = { - Key: this._bucketPrefix + filename - }; - this._s3Client.deleteObject(params, (err, data) =>{ - if(err !== null) { - return reject(err); - } - resolve(data); + return this.createBucket().then(() => { + return new Promise((resolve, reject) => { + let params = { + Key: this._bucketPrefix + filename + }; + this._s3Client.deleteObject(params, (err, data) =>{ + if(err !== null) { + return reject(err); + } + resolve(data); + }); }); }); } @@ -73,12 +93,18 @@ export class S3Adapter extends FilesAdapter { // Returns a promise that succeeds with the buffer result from S3 getFileData(config, filename) { let params = {Key: this._bucketPrefix + filename}; - return new Promise((resolve, reject) => { - this._s3Client.getObject(params, (err, data) => { - if (err !== null) { - return reject(err); - } - resolve(data.Body); + return this.createBucket().then(() => { + return new Promise((resolve, reject) => { + this._s3Client.getObject(params, (err, data) => { + if (err !== null) { + return reject(err); + } + // Something happend here... + if (data && !data.Body) { + return reject(data); + } + resolve(data.Body); + }); }); }); }