Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c2232a6d01 | ||
|
8fd20a0f35 | ||
|
a1dc06cf4b | ||
|
33a766a342 | ||
|
9b7ca3dac5 | ||
|
ff2c75cdf7 | ||
|
af329465c9 |
115
Gruntfile.js
115
Gruntfile.js
@ -1,3 +1,5 @@
|
||||
var webpackConfig = require('./webpack.config');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.initConfig({
|
||||
@ -8,78 +10,67 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
stop_node: { stop: {} },
|
||||
|
||||
run: {
|
||||
installBower: {
|
||||
cmd: 'node',
|
||||
args: [
|
||||
'./node_modules/bower/bin/bower',
|
||||
'install'
|
||||
]
|
||||
},
|
||||
killAllNodeWindows: {
|
||||
cmd: 'taskkill',
|
||||
args: [
|
||||
'/f',
|
||||
'/im',
|
||||
'node.exe'
|
||||
]
|
||||
},
|
||||
killAllNodeMac: {
|
||||
cmd: 'killall',
|
||||
args: [
|
||||
'node'
|
||||
]
|
||||
}
|
||||
stop_node: {
|
||||
stop: {}
|
||||
},
|
||||
|
||||
jasmine: {
|
||||
amd: {
|
||||
src: 'backbone-model-file-upload.js',
|
||||
host: 'http://localhost:8888/',
|
||||
headless: {
|
||||
options: {
|
||||
specs: ['test/*spec.js'],
|
||||
helpers: 'bower_components/Blob/Blob.js',
|
||||
//keepRunner: true,
|
||||
template: require('grunt-template-jasmine-requirejs'),
|
||||
templateOptions: {
|
||||
requireConfig: {
|
||||
paths: {
|
||||
"jquery": "bower_components/jquery/dist/jquery.min",
|
||||
"underscore": "bower_components/underscore/underscore-min",
|
||||
"backbone": "bower_components/backbone/backbone"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
browserGlobal: {
|
||||
src: 'backbone-model-file-upload.js',
|
||||
host: 'http://localhost:8888/',
|
||||
options: {
|
||||
specs: ['test/*spec.js'],
|
||||
//keepRunner: true,
|
||||
vendor: [
|
||||
"bower_components/Blob/Blob.js",
|
||||
"bower_components/jquery/dist/jquery.min.js",
|
||||
"bower_components/underscore/underscore-min.js",
|
||||
"bower_components/backbone/backbone.js"
|
||||
browser: 'chrome',
|
||||
headless: true,
|
||||
timeout: 20000,
|
||||
keepRunner: true,
|
||||
outfile: '_SpecRunner.html',
|
||||
host: 'http://localhost:8088',
|
||||
summary: true,
|
||||
display: 'short',
|
||||
reportSlowerThan: 2000,
|
||||
specs: [
|
||||
'.grunt/tests.specs.js'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
connect: {
|
||||
test: {
|
||||
options: {
|
||||
port: 8088,
|
||||
livereload: false,
|
||||
hostname: '0.0.0.0', // to be able to access the server not only from localhost
|
||||
base: {
|
||||
path: '.'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
specs: {
|
||||
options: {
|
||||
port: 8088,
|
||||
livereload: false,
|
||||
open: 'http://localhost:8088/_SpecRunner.html',
|
||||
hostname: '0.0.0.0',
|
||||
base: {
|
||||
path: '.'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
webpack: {
|
||||
options: {
|
||||
stats: false
|
||||
},
|
||||
test: webpackConfig
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks('grunt-webpack');
|
||||
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||
grunt.loadNpmTasks('grunt-run');
|
||||
grunt.loadNpmTasks('grunt-run-node');
|
||||
|
||||
grunt.registerTask('test', ['build','run_node','jasmine','stop_node']);
|
||||
grunt.registerTask('build', ['run:installBower']);
|
||||
grunt.registerTask('resetNodeWin', ['run:killAllNodeWindows']);
|
||||
grunt.registerTask('resetNodeMac', ['run:killAllNodeMac']);
|
||||
|
||||
};
|
||||
grunt.registerTask('test', ['webpack:test', 'connect:test', 'run_node','jasmine','stop_node']);
|
||||
grunt.registerTask('test:browser', ['webpack:test', 'connect:specs', 'run_node','jasmine','stop_node']);
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
Backbone.Model File Upload
|
||||
==========================
|
||||
[![Travis Build](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload.svg?branch=master)](https://travis-ci.org/homeslicesolutions/backbone-model-file-upload)
|
||||
|
||||
A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)
|
||||
|
||||
|
||||
@ -41,8 +43,8 @@ email.set('attachment', fileObject);
|
||||
|
||||
email.save();
|
||||
|
||||
email.on('progress', function(evt) { console.log(evt) });
|
||||
// Will result: with an event object you can use evt.loaded and evt.total to figure out the percent (i.e. 0.3233)
|
||||
email.on('progress', console.log);
|
||||
// Will result: the status in percent i.e. 0.3233
|
||||
|
||||
```
|
||||
### fileAttribute
|
||||
@ -174,9 +176,6 @@ c Version v0.1
|
||||
- Switching to "Bracket" notation for flattening nested objects
|
||||
- Added an "unflatten" internal method to unflatten
|
||||
|
||||
#### Version 1.0.2
|
||||
- Cutting a tag and fixing NPM issues
|
||||
|
||||
### Dev/Installation
|
||||
If you want to work on this plugin, test it, etc., it just needs an install of `node` and `grunt`.
|
||||
```
|
||||
|
@ -13,21 +13,21 @@
|
||||
|
||||
// AMD
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['underscore', 'backbone'], function(_, Backbone){
|
||||
factory(root, Backbone, _);
|
||||
define(['underscore', 'jquery', 'backbone'], function(_, $, Backbone){
|
||||
factory(root, Backbone, _, $);
|
||||
});
|
||||
|
||||
// NodeJS/CommonJS
|
||||
} else if (typeof exports !== 'undefined') {
|
||||
var _ = require('underscore'), Backbone = require('backbone');
|
||||
factory(root, Backbone, _);
|
||||
var _ = require('underscore'), $ = require('jquery'), Backbone = require('backbone');
|
||||
factory(root, Backbone, _, $);
|
||||
|
||||
// Browser global
|
||||
} else {
|
||||
factory(root, root.Backbone, root._);
|
||||
factory(root, root.Backbone, root._, root.$);
|
||||
}
|
||||
|
||||
}(this, function(root, Backbone, _) {
|
||||
}(this, function(root, Backbone, _, $) {
|
||||
'use strict';
|
||||
|
||||
// Clone the original Backbone.Model.prototype as superClass
|
||||
@ -43,8 +43,7 @@
|
||||
save: function(key, val, options) {
|
||||
|
||||
// Variables
|
||||
var attrs, attributes = this.attributes,
|
||||
that = this;
|
||||
var attrs, attributes = this.attributes;
|
||||
|
||||
// Signature parsing - taken directly from original Backbone.Model.save
|
||||
// and it states: 'Handle both "key", value and {key: value} -style arguments.'
|
||||
@ -87,14 +86,13 @@
|
||||
// Converting Attributes to Form Data
|
||||
var formData = new FormData();
|
||||
_.each( formAttrs, function( value, key ){
|
||||
if (value instanceof FileList || (key === that.fileAttribute && value instanceof Array)) {
|
||||
if (value instanceof FileList) {
|
||||
_.each(value, function(file) {
|
||||
formData.append( key, file );
|
||||
});
|
||||
return;
|
||||
}
|
||||
else {
|
||||
formData.append( key, value );
|
||||
}
|
||||
formData.append( key, value );
|
||||
});
|
||||
|
||||
// Set options for AJAX call
|
||||
@ -102,13 +100,12 @@
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
|
||||
// Handle "progress" events
|
||||
if (!options.xhr) {
|
||||
options.xhr = function(){
|
||||
var xhr = Backbone.$.ajaxSettings.xhr();
|
||||
xhr.upload.addEventListener('progress', _.bind(that._progressHandler, that), false);
|
||||
return xhr
|
||||
}
|
||||
// Apply custom XHR for processing status & listen to "progress"
|
||||
var that = this;
|
||||
options.xhr = function() {
|
||||
var xhr = $.ajaxSettings.xhr();
|
||||
xhr.upload.addEventListener('progress', that._progressHandler.bind(that), false);
|
||||
return xhr;
|
||||
}
|
||||
}
|
||||
|
||||
|
24
bower.json
24
bower.json
@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "backbone-model-file-upload",
|
||||
"description": "A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)",
|
||||
"version": "1.0.0",
|
||||
"main": "backbone-model-file-upload.js",
|
||||
"keywords": [
|
||||
"backbone",
|
||||
"fileupload",
|
||||
"file",
|
||||
"model",
|
||||
"multipart"
|
||||
],
|
||||
"author": "Joe Vu",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/homeslicesolutions/backbone-model-file-upload/issues"
|
||||
},
|
||||
"homepage": "https://github.com/homeslicesolutions/backbone-model-file-upload",
|
||||
"dependencies": {
|
||||
"jquery": "~2.1.1",
|
||||
"backbone": "~1.1.2",
|
||||
"Blob": "*"
|
||||
}
|
||||
}
|
22
package.json
22
package.json
@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "backbone-model-file-upload",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.0",
|
||||
"description": "A concise, non-iframe, & pure XHR2/AJAX Backbone.model file upload. (Good for IE >= 10, FF, Chrome.)",
|
||||
"main": "backbone-model-file-upload.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {},
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
},
|
||||
@ -28,13 +27,18 @@
|
||||
},
|
||||
"homepage": "https://github.com/homeslicesolutions/backbone-model-file-upload",
|
||||
"devDependencies": {
|
||||
"bower": "^1.3.12",
|
||||
"formidable": "~1.0.15",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-contrib-jasmine": "^0.6.5",
|
||||
"grunt-run": "^0.3.0",
|
||||
"grunt-run-node": "^0.1.0",
|
||||
"backbone": "1.2.3",
|
||||
"blob": "0.0.4",
|
||||
"grunt": "0.4.5",
|
||||
"grunt-contrib-connect": "^1.0.2",
|
||||
"grunt-contrib-jasmine": "CartoDB/grunt-contrib-jasmine#headless-chrome",
|
||||
"grunt-run": "0.3.0",
|
||||
"grunt-run-node": "0.1.3",
|
||||
"grunt-template-jasmine-requirejs": "^0.2.0",
|
||||
"lodash": "~2.4.1"
|
||||
"grunt-webpack": "^3.0.2",
|
||||
"jquery": "2.1.4",
|
||||
"underscore": "1.8.3",
|
||||
"webpack": "^3.5.5",
|
||||
"formidable": "~1.0.15"
|
||||
}
|
||||
}
|
||||
|
@ -1,320 +1,298 @@
|
||||
!function(){
|
||||
'use strict';
|
||||
var $ = require('jquery');
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
require('../backbone-model-file-upload');
|
||||
var Blob = require('blob');
|
||||
|
||||
describe('Testing Backbone Model Plugin', function(){
|
||||
describe('Testing Backbone Model Plugin', function () {
|
||||
|
||||
Backbone.$.ajaxSetup({
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
}
|
||||
});
|
||||
Backbone.$.ajaxSetup({
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
}
|
||||
});
|
||||
|
||||
var File = Backbone.Model.extend({
|
||||
url: 'http://localhost:8989/',
|
||||
fileAttribute: 'fileAttachment'
|
||||
});
|
||||
var File = Backbone.Model.extend({
|
||||
url: 'http://localhost:8989/',
|
||||
fileAttribute: 'fileAttachment'
|
||||
});
|
||||
|
||||
|
||||
|
||||
var fileModel;
|
||||
var simulatedFileObj;
|
||||
var simulatedFileObj2;
|
||||
var fileModel;
|
||||
var simulatedFileObj;
|
||||
|
||||
beforeEach(function(){
|
||||
beforeEach(function () {
|
||||
|
||||
simulatedFileObj = new Blob(['<strong>Hello World</strong>'], {type : 'text/html'});
|
||||
simulatedFileObj2 = new Blob(['<strong>Hello Again, World</strong>'], {type : 'text/html'});
|
||||
simulatedFileObj = new Blob(['<strong>Hello World</strong>'], {type : 'text/html'});
|
||||
|
||||
fileModel = new File({
|
||||
from: 'sample@email.com',
|
||||
subject: 'Hello, friend!',
|
||||
body: 'Dear friend, Just saying hello! Love, Yours truly.',
|
||||
nestedObject: {
|
||||
nest: 'eggs',
|
||||
nestier: {
|
||||
nestiest: {
|
||||
0: 'one',
|
||||
1: 'two',
|
||||
2: 'three'
|
||||
}
|
||||
fileModel = new File({
|
||||
from: 'sample@email.com',
|
||||
subject: 'Hello, friend!',
|
||||
body: 'Dear friend, Just saying hello! Love, Yours truly.',
|
||||
nestedObject: {
|
||||
nest: 'eggs',
|
||||
nestier: {
|
||||
nestiest: {
|
||||
0: 'one',
|
||||
1: 'two',
|
||||
2: 'three'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should detect the file(blob) save successfully', function(done){
|
||||
|
||||
// Arrange
|
||||
fileModel.set({fileAttachment: simulatedFileObj});
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save(null);
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to be saved in as an argument of "save" as object', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj});
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to be saved in as an argument of "save" as key/value argument', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save('fileAttachment', simulatedFileObj);
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to save an array of multiple file objects', function(done){
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment')[0].size).toBe(28);
|
||||
expect(model.get('fileAttachment')[0].type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment')[0].data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==')
|
||||
expect(model.get('fileAttachment')[1].size).toBe(35);
|
||||
expect(model.get('fileAttachment')[1].type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment')[1].data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBBZ2FpbiwgV29ybGQ8L3N0cm9uZz4K=')
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save('fileAttachment', [simulatedFileObj, simulatedFileObj2], {formData: true});
|
||||
});
|
||||
|
||||
it ('should be able to have "wait" and "validate" option', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj},{wait: true, validate: false});
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by setting it and save(null)', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('somethingelse@email.com');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.set({from: 'somethingelse@email.com'});
|
||||
fileModel.save();
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by save("from","yes")', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save('from','yes');
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by save({from: "yes"})', function(done){
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({from: "yes"});
|
||||
|
||||
});
|
||||
|
||||
it('should still silent true with file', function(done){
|
||||
|
||||
var changed = false;
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
setTimeout(function(){
|
||||
expect(changed).not.toBeTruthy();
|
||||
done();
|
||||
},500);
|
||||
|
||||
});
|
||||
|
||||
fileModel.on('change', function(){
|
||||
changed = true;
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj}, {silent: true});
|
||||
|
||||
});
|
||||
|
||||
it('should still silent true without file', function(done){
|
||||
|
||||
var changed = false;
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
|
||||
setTimeout(function(){
|
||||
expect(changed).not.toBeTruthy();
|
||||
done();
|
||||
},500);
|
||||
|
||||
});
|
||||
|
||||
fileModel.on('change', function(){
|
||||
changed = true;
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({from: "yes"}, {silent: true});
|
||||
|
||||
});
|
||||
|
||||
it('should flatten correctly using a bracket notation', function(){
|
||||
|
||||
// Arrange
|
||||
var expected = {
|
||||
"from": "sample@email.com",
|
||||
"subject": "Hello, friend!",
|
||||
"body": "Dear friend, Just saying hello! Love, Yours truly.",
|
||||
"nestedObject[nest]": "eggs",
|
||||
"nestedObject[nestier[nestiest[0]]]": "one",
|
||||
"nestedObject[nestier[nestiest[1]]]": "two",
|
||||
"nestedObject[nestier[nestiest[2]]]": "three"
|
||||
};
|
||||
|
||||
var flattened = fileModel._flatten(fileModel.toJSON());
|
||||
|
||||
expect(flattened["nestedObject[nest]"]).toBe("eggs")
|
||||
expect(flattened["nestedObject[nestier[nestiest[0]]]"]).toBe("one");
|
||||
expect(flattened["nestedObject[nestier[nestiest[1]]]"]).toBe("two");
|
||||
expect(flattened["nestedObject[nestier[nestiest[2]]]"]).toBe("three");
|
||||
});
|
||||
|
||||
it('should unflatten correctly using internal "unflatten" function', function(){
|
||||
|
||||
var flattened = fileModel._flatten(fileModel.toJSON()),
|
||||
unflattened = fileModel._unflatten(flattened);
|
||||
|
||||
expect(_.isEqual(unflattened, fileModel.toJSON())).toBeTruthy();
|
||||
|
||||
console.log(JSON.stringify(fileModel._flatten({
|
||||
'family': 'The Smiths',
|
||||
'grandpa': {
|
||||
'name': 'Ole Joe Smith',
|
||||
'children': [
|
||||
{
|
||||
'name': 'Mary Lee',
|
||||
'spouse': 'John Lee',
|
||||
'children': [
|
||||
{
|
||||
'name': 'Tiny Lee'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': 'Susan Smith'
|
||||
}
|
||||
]
|
||||
}
|
||||
})));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should detect the file(blob) save successfully', function (done) {
|
||||
|
||||
// Arrange
|
||||
fileModel.set({fileAttachment: simulatedFileObj});
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save(null);
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to be saved in as an argument of "save" as object', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj});
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to be saved in as an argument of "save" as key/value argument', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save('fileAttachment', simulatedFileObj);
|
||||
|
||||
});
|
||||
|
||||
it ('should be able to have "wait" and "validate" option', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('sample@email.com');
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj},{wait: true, validate: false});
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by setting it and save(null)', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('somethingelse@email.com');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.set({from: 'somethingelse@email.com'});
|
||||
fileModel.save();
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by save("from","yes")', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save('from','yes');
|
||||
|
||||
});
|
||||
|
||||
it('should still have the option to save normally by save({from: "yes"})', function (done) {
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({from: "yes"});
|
||||
|
||||
});
|
||||
|
||||
it('should still silent true with file', function (done) {
|
||||
|
||||
var changed = false;
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
// Assert Blob (phantomJS can't do Blobs so just test minimal attributes)
|
||||
expect(model.get('fileAttachment').size).toBe(28);
|
||||
expect(model.get('fileAttachment').type).toBe('text/html');
|
||||
//expect(model.get('fileAttachment').data).toBe('data:text/html;base64,PHN0cm9uZz5IZWxsbyBXb3JsZDwvc3Ryb25nPg==');
|
||||
|
||||
setTimeout(function(){
|
||||
expect(changed).not.toBeTruthy();
|
||||
done();
|
||||
},500);
|
||||
|
||||
});
|
||||
|
||||
fileModel.on('change', function(){
|
||||
changed = true;
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({fileAttachment: simulatedFileObj}, {silent: true});
|
||||
|
||||
});
|
||||
|
||||
it('should still silent true without file', function (done) {
|
||||
|
||||
var changed = false;
|
||||
|
||||
// Listen
|
||||
fileModel.on('sync', function(model){
|
||||
|
||||
// Assert
|
||||
expect(model.get('from')).toBe('yes');
|
||||
|
||||
setTimeout(function(){
|
||||
expect(changed).not.toBeTruthy();
|
||||
done();
|
||||
},500);
|
||||
|
||||
});
|
||||
|
||||
fileModel.on('change', function(){
|
||||
changed = true;
|
||||
});
|
||||
|
||||
// Act
|
||||
fileModel.save({from: "yes"}, {silent: true});
|
||||
|
||||
});
|
||||
|
||||
it('should flatten correctly using a bracket notation', function () {
|
||||
|
||||
// Arrange
|
||||
var expected = {
|
||||
"from": "sample@email.com",
|
||||
"subject": "Hello, friend!",
|
||||
"body": "Dear friend, Just saying hello! Love, Yours truly.",
|
||||
"nestedObject[nest]": "eggs",
|
||||
"nestedObject[nestier[nestiest[0]]]": "one",
|
||||
"nestedObject[nestier[nestiest[1]]]": "two",
|
||||
"nestedObject[nestier[nestiest[2]]]": "three"
|
||||
};
|
||||
|
||||
var flattened = fileModel._flatten(fileModel.toJSON());
|
||||
|
||||
expect(flattened["nestedObject[nest]"]).toBe("eggs")
|
||||
expect(flattened["nestedObject[nestier[nestiest[0]]]"]).toBe("one");
|
||||
expect(flattened["nestedObject[nestier[nestiest[1]]]"]).toBe("two");
|
||||
expect(flattened["nestedObject[nestier[nestiest[2]]]"]).toBe("three");
|
||||
});
|
||||
|
||||
it('should unflatten correctly using internal "unflatten" function', function () {
|
||||
|
||||
var flattened = fileModel._flatten(fileModel.toJSON()),
|
||||
unflattened = fileModel._unflatten(flattened);
|
||||
|
||||
expect(_.isEqual(unflattened, fileModel.toJSON())).toBeTruthy();
|
||||
|
||||
console.log(fileModel._flatten({
|
||||
'family': 'The Smiths',
|
||||
'grandpa': {
|
||||
'name': 'Ole Joe Smith',
|
||||
'children': [
|
||||
{
|
||||
'name': 'Mary Lee',
|
||||
'spouse': 'John Lee',
|
||||
'children': [
|
||||
{
|
||||
'name': 'Tiny Lee'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': 'Susan Smith'
|
||||
}
|
||||
]
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}();
|
||||
|
@ -1,10 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var http = require('http'),
|
||||
formidable = require('formidable'),
|
||||
fs = require('fs'),
|
||||
_ = require('lodash');
|
||||
|
||||
var http = require('http');
|
||||
var formidable = require('formidable');
|
||||
var fs = require('fs');
|
||||
var _ = require('underscore');
|
||||
var util = require('util');
|
||||
|
||||
var options = {
|
||||
host: 'localhost',
|
||||
@ -15,17 +13,9 @@ var server = http.createServer(function(req,res) {
|
||||
|
||||
console.log('POST Detected with incoming Form-data...');
|
||||
|
||||
var form = new formidable.IncomingForm(),
|
||||
files = {},
|
||||
fields = {};
|
||||
var form = new formidable.IncomingForm();
|
||||
|
||||
form.on('file', function(field, file) {
|
||||
files[field] = (files[field] || []).concat([file]);
|
||||
});
|
||||
form.on('field', function(field, value) {
|
||||
fields[field] = value;
|
||||
});
|
||||
form.on('end', function(err) {
|
||||
form.parse(req, function(err, fields, files) {
|
||||
console.log('POST Finished and publishing object back to browser...');
|
||||
|
||||
var headers = {};
|
||||
@ -41,32 +31,37 @@ var server = http.createServer(function(req,res) {
|
||||
var output = {};
|
||||
|
||||
_.extend(output, unflatten(fields));
|
||||
var fileOutputs = {};
|
||||
_.each(files, function(files, filename){
|
||||
var loopOutputs = [];
|
||||
_.each(files, function(file) {
|
||||
var fileOutput = {},
|
||||
data = fs.readFileSync(file.path);
|
||||
fileOutput.type = file.type;
|
||||
fileOutput.size = data.length;
|
||||
fileOutput.name = file.name;
|
||||
fileOutput.lastModifiedDate = file.lastModifiedDate;
|
||||
fileOutput.data = 'data:' + file.type + ';base64,' + data.toString('base64');
|
||||
loopOutputs.push(fileOutput);
|
||||
});
|
||||
loopOutputs = loopOutputs.length > 1 ? loopOutputs : loopOutputs[0];
|
||||
fileOutputs[filename] = loopOutputs;
|
||||
});
|
||||
output = _.merge(output, fileOutputs);
|
||||
|
||||
console.info(output);
|
||||
if (!_.isEmpty(files)) {
|
||||
|
||||
res.end(JSON.stringify(output));
|
||||
for (var i in files) {
|
||||
if (files.hasOwnProperty(i)) {
|
||||
|
||||
output[i] = {};
|
||||
|
||||
// This is fucking async
|
||||
fs.readFile(files[i].path, function (err, data) {
|
||||
|
||||
output[i].type = files[i].type;
|
||||
output[i].size = files[i].size;
|
||||
output[i].name = files[i].name;
|
||||
output[i].lastModifiedDate = files[i].lastModifiedDate;
|
||||
output[i].data = 'data:' + files[i].type + ';base64,' + data.toString('base64');
|
||||
|
||||
console.info(output);
|
||||
res.end(JSON.stringify(output));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
console.info(output);
|
||||
res.end(JSON.stringify(output));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
form.parse(req)
|
||||
|
||||
});
|
||||
|
||||
function unflatten(obj, output) {
|
||||
@ -88,4 +83,4 @@ function unflatten(obj, output) {
|
||||
}
|
||||
|
||||
server.listen(options.port, options.host);
|
||||
console.log("listening on " + options.host + ':' + options.port);
|
||||
console.info("listening on " + options.host + ':' + options.port);
|
||||
|
10
webpack.config.js
Normal file
10
webpack.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './test/backbone-model-file-upload.spec.js',
|
||||
output: {
|
||||
path: path.resolve(path.resolve('.'), '.grunt'),
|
||||
filename: 'tests.specs.js'
|
||||
},
|
||||
devtool: 'inline-source-map'
|
||||
};
|
Loading…
Reference in New Issue
Block a user