2462 lines
85 KiB
JavaScript
2462 lines
85 KiB
JavaScript
import Dropzone from "../src/dropzone.js";
|
|
|
|
describe("Dropzone", function () {
|
|
let getMockFile = (
|
|
type = "text/html",
|
|
filename = "test file name",
|
|
contents = ["file contents"]
|
|
) => {
|
|
let file = new File(contents, filename, { type: type });
|
|
file.status = Dropzone.ADDED;
|
|
file.accepted = true;
|
|
file.upload = {
|
|
filename: filename,
|
|
};
|
|
return file;
|
|
};
|
|
|
|
let xhr = null;
|
|
beforeEach(() => (xhr = sinon.useFakeXMLHttpRequest()));
|
|
|
|
describe("Emitter", function () {
|
|
let emitter = null;
|
|
beforeEach(() => (emitter = new Dropzone.prototype.Emitter()));
|
|
|
|
it(".on() should return the object itself", () =>
|
|
emitter.on("test", function () {}).should.equal(emitter));
|
|
|
|
it(".on() should properly register listeners", function () {
|
|
(emitter._callbacks === undefined).should.be.true;
|
|
let callback = function () {};
|
|
let callback2 = function () {};
|
|
emitter.on("test", callback);
|
|
emitter.on("test", callback2);
|
|
emitter.on("test2", callback);
|
|
emitter._callbacks.test.length.should.equal(2);
|
|
emitter._callbacks.test[0].should.equal(callback);
|
|
emitter._callbacks.test[1].should.equal(callback2);
|
|
emitter._callbacks.test2.length.should.equal(1);
|
|
return emitter._callbacks.test2[0].should.equal(callback);
|
|
});
|
|
|
|
it(".emit() should return the object itself", () =>
|
|
emitter.emit("test").should.equal(emitter));
|
|
|
|
it(".emit() should properly invoke all registered callbacks with arguments", function () {
|
|
let callCount1 = 0;
|
|
let callCount12 = 0;
|
|
let callCount2 = 0;
|
|
let callback1 = function (var1, var2) {
|
|
callCount1++;
|
|
var1.should.equal("callback1 var1");
|
|
return var2.should.equal("callback1 var2");
|
|
};
|
|
let callback12 = function (var1, var2) {
|
|
callCount12++;
|
|
var1.should.equal("callback1 var1");
|
|
return var2.should.equal("callback1 var2");
|
|
};
|
|
let callback2 = function (var1, var2) {
|
|
callCount2++;
|
|
var1.should.equal("callback2 var1");
|
|
return var2.should.equal("callback2 var2");
|
|
};
|
|
|
|
emitter.on("test1", callback1);
|
|
emitter.on("test1", callback12);
|
|
emitter.on("test2", callback2);
|
|
|
|
callCount1.should.equal(0);
|
|
callCount12.should.equal(0);
|
|
callCount2.should.equal(0);
|
|
|
|
emitter.emit("test1", "callback1 var1", "callback1 var2");
|
|
|
|
callCount1.should.equal(1);
|
|
callCount12.should.equal(1);
|
|
callCount2.should.equal(0);
|
|
|
|
emitter.emit("test2", "callback2 var1", "callback2 var2");
|
|
|
|
callCount1.should.equal(1);
|
|
callCount12.should.equal(1);
|
|
callCount2.should.equal(1);
|
|
|
|
emitter.emit("test1", "callback1 var1", "callback1 var2");
|
|
|
|
callCount1.should.equal(2);
|
|
callCount12.should.equal(2);
|
|
return callCount2.should.equal(1);
|
|
});
|
|
|
|
return describe(".off()", function () {
|
|
let callback1 = function () {};
|
|
let callback2 = function () {};
|
|
let callback3 = function () {};
|
|
let callback4 = function () {};
|
|
|
|
beforeEach(
|
|
() =>
|
|
(emitter._callbacks = {
|
|
test1: [callback1, callback2],
|
|
test2: [callback3],
|
|
test3: [callback1, callback4],
|
|
test4: [],
|
|
})
|
|
);
|
|
|
|
it("should work without any listeners", function () {
|
|
emitter._callbacks = undefined;
|
|
let emt = emitter.off();
|
|
emitter._callbacks.should.eql({});
|
|
return emt.should.equal(emitter);
|
|
});
|
|
|
|
it("should properly remove all event listeners", function () {
|
|
let emt = emitter.off();
|
|
emitter._callbacks.should.eql({});
|
|
return emt.should.equal(emitter);
|
|
});
|
|
|
|
it("should properly remove all event listeners for specific event", function () {
|
|
emitter.off("test1");
|
|
(emitter._callbacks["test1"] === undefined).should.be.true;
|
|
emitter._callbacks["test2"].length.should.equal(1);
|
|
emitter._callbacks["test3"].length.should.equal(2);
|
|
let emt = emitter.off("test2");
|
|
(emitter._callbacks["test2"] === undefined).should.be.true;
|
|
return emt.should.equal(emitter);
|
|
});
|
|
|
|
it("should properly remove specific event listener", function () {
|
|
emitter.off("test1", callback1);
|
|
emitter._callbacks["test1"].length.should.equal(1);
|
|
emitter._callbacks["test1"][0].should.equal(callback2);
|
|
emitter._callbacks["test3"].length.should.equal(2);
|
|
let emt = emitter.off("test3", callback4);
|
|
emitter._callbacks["test3"].length.should.equal(1);
|
|
emitter._callbacks["test3"][0].should.equal(callback1);
|
|
return emt.should.equal(emitter);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("static functions", function () {
|
|
describe("Dropzone.isBrowserSupported()", function () {
|
|
let initialValue;
|
|
beforeEach(() => {
|
|
initialValue = Dropzone.blockedBrowsers;
|
|
});
|
|
afterEach(() => {
|
|
Dropzone.blockedBrowsers = initialValue;
|
|
Dropzone.blacklistedBrowsers = undefined;
|
|
});
|
|
it("should use blockedBrowsers usually", () => {
|
|
let initialValue = Dropzone.blockedBrowsers;
|
|
Dropzone.isBrowserSupported().should.be.true;
|
|
initialValue.should.equal(Dropzone.blockedBrowsers);
|
|
|
|
Dropzone.blockedBrowsers = [/HeadlessChrome/];
|
|
Dropzone.isBrowserSupported().should.be.false;
|
|
});
|
|
it("should user blacklistedBrowsers if its set", () => {
|
|
let initialValue = Dropzone.blockedBrowsers;
|
|
|
|
Dropzone.isBrowserSupported().should.be.true;
|
|
|
|
Dropzone.blacklistedBrowsers = [/HeadlessChrome/];
|
|
Dropzone.isBrowserSupported().should.be.false;
|
|
initialValue.should.not.equal(Dropzone.blockedBrowsers);
|
|
Dropzone.blockedBrowsers.should.equal(Dropzone.blacklistedBrowsers);
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.createElement()", function () {
|
|
let element = Dropzone.createElement(
|
|
'<div class="test"><span>Hallo</span></div>'
|
|
);
|
|
|
|
it("should properly create an element from a string", () =>
|
|
element.tagName.should.equal("DIV"));
|
|
it("should properly add the correct class", () =>
|
|
element.classList.contains("test").should.be.ok);
|
|
it("should properly create child elements", () =>
|
|
element.querySelector("span").tagName.should.equal("SPAN"));
|
|
it("should always return only one element", function () {
|
|
element = Dropzone.createElement("<div></div><span></span>");
|
|
return element.tagName.should.equal("DIV");
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.elementInside()", function () {
|
|
let element = Dropzone.createElement(
|
|
'<div id="test"><div class="child1"><div class="child2"></div></div></div>'
|
|
);
|
|
document.body.appendChild(element);
|
|
|
|
let child1 = element.querySelector(".child1");
|
|
let child2 = element.querySelector(".child2");
|
|
|
|
after(() => document.body.removeChild(element));
|
|
|
|
it("should return yes if elements are the same", () =>
|
|
Dropzone.elementInside(element, element).should.be.ok);
|
|
it("should return yes if element is direct child", () =>
|
|
Dropzone.elementInside(child1, element).should.be.ok);
|
|
it("should return yes if element is some child", function () {
|
|
Dropzone.elementInside(child2, element).should.be.ok;
|
|
return Dropzone.elementInside(child2, document.body).should.be.ok;
|
|
});
|
|
it("should return no unless element is some child", function () {
|
|
Dropzone.elementInside(element, child1).should.not.be.ok;
|
|
return Dropzone.elementInside(document.body, child1).should.not.be.ok;
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.optionsForElement()", function () {
|
|
let testOptions = {
|
|
url: "/some/url",
|
|
method: "put",
|
|
};
|
|
|
|
before(() => (Dropzone.options.testElement = testOptions));
|
|
after(() => delete Dropzone.options.testElement);
|
|
|
|
let element = document.createElement("div");
|
|
|
|
it("should take options set in Dropzone.options from camelized id", function () {
|
|
element.id = "test-element";
|
|
return Dropzone.optionsForElement(element).should.equal(testOptions);
|
|
});
|
|
|
|
it("should return undefined if no options set", function () {
|
|
element.id = "test-element2";
|
|
return expect(Dropzone.optionsForElement(element)).to.equal(undefined);
|
|
});
|
|
|
|
it("should return undefined and not throw if it's a form with an input element of the name 'id'", function () {
|
|
element = Dropzone.createElement('<form><input name="id" /</form>');
|
|
return expect(Dropzone.optionsForElement(element)).to.equal(undefined);
|
|
});
|
|
|
|
it("should ignore input fields with the name='id'", function () {
|
|
element = Dropzone.createElement(
|
|
'<form id="test-element"><input type="hidden" name="id" value="fooo" /></form>'
|
|
);
|
|
return Dropzone.optionsForElement(element).should.equal(testOptions);
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.forElement()", function () {
|
|
let element = document.createElement("div");
|
|
element.id = "some-test-element";
|
|
let dropzone = null;
|
|
before(function () {
|
|
document.body.appendChild(element);
|
|
return (dropzone = new Dropzone(element, { url: "/test" }));
|
|
});
|
|
after(function () {
|
|
dropzone.disable();
|
|
return document.body.removeChild(element);
|
|
});
|
|
|
|
it("should throw an exception if no dropzone attached", () =>
|
|
expect(() =>
|
|
Dropzone.forElement(document.createElement("div"))
|
|
).to.throw(
|
|
"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."
|
|
));
|
|
|
|
it("should accept css selectors", () =>
|
|
expect(Dropzone.forElement("#some-test-element")).to.equal(dropzone));
|
|
|
|
it("should accept native elements", () =>
|
|
expect(Dropzone.forElement(element)).to.equal(dropzone));
|
|
});
|
|
|
|
describe("Dropzone.discover()", function () {
|
|
let element1 = document.createElement("div");
|
|
element1.className = "dropzone";
|
|
let element2 = element1.cloneNode();
|
|
let element3 = element1.cloneNode();
|
|
|
|
element1.id = "test-element-1";
|
|
element2.id = "test-element-2";
|
|
element3.id = "test-element-3";
|
|
|
|
describe("specific options", function () {
|
|
before(function () {
|
|
Dropzone.options.testElement1 = { url: "test-url" };
|
|
Dropzone.options.testElement2 = false; // Disabled
|
|
document.body.appendChild(element1);
|
|
document.body.appendChild(element2);
|
|
return Dropzone.discover();
|
|
});
|
|
after(function () {
|
|
document.body.removeChild(element1);
|
|
return document.body.removeChild(element2);
|
|
});
|
|
|
|
it("should find elements with a .dropzone class", () =>
|
|
element1.dropzone.should.be.ok);
|
|
|
|
it("should not create dropzones with disabled options", () =>
|
|
expect(element2.dropzone).to.not.be.ok);
|
|
});
|
|
|
|
return describe("Dropzone.autoDiscover", function () {
|
|
before(function () {
|
|
Dropzone.options.testElement3 = { url: "test-url" };
|
|
return document.body.appendChild(element3);
|
|
});
|
|
after(() => document.body.removeChild(element3));
|
|
|
|
it("should create dropzones even if Dropzone.autoDiscover == false", function () {
|
|
// Because the check is in the actual contentLoaded function.
|
|
Dropzone.autoDiscover = false;
|
|
Dropzone.discover();
|
|
return expect(element3.dropzone).to.be.ok;
|
|
});
|
|
|
|
it("should not automatically be called if Dropzone.autoDiscover == false", function () {
|
|
Dropzone.autoDiscover = false;
|
|
Dropzone.discover = () => expect(false).to.be.ok;
|
|
return Dropzone._autoDiscoverFunction();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.isValidFile()", function () {
|
|
it("should return true if called without acceptedFiles", () =>
|
|
Dropzone.isValidFile({ type: "some/type" }, null).should.be.ok);
|
|
|
|
it("should properly validate if called with concrete mime types", function () {
|
|
let acceptedMimeTypes = "text/html,image/jpeg,application/json";
|
|
|
|
Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
|
|
.ok;
|
|
Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
|
|
.be.ok;
|
|
Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
|
|
.should.be.ok;
|
|
return Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes)
|
|
.should.not.be.ok;
|
|
});
|
|
|
|
it("should properly validate if called with base mime types", function () {
|
|
let acceptedMimeTypes = "text/*,image/*,application/*";
|
|
|
|
Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
|
|
.ok;
|
|
Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
|
|
.be.ok;
|
|
Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
|
|
.should.be.ok;
|
|
Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes).should.be
|
|
.ok;
|
|
return Dropzone.isValidFile({ type: "some/type" }, acceptedMimeTypes)
|
|
.should.not.be.ok;
|
|
});
|
|
|
|
it("should properly validate if called with mixed mime types", function () {
|
|
let acceptedMimeTypes = "text/*,image/jpeg,application/*";
|
|
|
|
Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
|
|
.ok;
|
|
Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
|
|
.be.ok;
|
|
Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes).should
|
|
.not.be.ok;
|
|
Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
|
|
.should.be.ok;
|
|
return Dropzone.isValidFile({ type: "some/type" }, acceptedMimeTypes)
|
|
.should.not.be.ok;
|
|
});
|
|
|
|
it("should properly validate even with spaces in between", function () {
|
|
let acceptedMimeTypes = "text/html , image/jpeg, application/json";
|
|
|
|
Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
|
|
.ok;
|
|
return Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes)
|
|
.should.be.ok;
|
|
});
|
|
|
|
it("should properly validate extensions", function () {
|
|
let acceptedMimeTypes = "text/html , image/jpeg, .pdf ,.png";
|
|
|
|
Dropzone.isValidFile(
|
|
{ name: "somxsfsd", type: "text/html" },
|
|
acceptedMimeTypes
|
|
).should.be.ok;
|
|
Dropzone.isValidFile(
|
|
{ name: "somesdfsdf", type: "image/jpeg" },
|
|
acceptedMimeTypes
|
|
).should.be.ok;
|
|
Dropzone.isValidFile(
|
|
{ name: "somesdfadfadf", type: "application/json" },
|
|
acceptedMimeTypes
|
|
).should.not.be.ok;
|
|
Dropzone.isValidFile(
|
|
{ name: "some-file file.pdf", type: "random/type" },
|
|
acceptedMimeTypes
|
|
).should.be.ok;
|
|
// .pdf has to be in the end
|
|
Dropzone.isValidFile(
|
|
{ name: "some-file.pdf file.gif", type: "random/type" },
|
|
acceptedMimeTypes
|
|
).should.not.be.ok;
|
|
return Dropzone.isValidFile(
|
|
{ name: "some-file file.png", type: "random/type" },
|
|
acceptedMimeTypes
|
|
).should.be.ok;
|
|
});
|
|
});
|
|
|
|
return describe("Dropzone.confirm", function () {
|
|
beforeEach(() => sinon.stub(window, "confirm"));
|
|
afterEach(() => window.confirm.restore());
|
|
it("should forward to window.confirm and call the callbacks accordingly", function () {
|
|
let rejected;
|
|
let accepted = (rejected = false);
|
|
window.confirm.returns(true);
|
|
Dropzone.confirm(
|
|
"test question",
|
|
() => (accepted = true),
|
|
() => (rejected = true)
|
|
);
|
|
window.confirm.args[0][0].should.equal("test question");
|
|
accepted.should.equal(true);
|
|
rejected.should.equal(false);
|
|
|
|
accepted = rejected = false;
|
|
window.confirm.returns(false);
|
|
Dropzone.confirm(
|
|
"test question 2",
|
|
() => (accepted = true),
|
|
() => (rejected = true)
|
|
);
|
|
window.confirm.args[1][0].should.equal("test question 2");
|
|
accepted.should.equal(false);
|
|
return rejected.should.equal(true);
|
|
});
|
|
|
|
it("should not error if rejected is not provided", function () {
|
|
let rejected;
|
|
let accepted = (rejected = false);
|
|
window.confirm.returns(false);
|
|
Dropzone.confirm("test question", () => (accepted = true));
|
|
window.confirm.args[0][0].should.equal("test question");
|
|
// Nothing should have changed since there is no rejected function.
|
|
accepted.should.equal(false);
|
|
return rejected.should.equal(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Dropzone.getElement() / getElements()", function () {
|
|
let tmpElements = [];
|
|
|
|
beforeEach(function () {
|
|
tmpElements = [];
|
|
tmpElements.push(Dropzone.createElement('<div class="tmptest"></div>'));
|
|
tmpElements.push(
|
|
Dropzone.createElement('<div id="tmptest1" class="random"></div>')
|
|
);
|
|
tmpElements.push(
|
|
Dropzone.createElement('<div class="random div"></div>')
|
|
);
|
|
return tmpElements.forEach((el) => document.body.appendChild(el));
|
|
});
|
|
|
|
afterEach(() => tmpElements.forEach((el) => document.body.removeChild(el)));
|
|
|
|
describe(".getElement()", function () {
|
|
it("should accept a string", function () {
|
|
let el = Dropzone.getElement(".tmptest");
|
|
el.should.equal(tmpElements[0]);
|
|
el = Dropzone.getElement("#tmptest1");
|
|
return el.should.equal(tmpElements[1]);
|
|
});
|
|
it("should accept a node", function () {
|
|
let el = Dropzone.getElement(tmpElements[2]);
|
|
return el.should.equal(tmpElements[2]);
|
|
});
|
|
it("should fail if invalid selector", function () {
|
|
let errorMessage =
|
|
"Invalid `clickable` option provided. Please provide a CSS selector or a plain HTML element.";
|
|
expect(() => Dropzone.getElement("lblasdlfsfl", "clickable")).to.throw(
|
|
errorMessage
|
|
);
|
|
expect(() =>
|
|
Dropzone.getElement({ lblasdlfsfl: "lblasdlfsfl" }, "clickable")
|
|
).to.throw(errorMessage);
|
|
return expect(() =>
|
|
Dropzone.getElement(["lblasdlfsfl"], "clickable")
|
|
).to.throw(errorMessage);
|
|
});
|
|
});
|
|
|
|
return describe(".getElements()", function () {
|
|
it("should accept a list of strings", function () {
|
|
let els = Dropzone.getElements([".tmptest", "#tmptest1"]);
|
|
return els.should.eql([tmpElements[0], tmpElements[1]]);
|
|
});
|
|
it("should accept a list of nodes", function () {
|
|
let els = Dropzone.getElements([tmpElements[0], tmpElements[2]]);
|
|
return els.should.eql([tmpElements[0], tmpElements[2]]);
|
|
});
|
|
it("should accept a mixed list", function () {
|
|
let els = Dropzone.getElements(["#tmptest1", tmpElements[2]]);
|
|
return els.should.eql([tmpElements[1], tmpElements[2]]);
|
|
});
|
|
it("should accept a string selector", function () {
|
|
let els = Dropzone.getElements(".random");
|
|
return els.should.eql([tmpElements[1], tmpElements[2]]);
|
|
});
|
|
it("should accept a single node", function () {
|
|
let els = Dropzone.getElements(tmpElements[1]);
|
|
return els.should.eql([tmpElements[1]]);
|
|
});
|
|
it("should fail if invalid selector", function () {
|
|
let errorMessage =
|
|
"Invalid `clickable` option provided. Please provide a CSS selector, a plain HTML element or a list of those.";
|
|
expect(() => Dropzone.getElements("lblasdlfsfl", "clickable")).to.throw(
|
|
errorMessage
|
|
);
|
|
return expect(() =>
|
|
Dropzone.getElements(["lblasdlfsfl"], "clickable")
|
|
).to.throw(errorMessage);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("constructor()", function () {
|
|
let dropzone = null;
|
|
|
|
afterEach(function () {
|
|
if (dropzone != null) {
|
|
return dropzone.destroy();
|
|
}
|
|
});
|
|
|
|
it("should throw an exception if the element is invalid", () =>
|
|
expect(() => (dropzone = new Dropzone("#invalid-element"))).to.throw(
|
|
"Invalid dropzone element."
|
|
));
|
|
|
|
it("should throw an exception if assigned twice to the same element", function () {
|
|
let element = document.createElement("div");
|
|
dropzone = new Dropzone(element, { url: "url" });
|
|
return expect(() => new Dropzone(element, { url: "url" })).to.throw(
|
|
"Dropzone already attached."
|
|
);
|
|
});
|
|
|
|
it("should throw an exception if both acceptedFiles and acceptedMimeTypes are specified", function () {
|
|
let element = document.createElement("div");
|
|
return expect(
|
|
() =>
|
|
(dropzone = new Dropzone(element, {
|
|
url: "test",
|
|
acceptedFiles: "param",
|
|
acceptedMimeTypes: "types",
|
|
}))
|
|
).to.throw(
|
|
"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."
|
|
);
|
|
});
|
|
|
|
it("should set itself as element.dropzone", function () {
|
|
let element = document.createElement("div");
|
|
dropzone = new Dropzone(element, { url: "url" });
|
|
return element.dropzone.should.equal(dropzone);
|
|
});
|
|
|
|
it("should add itself to Dropzone.instances", function () {
|
|
let element = document.createElement("div");
|
|
dropzone = new Dropzone(element, { url: "url" });
|
|
return Dropzone.instances[Dropzone.instances.length - 1].should.equal(
|
|
dropzone
|
|
);
|
|
});
|
|
|
|
it("should use the action attribute not the element with the name action", function () {
|
|
let element = Dropzone.createElement(
|
|
'<form action="real-action"><input type="hidden" name="action" value="wrong-action" /></form>'
|
|
);
|
|
dropzone = new Dropzone(element);
|
|
return dropzone.options.url.should.equal("real-action");
|
|
});
|
|
|
|
return describe("options", function () {
|
|
let element = null;
|
|
let element2 = null;
|
|
beforeEach(function () {
|
|
element = document.createElement("div");
|
|
element.id = "test-element";
|
|
element2 = document.createElement("div");
|
|
element2.id = "test-element2";
|
|
return (Dropzone.options.testElement = {
|
|
url: "/some/url",
|
|
parallelUploads: 10,
|
|
});
|
|
});
|
|
afterEach(() => delete Dropzone.options.testElement);
|
|
|
|
it("should take the options set in Dropzone.options", function () {
|
|
dropzone = new Dropzone(element);
|
|
dropzone.options.url.should.equal("/some/url");
|
|
return dropzone.options.parallelUploads.should.equal(10);
|
|
});
|
|
|
|
it("should prefer passed options over Dropzone.options", function () {
|
|
dropzone = new Dropzone(element, { url: "/some/other/url" });
|
|
return dropzone.options.url.should.equal("/some/other/url");
|
|
});
|
|
|
|
it("should take the default options if nothing set in Dropzone.options", function () {
|
|
dropzone = new Dropzone(element2, { url: "/some/url" });
|
|
return dropzone.options.parallelUploads.should.equal(2);
|
|
});
|
|
|
|
it("should call the fallback function if forceFallback == true", (done) =>
|
|
(dropzone = new Dropzone(element, {
|
|
url: "/some/other/url",
|
|
forceFallback: true,
|
|
fallback() {
|
|
return done();
|
|
},
|
|
})));
|
|
|
|
it("should set acceptedFiles if deprecated acceptedMimetypes option has been passed", function () {
|
|
dropzone = new Dropzone(element, {
|
|
url: "/some/other/url",
|
|
acceptedMimeTypes: "my/type",
|
|
});
|
|
return dropzone.options.acceptedFiles.should.equal("my/type");
|
|
});
|
|
|
|
return describe("options.clickable", function () {
|
|
let clickableElement = null;
|
|
dropzone = null;
|
|
beforeEach(function () {
|
|
clickableElement = document.createElement("div");
|
|
clickableElement.className = "some-clickable";
|
|
return document.body.appendChild(clickableElement);
|
|
});
|
|
afterEach(function () {
|
|
document.body.removeChild(clickableElement);
|
|
if (dropzone != null) {
|
|
return dropzone.destroy;
|
|
}
|
|
});
|
|
|
|
it("should use the default element if clickable == true", function () {
|
|
dropzone = new Dropzone(element, { clickable: true });
|
|
return dropzone.clickableElements.should.eql([dropzone.element]);
|
|
});
|
|
it("should lookup the element if clickable is a CSS selector", function () {
|
|
dropzone = new Dropzone(element, { clickable: ".some-clickable" });
|
|
return dropzone.clickableElements.should.eql([clickableElement]);
|
|
});
|
|
it("should simply use the provided element", function () {
|
|
dropzone = new Dropzone(element, { clickable: clickableElement });
|
|
return dropzone.clickableElements.should.eql([clickableElement]);
|
|
});
|
|
it("should accept multiple clickable elements", function () {
|
|
dropzone = new Dropzone(element, {
|
|
clickable: [document.body, ".some-clickable"],
|
|
});
|
|
return dropzone.clickableElements.should.eql([
|
|
document.body,
|
|
clickableElement,
|
|
]);
|
|
});
|
|
it("should throw an exception if the element is invalid", () =>
|
|
expect(
|
|
() =>
|
|
(dropzone = new Dropzone(element, {
|
|
clickable: ".some-invalid-clickable",
|
|
}))
|
|
).to.throw(
|
|
"Invalid `clickable` option provided. Please provide a CSS selector, a plain HTML element or a list of those."
|
|
));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("init()", function () {
|
|
describe("clickable", function () {
|
|
let dropzones = {
|
|
"using acceptedFiles": new Dropzone(
|
|
Dropzone.createElement('<form action="/"></form>'),
|
|
{ clickable: true, acceptedFiles: "audio/*,video/*" }
|
|
),
|
|
"using acceptedMimeTypes": new Dropzone(
|
|
Dropzone.createElement('<form action="/"></form>'),
|
|
{ clickable: true, acceptedMimeTypes: "audio/*,video/*" }
|
|
),
|
|
};
|
|
|
|
it("should not add an accept attribute if no acceptParameter", function () {
|
|
let dropzone = new Dropzone(
|
|
Dropzone.createElement('<form action="/"></form>'),
|
|
{ clickable: true, acceptParameter: null, acceptedMimeTypes: null }
|
|
);
|
|
return dropzone.hiddenFileInput.hasAttribute("accept").should.be.false;
|
|
});
|
|
|
|
return (() => {
|
|
let result = [];
|
|
for (let name in dropzones) {
|
|
var dropzone = dropzones[name];
|
|
result.push(
|
|
describe(name, () =>
|
|
(function (dropzone) {
|
|
it("should create a hidden file input if clickable", function () {
|
|
dropzone.hiddenFileInput.should.be.ok;
|
|
dropzone.hiddenFileInput.tagName.should.equal("INPUT");
|
|
});
|
|
|
|
it("should have a tabindex of -1", function () {
|
|
dropzone.hiddenFileInput.tabIndex.should.equal(-1);
|
|
});
|
|
|
|
it("should use the acceptParameter", () =>
|
|
dropzone.hiddenFileInput
|
|
.getAttribute("accept")
|
|
.should.equal("audio/*,video/*"));
|
|
|
|
it("should create a new input element when something is selected to reset the input field", () =>
|
|
(() => {
|
|
let result1 = [];
|
|
for (let i = 0; i <= 3; i++) {
|
|
let { hiddenFileInput } = dropzone;
|
|
let event = document.createEvent("HTMLEvents");
|
|
event.initEvent("change", true, true);
|
|
hiddenFileInput.dispatchEvent(event);
|
|
dropzone.hiddenFileInput.should.not.equal(
|
|
hiddenFileInput
|
|
);
|
|
result1.push(
|
|
Dropzone.elementInside(hiddenFileInput, document).should
|
|
.not.be.ok
|
|
);
|
|
}
|
|
return result1;
|
|
})());
|
|
})(dropzone)
|
|
)
|
|
);
|
|
}
|
|
return result;
|
|
})();
|
|
});
|
|
|
|
it("should create a .dz-message element", function () {
|
|
let element = Dropzone.createElement(
|
|
'<form class="dropzone" action="/"></form>'
|
|
);
|
|
let dropzone = new Dropzone(element, {
|
|
clickable: true,
|
|
acceptParameter: null,
|
|
acceptedMimeTypes: null,
|
|
});
|
|
return element.querySelector(".dz-message").should.be.instanceof(Element);
|
|
});
|
|
|
|
it("should not create a .dz-message element if there already is one", function () {
|
|
let element = Dropzone.createElement(
|
|
'<form class="dropzone" action="/"></form>'
|
|
);
|
|
let msg = Dropzone.createElement('<div class="dz-message">TEST</div>');
|
|
element.appendChild(msg);
|
|
|
|
let dropzone = new Dropzone(element, {
|
|
clickable: true,
|
|
acceptParameter: null,
|
|
acceptedMimeTypes: null,
|
|
});
|
|
element.querySelector(".dz-message").should.equal(msg);
|
|
|
|
return element.querySelectorAll(".dz-message").length.should.equal(1);
|
|
});
|
|
});
|
|
|
|
describe("options", function () {
|
|
let element = null;
|
|
let dropzone = null;
|
|
|
|
beforeEach(function () {
|
|
element = Dropzone.createElement("<div></div>");
|
|
return (dropzone = new Dropzone(element, {
|
|
maxFilesize: 4,
|
|
url: "url",
|
|
acceptedMimeTypes: "audio/*,image/png",
|
|
maxFiles: 3,
|
|
}));
|
|
});
|
|
|
|
return describe("file specific", function () {
|
|
let file = null;
|
|
beforeEach(function () {
|
|
file = {
|
|
name: "test name",
|
|
size: 2 * 1024 * 1024,
|
|
width: 200,
|
|
height: 100,
|
|
upload: {
|
|
filename: "test name",
|
|
},
|
|
};
|
|
return dropzone.options.addedfile.call(dropzone, file);
|
|
});
|
|
|
|
describe(".addedFile()", () =>
|
|
it("should properly create the previewElement", function () {
|
|
file.previewElement.should.be.instanceof(Element);
|
|
|
|
file.previewElement
|
|
.querySelector("[data-dz-name]")
|
|
.innerHTML.should.eql("test name");
|
|
return file.previewElement
|
|
.querySelector("[data-dz-size]")
|
|
.innerHTML.should.eql("<strong>2.1</strong> MB");
|
|
}));
|
|
|
|
describe(".error()", function () {
|
|
it("should properly insert the error", function () {
|
|
dropzone.options.error.call(dropzone, file, "test message");
|
|
|
|
return file.previewElement
|
|
.querySelector("[data-dz-errormessage]")
|
|
.innerHTML.should.eql("test message");
|
|
});
|
|
|
|
it("should properly insert the error when provided with an object containing the error", function () {
|
|
dropzone.options.error.call(dropzone, file, {
|
|
error: "test message",
|
|
});
|
|
|
|
return file.previewElement
|
|
.querySelector("[data-dz-errormessage]")
|
|
.innerHTML.should.eql("test message");
|
|
});
|
|
});
|
|
|
|
describe(".thumbnail()", () =>
|
|
it("should properly insert the error", function () {
|
|
let transparentGif =
|
|
"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
|
|
dropzone.options.thumbnail.call(dropzone, file, transparentGif);
|
|
let thumbnail = file.previewElement.querySelector(
|
|
"[data-dz-thumbnail]"
|
|
);
|
|
thumbnail.src.should.eql(transparentGif);
|
|
return thumbnail.alt.should.eql("test name");
|
|
}));
|
|
|
|
describe(".uploadprogress()", () =>
|
|
it("should properly set the width", function () {
|
|
dropzone.options.uploadprogress.call(dropzone, file, 0);
|
|
file.previewElement
|
|
.querySelector("[data-dz-uploadprogress]")
|
|
.style.width.should.eql("0%");
|
|
dropzone.options.uploadprogress.call(dropzone, file, 80);
|
|
file.previewElement
|
|
.querySelector("[data-dz-uploadprogress]")
|
|
.style.width.should.eql("80%");
|
|
dropzone.options.uploadprogress.call(dropzone, file, 90);
|
|
file.previewElement
|
|
.querySelector("[data-dz-uploadprogress]")
|
|
.style.width.should.eql("90%");
|
|
dropzone.options.uploadprogress.call(dropzone, file, 100);
|
|
return file.previewElement
|
|
.querySelector("[data-dz-uploadprogress]")
|
|
.style.width.should.eql("100%");
|
|
}));
|
|
|
|
return describe(".resize()", function () {
|
|
describe("with default thumbnail settings", function () {
|
|
it("should properly return target dimensions for 'contain'", function () {
|
|
let info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
120,
|
|
120,
|
|
"crop"
|
|
);
|
|
info.trgWidth.should.eql(120);
|
|
info.trgHeight.should.eql(100);
|
|
info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
100,
|
|
100,
|
|
"crop"
|
|
);
|
|
info.trgWidth.should.eql(100);
|
|
return info.trgHeight.should.eql(100);
|
|
});
|
|
|
|
it("should properly return target dimensions for 'contain'", function () {
|
|
let info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
120,
|
|
120,
|
|
"contain"
|
|
);
|
|
info.trgWidth.should.eql(120);
|
|
info.trgHeight.should.eql(60);
|
|
info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
100,
|
|
100,
|
|
"contain"
|
|
);
|
|
info.trgWidth.should.eql(100);
|
|
return info.trgHeight.should.eql(50);
|
|
});
|
|
});
|
|
|
|
return describe("with null thumbnail settings", function () {
|
|
it("should properly return target dimensions for crop", function () {
|
|
let testSettings = [
|
|
[null, null],
|
|
[null, 80],
|
|
[150, null],
|
|
];
|
|
|
|
return (() => {
|
|
let result = [];
|
|
for (let i = 0; i < testSettings.length; i++) {
|
|
let setting = testSettings[i];
|
|
let info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
setting[0],
|
|
setting[1],
|
|
"crop"
|
|
);
|
|
|
|
if (i === 0) {
|
|
info.trgWidth.should.eql(200);
|
|
info.trgHeight.should.eql(100);
|
|
}
|
|
|
|
if (i === 1) {
|
|
info.trgWidth.should.eql(160);
|
|
info.trgHeight.should.eql(80);
|
|
}
|
|
|
|
if (i === 2) {
|
|
info.trgWidth.should.eql(150);
|
|
result.push(info.trgHeight.should.eql(75));
|
|
} else {
|
|
result.push(undefined);
|
|
}
|
|
}
|
|
return result;
|
|
})();
|
|
});
|
|
|
|
it("should properly return target dimensions for contain", function () {
|
|
let testSettings = [
|
|
[null, 80],
|
|
[150, null],
|
|
];
|
|
|
|
return (() => {
|
|
let result = [];
|
|
for (let i = 0; i < testSettings.length; i++) {
|
|
let setting = testSettings[i];
|
|
let info = dropzone.options.resize.call(
|
|
dropzone,
|
|
file,
|
|
setting[0],
|
|
setting[1],
|
|
"contain"
|
|
);
|
|
|
|
if (i === 0) {
|
|
info.trgWidth.should.eql(160);
|
|
info.trgHeight.should.eql(80);
|
|
}
|
|
|
|
if (i === 1) {
|
|
info.trgWidth.should.eql(150);
|
|
result.push(info.trgHeight.should.eql(75));
|
|
} else {
|
|
result.push(undefined);
|
|
}
|
|
}
|
|
return result;
|
|
})();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("instance", function () {
|
|
let element = null;
|
|
let dropzone = null;
|
|
let requests = null;
|
|
beforeEach(function () {
|
|
requests = [];
|
|
xhr.onCreate = (xhr) => requests.push(xhr);
|
|
|
|
element = Dropzone.createElement("<div></div>");
|
|
document.body.appendChild(element);
|
|
return (dropzone = new Dropzone(element, {
|
|
maxFilesize: 4,
|
|
maxFiles: 100,
|
|
url: "url",
|
|
acceptedMimeTypes: "audio/*,image/png",
|
|
uploadprogress() {},
|
|
}));
|
|
});
|
|
afterEach(function () {
|
|
document.body.removeChild(element);
|
|
dropzone.destroy();
|
|
return xhr.restore();
|
|
});
|
|
|
|
describe(".accept()", function () {
|
|
it("should pass if the filesize is OK", () =>
|
|
dropzone.accept(
|
|
{ size: 2 * 1024 * 1024, type: "audio/mp3" },
|
|
(err) => expect(err).to.be.undefined
|
|
));
|
|
|
|
it("shouldn't pass if the filesize is too big", () =>
|
|
dropzone.accept({ size: 10 * 1024 * 1024, type: "audio/mp3" }, (err) =>
|
|
err.should.eql("File is too big (10MiB). Max filesize: 4MiB.")
|
|
));
|
|
|
|
it("should properly accept files which mime types are listed in acceptedFiles", function () {
|
|
dropzone.accept(
|
|
{ type: "audio/mp3" },
|
|
(err) => expect(err).to.be.undefined
|
|
);
|
|
dropzone.accept(
|
|
{ type: "image/png" },
|
|
(err) => expect(err).to.be.undefined
|
|
);
|
|
return dropzone.accept(
|
|
{ type: "audio/wav" },
|
|
(err) => expect(err).to.be.undefined
|
|
);
|
|
});
|
|
|
|
it("should properly reject files when the mime type isn't listed in acceptedFiles", () =>
|
|
dropzone.accept({ type: "image/jpeg" }, (err) =>
|
|
err.should.eql("You can't upload files of this type.")
|
|
));
|
|
|
|
it("should fail if maxFiles has been exceeded and call the event maxfilesexceeded", function () {
|
|
sinon.stub(dropzone, "getAcceptedFiles");
|
|
let file = { type: "audio/mp3" };
|
|
|
|
dropzone.getAcceptedFiles.returns({ length: 99 });
|
|
|
|
dropzone.options.dictMaxFilesExceeded =
|
|
"You can only upload {{maxFiles}} files.";
|
|
|
|
let called = false;
|
|
dropzone.on("maxfilesexceeded", function (lfile) {
|
|
lfile.should.equal(file);
|
|
return (called = true);
|
|
});
|
|
|
|
dropzone.accept(file, (err) => expect(err).to.be.undefined);
|
|
called.should.not.be.ok;
|
|
|
|
dropzone.getAcceptedFiles.returns({ length: 100 });
|
|
dropzone.accept(file, (err) =>
|
|
expect(err).to.equal("You can only upload 100 files.")
|
|
);
|
|
called.should.be.ok;
|
|
|
|
return dropzone.getAcceptedFiles.restore();
|
|
});
|
|
|
|
it("should properly handle if maxFiles is 0", function () {
|
|
let file = { type: "audio/mp3" };
|
|
|
|
dropzone.options.maxFiles = 0;
|
|
|
|
let called = false;
|
|
dropzone.on("maxfilesexceeded", function (lfile) {
|
|
lfile.should.equal(file);
|
|
return (called = true);
|
|
});
|
|
|
|
dropzone.accept(file, (err) =>
|
|
expect(err).to.equal("You can not upload any more files.")
|
|
);
|
|
return called.should.be.ok;
|
|
});
|
|
});
|
|
|
|
describe(".removeFile()", () =>
|
|
it("should abort uploading if file is currently being uploaded", function (done) {
|
|
let mockFile = getMockFile();
|
|
dropzone.uploadFile = function (file) {};
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
sinon.stub(dropzone, "cancelUpload");
|
|
|
|
dropzone.addFile(mockFile);
|
|
return setTimeout(function () {
|
|
mockFile.status.should.equal(Dropzone.UPLOADING);
|
|
dropzone.getUploadingFiles()[0].should.equal(mockFile);
|
|
|
|
dropzone.cancelUpload.callCount.should.equal(0);
|
|
dropzone.removeFile(mockFile);
|
|
dropzone.cancelUpload.callCount.should.equal(1);
|
|
return done();
|
|
}, 100);
|
|
}));
|
|
|
|
describe(".cancelUpload()", function () {
|
|
it("should properly cancel upload if file currently uploading", function (done) {
|
|
let mockFile = getMockFile();
|
|
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
mockFile.status.should.equal(Dropzone.UPLOADING);
|
|
dropzone.getUploadingFiles()[0].should.equal(mockFile);
|
|
dropzone.cancelUpload(mockFile);
|
|
mockFile.status.should.equal(Dropzone.CANCELED);
|
|
dropzone.getUploadingFiles().length.should.equal(0);
|
|
dropzone.getQueuedFiles().length.should.equal(0);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should properly cancel the upload if file is not yet uploading", function () {
|
|
let mockFile = getMockFile();
|
|
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
// Making sure the file stays in the queue.
|
|
dropzone.options.parallelUploads = 0;
|
|
|
|
dropzone.addFile(mockFile);
|
|
mockFile.status.should.equal(Dropzone.QUEUED);
|
|
dropzone.getQueuedFiles()[0].should.equal(mockFile);
|
|
|
|
dropzone.cancelUpload(mockFile);
|
|
mockFile.status.should.equal(Dropzone.CANCELED);
|
|
dropzone.getQueuedFiles().length.should.equal(0);
|
|
return dropzone.getUploadingFiles().length.should.equal(0);
|
|
});
|
|
|
|
it("should call processQueue()", function (done) {
|
|
let mockFile = getMockFile();
|
|
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
// Making sure the file stays in the queue.
|
|
dropzone.options.parallelUploads = 0;
|
|
|
|
sinon.spy(dropzone, "processQueue");
|
|
|
|
dropzone.addFile(mockFile);
|
|
return setTimeout(function () {
|
|
dropzone.processQueue.callCount.should.equal(1);
|
|
|
|
dropzone.cancelUpload(mockFile);
|
|
|
|
dropzone.processQueue.callCount.should.equal(2);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should properly cancel all files with the same XHR if uploadMultiple is true", function (done) {
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
// Making sure the file stays in the queue.
|
|
dropzone.options.uploadMultiple = true;
|
|
dropzone.options.parallelUploads = 3;
|
|
|
|
sinon.spy(dropzone, "processFiles");
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
|
|
return setTimeout(function () {
|
|
dropzone.processFiles.callCount.should.equal(1);
|
|
|
|
sinon.spy(mock1.xhr, "abort");
|
|
|
|
dropzone.cancelUpload(mock1);
|
|
|
|
expect(mock1.xhr === mock2.xhr && mock2.xhr === mock3.xhr).to.be.ok;
|
|
|
|
mock1.status.should.equal(Dropzone.CANCELED);
|
|
mock2.status.should.equal(Dropzone.CANCELED);
|
|
mock3.status.should.equal(Dropzone.CANCELED);
|
|
|
|
// The XHR should only be aborted once!
|
|
mock1.xhr.abort.callCount.should.equal(1);
|
|
|
|
return done();
|
|
}, 10);
|
|
});
|
|
});
|
|
|
|
describe(".disable()", () =>
|
|
it("should properly cancel all pending uploads", function (done) {
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
dropzone.options.parallelUploads = 1;
|
|
|
|
dropzone.addFile(getMockFile());
|
|
dropzone.addFile(getMockFile());
|
|
|
|
return setTimeout(function () {
|
|
dropzone.getUploadingFiles().length.should.equal(1);
|
|
dropzone.getQueuedFiles().length.should.equal(1);
|
|
dropzone.files.length.should.equal(2);
|
|
|
|
sinon.spy(requests[0], "abort");
|
|
|
|
requests[0].abort.callCount.should.equal(0);
|
|
|
|
dropzone.disable();
|
|
|
|
requests[0].abort.callCount.should.equal(1);
|
|
|
|
dropzone.getUploadingFiles().length.should.equal(0);
|
|
dropzone.getQueuedFiles().length.should.equal(0);
|
|
dropzone.files.length.should.equal(2);
|
|
|
|
dropzone.files[0].status.should.equal(Dropzone.CANCELED);
|
|
dropzone.files[1].status.should.equal(Dropzone.CANCELED);
|
|
return done();
|
|
}, 10);
|
|
}));
|
|
|
|
describe(".destroy()", function () {
|
|
it("should properly cancel all pending uploads and remove all file references", function (done) {
|
|
dropzone.accept = (file, done) => done();
|
|
|
|
dropzone.options.parallelUploads = 1;
|
|
|
|
dropzone.addFile(getMockFile());
|
|
dropzone.addFile(getMockFile());
|
|
|
|
return setTimeout(function () {
|
|
dropzone.getUploadingFiles().length.should.equal(1);
|
|
dropzone.getQueuedFiles().length.should.equal(1);
|
|
dropzone.files.length.should.equal(2);
|
|
|
|
sinon.spy(dropzone, "disable");
|
|
|
|
dropzone.destroy();
|
|
|
|
dropzone.disable.callCount.should.equal(1);
|
|
element.should.not.have.property("dropzone");
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should be able to create instance of dropzone on the same element after destroy", function () {
|
|
dropzone.destroy();
|
|
return (() =>
|
|
new Dropzone(element, {
|
|
maxFilesize: 4,
|
|
url: "url",
|
|
acceptedMimeTypes: "audio/*,image/png",
|
|
uploadprogress() {},
|
|
})).should.not.throw(Error);
|
|
});
|
|
|
|
it("should remove itself from Dropzone.instances", function () {
|
|
(Dropzone.instances.indexOf(dropzone) !== -1).should.be.ok;
|
|
dropzone.destroy();
|
|
return (Dropzone.instances.indexOf(dropzone) === -1).should.be.ok;
|
|
});
|
|
});
|
|
|
|
describe(".filesize()", function () {
|
|
it("should handle files with 0 size properly", () =>
|
|
dropzone.filesize(0).should.eql("<strong>0</strong> b"));
|
|
|
|
it("should convert to KiloBytes, etc..", function () {
|
|
dropzone.options.filesizeBase.should.eql(1000); // Just making sure the default config is correct
|
|
|
|
dropzone.filesize(2 * 1000 * 1000).should.eql("<strong>2</strong> MB");
|
|
dropzone
|
|
.filesize(2 * 1024 * 1024)
|
|
.should.eql("<strong>2.1</strong> MB");
|
|
|
|
dropzone
|
|
.filesize(2 * 1000 * 1000 * 1000)
|
|
.should.eql("<strong>2</strong> GB");
|
|
dropzone
|
|
.filesize(2 * 1024 * 1024 * 1024)
|
|
.should.eql("<strong>2.1</strong> GB");
|
|
|
|
dropzone
|
|
.filesize(2.5111 * 1000 * 1000 * 1000)
|
|
.should.eql("<strong>2.5</strong> GB");
|
|
dropzone.filesize(1.1 * 1000).should.eql("<strong>1.1</strong> KB");
|
|
return dropzone
|
|
.filesize(999 * 1000)
|
|
.should.eql("<strong>1</strong> MB");
|
|
});
|
|
|
|
it("should convert to KibiBytes, etc.. when the filesizeBase is changed to 1024", function () {
|
|
dropzone.options.filesizeBase = 1024;
|
|
|
|
dropzone.filesize(2 * 1024 * 1024).should.eql("<strong>2</strong> MB");
|
|
return dropzone
|
|
.filesize(2 * 1000 * 1000)
|
|
.should.eql("<strong>1.9</strong> MB");
|
|
});
|
|
});
|
|
|
|
describe("._updateMaxFilesReachedClass()", function () {
|
|
it("should properly add the dz-max-files-reached class", function () {
|
|
dropzone.getAcceptedFiles = () => ({ length: 10 });
|
|
dropzone.options.maxFiles = 10;
|
|
dropzone.element.classList.contains("dz-max-files-reached").should.not
|
|
.be.ok;
|
|
dropzone._updateMaxFilesReachedClass();
|
|
return dropzone.element.classList.contains("dz-max-files-reached")
|
|
.should.be.ok;
|
|
});
|
|
it("should fire the 'maxfilesreached' event when appropriate", function () {
|
|
let spy = sinon.spy();
|
|
dropzone.on("maxfilesreached", () => spy());
|
|
dropzone.getAcceptedFiles = () => ({ length: 9 });
|
|
dropzone.options.maxFiles = 10;
|
|
dropzone._updateMaxFilesReachedClass();
|
|
spy.notCalled.should.be.true;
|
|
dropzone.getAcceptedFiles = () => ({ length: 10 });
|
|
dropzone._updateMaxFilesReachedClass();
|
|
spy.called.should.be.true;
|
|
dropzone.getAcceptedFiles = () => ({ length: 11 });
|
|
dropzone._updateMaxFilesReachedClass();
|
|
spy.calledOnce.should.be.true;
|
|
}); //ie, it has not been called again
|
|
|
|
it("should properly remove the dz-max-files-reached class", function () {
|
|
dropzone.getAcceptedFiles = () => ({ length: 10 });
|
|
dropzone.options.maxFiles = 10;
|
|
dropzone.element.classList.contains("dz-max-files-reached").should.not
|
|
.be.ok;
|
|
dropzone._updateMaxFilesReachedClass();
|
|
dropzone.element.classList.contains("dz-max-files-reached").should.be
|
|
.ok;
|
|
dropzone.getAcceptedFiles = () => ({ length: 9 });
|
|
dropzone._updateMaxFilesReachedClass();
|
|
return dropzone.element.classList.contains("dz-max-files-reached")
|
|
.should.not.be.ok;
|
|
});
|
|
});
|
|
|
|
return describe("events", () => {
|
|
describe("progress updates", () =>
|
|
it("should properly emit a totaluploadprogress event", function (done) {
|
|
dropzone.files = [
|
|
{
|
|
size: 1990,
|
|
accepted: true,
|
|
status: Dropzone.UPLOADING,
|
|
upload: {
|
|
progress: 20,
|
|
total: 2000, // The bytes to upload are higher than the file size
|
|
bytesSent: 400,
|
|
},
|
|
},
|
|
{
|
|
size: 1990,
|
|
accepted: true,
|
|
status: Dropzone.UPLOADING,
|
|
upload: {
|
|
progress: 10,
|
|
total: 2000, // The bytes to upload are higher than the file size
|
|
bytesSent: 200,
|
|
},
|
|
},
|
|
];
|
|
|
|
let _called = 0;
|
|
|
|
dropzone.on("totaluploadprogress", function (progress) {
|
|
progress.should.equal(totalProgressExpectation);
|
|
if (++_called === 3) {
|
|
return done();
|
|
}
|
|
});
|
|
|
|
var totalProgressExpectation = 15;
|
|
dropzone.emit("uploadprogress", {});
|
|
|
|
totalProgressExpectation = 97.5;
|
|
dropzone.files[0].upload.bytesSent = 2000;
|
|
dropzone.files[1].upload.bytesSent = 1900;
|
|
// It shouldn't matter that progress is not properly updated since the total size
|
|
// should be calculated from the bytes
|
|
dropzone.emit("uploadprogress", {});
|
|
|
|
totalProgressExpectation = 100;
|
|
dropzone.files[0].upload.bytesSent = 2000;
|
|
dropzone.files[1].upload.bytesSent = 2000;
|
|
// It shouldn't matter that progress is not properly updated since the total size
|
|
// should be calculated from the bytes
|
|
dropzone.emit("uploadprogress", {});
|
|
|
|
// Just so the afterEach hook doesn't try to cancel them.
|
|
dropzone.files[0].status = Dropzone.CANCELED;
|
|
return (dropzone.files[1].status = Dropzone.CANCELED);
|
|
}));
|
|
|
|
it("should emit DOM events", function (done) {
|
|
let element = Dropzone.createElement(`<form action="/the/url">
|
|
<input type="hidden" name="test" value="hidden" />
|
|
<input type="checkbox" name="unchecked" value="1" />
|
|
<input type="checkbox" name="checked" value="value1" checked="checked" />
|
|
<input type="radio" value="radiovalue1" name="radio1" />
|
|
<input type="radio" value="radiovalue2" name="radio1" checked="checked" />
|
|
<select name="select"><option value="1">1</option><option value="2" selected>2</option></select>
|
|
</form>`);
|
|
dropzone = new Dropzone(element, { url: "/the/url" });
|
|
|
|
var domEventTriggered = false;
|
|
element.addEventListener("dropzone:sending", function (evt) {
|
|
domEventTriggered = true;
|
|
});
|
|
|
|
let mock1 = getMockFile();
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
expect(domEventTriggered).to.equal(true);
|
|
done();
|
|
}, 10);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("helper function", function () {
|
|
let element = null;
|
|
let dropzone = null;
|
|
beforeEach(function () {
|
|
element = Dropzone.createElement("<div></div>");
|
|
return (dropzone = new Dropzone(element, { url: "url" }));
|
|
});
|
|
|
|
describe("getExistingFallback()", function () {
|
|
it("should return undefined if no fallback", () =>
|
|
expect(dropzone.getExistingFallback()).to.equal(undefined));
|
|
|
|
it("should only return the fallback element if it contains exactly fallback", function () {
|
|
element.appendChild(
|
|
Dropzone.createElement('<form class="fallbacks"></form>')
|
|
);
|
|
element.appendChild(
|
|
Dropzone.createElement('<form class="sfallback"></form>')
|
|
);
|
|
return expect(dropzone.getExistingFallback()).to.equal(undefined);
|
|
});
|
|
|
|
it("should return divs as fallback", function () {
|
|
let fallback = Dropzone.createElement(
|
|
'<form class=" abc fallback test "></form>'
|
|
);
|
|
element.appendChild(fallback);
|
|
return fallback.should.equal(dropzone.getExistingFallback());
|
|
});
|
|
it("should return forms as fallback", function () {
|
|
let fallback = Dropzone.createElement(
|
|
'<div class=" abc fallback test "></div>'
|
|
);
|
|
element.appendChild(fallback);
|
|
return fallback.should.equal(dropzone.getExistingFallback());
|
|
});
|
|
});
|
|
|
|
describe("getFallbackForm()", function () {
|
|
it("should use the paramName without [0] if uploadMultiple is false", function () {
|
|
dropzone.options.uploadMultiple = false;
|
|
dropzone.options.paramName = "myFile";
|
|
let fallback = dropzone.getFallbackForm();
|
|
let fileInput = fallback.querySelector("input[type=file]");
|
|
return fileInput.name.should.equal("myFile");
|
|
});
|
|
it("should properly add [0] to the file name if uploadMultiple is true", function () {
|
|
dropzone.options.uploadMultiple = true;
|
|
dropzone.options.paramName = "myFile";
|
|
let fallback = dropzone.getFallbackForm();
|
|
let fileInput = fallback.querySelector("input[type=file]");
|
|
return fileInput.name.should.equal("myFile[0]");
|
|
});
|
|
});
|
|
|
|
describe("getAcceptedFiles() / getRejectedFiles()", function () {
|
|
let mock2, mock3, mock4;
|
|
let mock1 = (mock2 = mock3 = mock4 = null);
|
|
beforeEach(function () {
|
|
mock1 = getMockFile();
|
|
mock2 = getMockFile();
|
|
mock3 = getMockFile();
|
|
mock4 = getMockFile();
|
|
dropzone.options.accept = function (file, done) {
|
|
if (file === mock1 || file === mock3) {
|
|
return done();
|
|
} else {
|
|
return done("error");
|
|
}
|
|
};
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
return dropzone.addFile(mock4);
|
|
});
|
|
|
|
it("getAcceptedFiles() should only return accepted files", () =>
|
|
dropzone.getAcceptedFiles().should.eql([mock1, mock3]));
|
|
it("getRejectedFiles() should only return rejected files", () =>
|
|
dropzone.getRejectedFiles().should.eql([mock2, mock4]));
|
|
});
|
|
|
|
describe("getQueuedFiles()", () =>
|
|
it("should return all files with the status Dropzone.QUEUED", function () {
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
let mock4 = getMockFile();
|
|
|
|
dropzone.options.accept = (file, done) => (file.done = done);
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
dropzone.addFile(mock4);
|
|
|
|
dropzone.getQueuedFiles().should.eql([]);
|
|
|
|
mock1.done();
|
|
mock3.done();
|
|
|
|
dropzone.getQueuedFiles().should.eql([mock1, mock3]);
|
|
mock1.status.should.equal(Dropzone.QUEUED);
|
|
mock3.status.should.equal(Dropzone.QUEUED);
|
|
mock2.status.should.equal(Dropzone.ADDED);
|
|
return mock4.status.should.equal(Dropzone.ADDED);
|
|
}));
|
|
|
|
describe("getUploadingFiles()", () =>
|
|
it("should return all files with the status Dropzone.UPLOADING", function (done) {
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
let mock4 = getMockFile();
|
|
|
|
dropzone.options.accept = (file, _done) => (file.done = _done);
|
|
dropzone.uploadFile = function () {};
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
dropzone.addFile(mock4);
|
|
|
|
dropzone.getUploadingFiles().should.eql([]);
|
|
|
|
mock1.done();
|
|
mock3.done();
|
|
|
|
return setTimeout(function () {
|
|
dropzone.getUploadingFiles().should.eql([mock1, mock3]);
|
|
mock1.status.should.equal(Dropzone.UPLOADING);
|
|
mock3.status.should.equal(Dropzone.UPLOADING);
|
|
mock2.status.should.equal(Dropzone.ADDED);
|
|
mock4.status.should.equal(Dropzone.ADDED);
|
|
return done();
|
|
}, 10);
|
|
}));
|
|
|
|
describe("getActiveFiles()", () =>
|
|
it("should return all files with the status Dropzone.UPLOADING or Dropzone.QUEUED", function (done) {
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
let mock4 = getMockFile();
|
|
|
|
dropzone.options.accept = (file, _done) => (file.done = _done);
|
|
dropzone.uploadFile = function () {};
|
|
dropzone.options.parallelUploads = 2;
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
dropzone.addFile(mock4);
|
|
|
|
dropzone.getActiveFiles().should.eql([]);
|
|
|
|
mock1.done();
|
|
mock3.done();
|
|
mock4.done();
|
|
|
|
return setTimeout(function () {
|
|
dropzone.getActiveFiles().should.eql([mock1, mock3, mock4]);
|
|
mock1.status.should.equal(Dropzone.UPLOADING);
|
|
mock3.status.should.equal(Dropzone.UPLOADING);
|
|
mock2.status.should.equal(Dropzone.ADDED);
|
|
mock4.status.should.equal(Dropzone.QUEUED);
|
|
return done();
|
|
}, 10);
|
|
}));
|
|
|
|
return describe("getFilesWithStatus()", () =>
|
|
it("should return all files with provided status", function () {
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
let mock4 = getMockFile();
|
|
|
|
dropzone.options.accept = (file, _done) => (file.done = _done);
|
|
dropzone.uploadFile = function () {};
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
dropzone.addFile(mock4);
|
|
|
|
dropzone
|
|
.getFilesWithStatus(Dropzone.ADDED)
|
|
.should.eql([mock1, mock2, mock3, mock4]);
|
|
|
|
mock1.status = Dropzone.UPLOADING;
|
|
mock3.status = Dropzone.QUEUED;
|
|
mock4.status = Dropzone.QUEUED;
|
|
|
|
dropzone.getFilesWithStatus(Dropzone.ADDED).should.eql([mock2]);
|
|
dropzone.getFilesWithStatus(Dropzone.UPLOADING).should.eql([mock1]);
|
|
return dropzone
|
|
.getFilesWithStatus(Dropzone.QUEUED)
|
|
.should.eql([mock3, mock4]);
|
|
}));
|
|
});
|
|
|
|
describe("file handling", function () {
|
|
let mockFile = null;
|
|
let dropzone = null;
|
|
|
|
beforeEach(function () {
|
|
mockFile = getMockFile();
|
|
|
|
let element = Dropzone.createElement("<div></div>");
|
|
dropzone = new Dropzone(element, { url: "/the/url" });
|
|
});
|
|
|
|
afterEach(() => dropzone.destroy());
|
|
|
|
describe("addFile()", function () {
|
|
it("should properly set the status of the file", function () {
|
|
let doneFunction = null;
|
|
|
|
dropzone.accept = (file, done) => (doneFunction = done);
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
mockFile.status.should.eql(Dropzone.ADDED);
|
|
doneFunction();
|
|
mockFile.status.should.eql(Dropzone.QUEUED);
|
|
|
|
mockFile = getMockFile();
|
|
dropzone.addFile(mockFile);
|
|
|
|
mockFile.status.should.eql(Dropzone.ADDED);
|
|
doneFunction("error");
|
|
return mockFile.status.should.eql(Dropzone.ERROR);
|
|
});
|
|
|
|
it("should properly set the status of the file if autoProcessQueue is false and not call processQueue", function (done) {
|
|
let doneFunction = null;
|
|
dropzone.options.autoProcessQueue = false;
|
|
dropzone.accept = (file, done) => (doneFunction = done);
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
dropzone.addFile(mockFile);
|
|
sinon.stub(dropzone, "processQueue");
|
|
|
|
mockFile.status.should.eql(Dropzone.ADDED);
|
|
doneFunction();
|
|
mockFile.status.should.eql(Dropzone.QUEUED);
|
|
dropzone.processQueue.callCount.should.equal(0);
|
|
return setTimeout(function () {
|
|
dropzone.processQueue.callCount.should.equal(0);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should not add the file to the queue if autoQueue is false", function () {
|
|
let doneFunction = null;
|
|
dropzone.options.autoQueue = false;
|
|
dropzone.accept = (file, done) => (doneFunction = done);
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
mockFile.status.should.eql(Dropzone.ADDED);
|
|
doneFunction();
|
|
return mockFile.status.should.eql(Dropzone.ADDED);
|
|
});
|
|
|
|
it("should create a remove link if configured to do so", function () {
|
|
dropzone.options.addRemoveLinks = true;
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
sinon.stub(dropzone, "processQueue");
|
|
dropzone.addFile(mockFile);
|
|
|
|
return dropzone.files[0].previewElement.querySelector(
|
|
"a[data-dz-remove].dz-remove"
|
|
).should.be.ok;
|
|
});
|
|
|
|
it("should create a remove link with HTML if configured to do so", function () {
|
|
dropzone.options.addRemoveLinks = true;
|
|
dropzone.options.dictRemoveFile =
|
|
'<i class="icon icon-class"></i> Remove';
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
sinon.stub(dropzone, "processQueue");
|
|
dropzone.addFile(mockFile);
|
|
|
|
return (
|
|
dropzone.files[0].previewElement.querySelector(
|
|
"a[data-dz-remove].dz-remove"
|
|
).should.be.ok &&
|
|
dropzone.files[0].previewElement
|
|
.querySelector("a[data-dz-remove].dz-remove")
|
|
.innerHTML.should.equal('<i class="icon icon-class"></i> Remove')
|
|
);
|
|
});
|
|
|
|
it("should attach an event handler to data-dz-remove links", function () {
|
|
dropzone.options.previewTemplate = `\
|
|
<div class="dz-preview dz-file-preview">
|
|
<div class="dz-details">
|
|
<div class="dz-filename"><span data-dz-name></span></div>
|
|
<div class="dz-size" data-dz-size></div>
|
|
<img data-dz-thumbnail />
|
|
</div>
|
|
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
|
|
<div class="dz-success-mark"><span>✔</span></div>
|
|
<div class="dz-error-mark"><span>✘</span></div>
|
|
<div class="dz-error-message"><span data-dz-errormessage></span></div>
|
|
<a class="link1" data-dz-remove></a>
|
|
<a class="link2" data-dz-remove></a>
|
|
</div>\
|
|
`;
|
|
|
|
sinon.stub(dropzone, "processQueue");
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
let file = dropzone.files[0];
|
|
let removeLink1 = file.previewElement.querySelector(
|
|
"a[data-dz-remove].link1"
|
|
);
|
|
let removeLink2 = file.previewElement.querySelector(
|
|
"a[data-dz-remove].link2"
|
|
);
|
|
|
|
sinon.stub(dropzone, "removeFile");
|
|
|
|
let event = document.createEvent("HTMLEvents");
|
|
event.initEvent("click", true, true);
|
|
removeLink1.dispatchEvent(event);
|
|
|
|
dropzone.removeFile.callCount.should.eql(1);
|
|
|
|
event = document.createEvent("HTMLEvents");
|
|
event.initEvent("click", true, true);
|
|
removeLink2.dispatchEvent(event);
|
|
|
|
return dropzone.removeFile.callCount.should.eql(2);
|
|
});
|
|
|
|
return describe("thumbnails", function () {
|
|
it("should properly queue the thumbnail creation", function (done) {
|
|
let ct_callback;
|
|
let doneFunction;
|
|
|
|
dropzone.accept = (file, done) => (doneFunction = done);
|
|
dropzone.processFile = function () {};
|
|
dropzone.uploadFile = function () {};
|
|
|
|
let mock1 = getMockFile("image/jpg");
|
|
let mock2 = getMockFile("image/jpg");
|
|
let mock3 = getMockFile("image/jpg");
|
|
|
|
let ct_file;
|
|
dropzone.createThumbnail = function (
|
|
file,
|
|
thumbnailWidth,
|
|
thumbnailHeight,
|
|
resizeMethod,
|
|
fixOrientation,
|
|
callback
|
|
) {
|
|
ct_file = file;
|
|
ct_callback = callback;
|
|
};
|
|
|
|
sinon.spy(dropzone, "createThumbnail");
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
dropzone.addFile(mock3);
|
|
|
|
dropzone.files.length.should.eql(3);
|
|
return setTimeout(function () {
|
|
dropzone.createThumbnail.callCount.should.eql(1);
|
|
mock1.should.equal(ct_file);
|
|
ct_callback();
|
|
dropzone.createThumbnail.callCount.should.eql(2);
|
|
mock2.should.equal(ct_file);
|
|
ct_callback();
|
|
dropzone.createThumbnail.callCount.should.eql(3);
|
|
mock3.should.equal(ct_file);
|
|
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
return describe("when file is SVG", () =>
|
|
it("should use the SVG image itself", function (done) {
|
|
let createBlob = function (data, type) {
|
|
try {
|
|
return new Blob([data], { type });
|
|
} catch (e) {
|
|
let BlobBuilder =
|
|
window.BlobBuilder ||
|
|
window.WebKitBlobBuilder ||
|
|
window.MozBlobBuilder ||
|
|
window.MSBlobBuilder;
|
|
let builder = new BlobBuilder();
|
|
builder.append(data.buffer || data);
|
|
return builder.getBlob(type);
|
|
}
|
|
};
|
|
|
|
let blob = createBlob("foo", "image/svg+xml");
|
|
|
|
return dropzone.createThumbnail(
|
|
blob,
|
|
dropzone.options.thumbnailWidth,
|
|
dropzone.options.thumbnailHeight,
|
|
"crop",
|
|
false,
|
|
function (dataURI, canvas) {
|
|
let fileReader = new FileReader();
|
|
fileReader.onload = function () {
|
|
fileReader.result.should.equal(dataURI);
|
|
return done();
|
|
};
|
|
return fileReader.readAsDataURL(blob);
|
|
}
|
|
);
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("enqueueFile()", function () {
|
|
it("should be wrapped by enqueueFiles()", function () {
|
|
sinon.stub(dropzone, "enqueueFile");
|
|
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
let mock3 = getMockFile();
|
|
|
|
dropzone.enqueueFiles([mock1, mock2, mock3]);
|
|
|
|
dropzone.enqueueFile.callCount.should.equal(3);
|
|
dropzone.enqueueFile.args[0][0].should.equal(mock1);
|
|
dropzone.enqueueFile.args[1][0].should.equal(mock2);
|
|
return dropzone.enqueueFile.args[2][0].should.equal(mock3);
|
|
});
|
|
|
|
it("should fail if the file has already been processed", function () {
|
|
mockFile.status = Dropzone.ERROR;
|
|
expect(() => dropzone.enqueueFile(mockFile)).to.throw(
|
|
"This file can't be queued because it has already been processed or was rejected."
|
|
);
|
|
mockFile.status = Dropzone.COMPLETE;
|
|
expect(() => dropzone.enqueueFile(mockFile)).to.throw(
|
|
"This file can't be queued because it has already been processed or was rejected."
|
|
);
|
|
mockFile.status = Dropzone.UPLOADING;
|
|
return expect(() => dropzone.enqueueFile(mockFile)).to.throw(
|
|
"This file can't be queued because it has already been processed or was rejected."
|
|
);
|
|
});
|
|
|
|
it("should set the status to QUEUED and call processQueue asynchronously if everything's ok", function (done) {
|
|
mockFile.status = Dropzone.ADDED;
|
|
sinon.stub(dropzone, "processQueue");
|
|
dropzone.processQueue.callCount.should.equal(0);
|
|
dropzone.enqueueFile(mockFile);
|
|
mockFile.status.should.equal(Dropzone.QUEUED);
|
|
dropzone.processQueue.callCount.should.equal(0);
|
|
return setTimeout(function () {
|
|
dropzone.processQueue.callCount.should.equal(1);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
});
|
|
|
|
describe("uploadFiles()", function () {
|
|
let requests;
|
|
|
|
beforeEach(function () {
|
|
requests = [];
|
|
|
|
return (xhr.onCreate = (xhr) => requests.push(xhr));
|
|
});
|
|
|
|
afterEach(() => xhr.restore());
|
|
|
|
// Removed this test because multiple filenames can be transmitted now
|
|
// it "should properly urlencode the filename for the headers"
|
|
|
|
it("should be wrapped by uploadFile()", function () {
|
|
sinon.stub(dropzone, "uploadFiles");
|
|
|
|
dropzone.uploadFile(mockFile);
|
|
|
|
dropzone.uploadFiles.callCount.should.equal(1);
|
|
return dropzone.uploadFiles.calledWith([mockFile]).should.be.ok;
|
|
});
|
|
|
|
it("should use url options if strings", function (done) {
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
expect(requests.length).to.equal(1);
|
|
expect(requests[0].url).to.equal(dropzone.options.url);
|
|
expect(requests[0].method).to.equal(dropzone.options.method);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should call url options if functions", function (done) {
|
|
let method = "PUT";
|
|
let url = "/custom/upload/url";
|
|
|
|
dropzone.options.method = sinon.stub().returns(method);
|
|
dropzone.options.url = sinon.stub().returns(url);
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
dropzone.options.method.callCount.should.equal(1);
|
|
dropzone.options.url.callCount.should.equal(1);
|
|
sinon.assert.calledWith(dropzone.options.method, [mockFile]);
|
|
sinon.assert.calledWith(dropzone.options.url, [mockFile]);
|
|
expect(requests.length).to.equal(1);
|
|
expect(requests[0].url).to.equal(url);
|
|
expect(requests[0].method).to.equal(method);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should use the timeout option", function (done) {
|
|
dropzone.options.timeout = 10000;
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
expect(requests[0].timeout).to.equal(10000);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should properly handle if timeout is null", function (done) {
|
|
dropzone.options.timeout = null;
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
expect(requests[0].timeout).to.equal(0);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should ignore the onreadystate callback if readyState != 4", function (done) {
|
|
dropzone.addFile(mockFile);
|
|
return setTimeout(function () {
|
|
mockFile.status.should.eql(Dropzone.UPLOADING);
|
|
|
|
requests[0].status = 200;
|
|
requests[0].readyState = 3;
|
|
requests[0].responseHeaders = { "content-type": "text/plain" };
|
|
requests[0].onload();
|
|
|
|
mockFile.status.should.eql(Dropzone.UPLOADING);
|
|
|
|
requests[0].readyState = 4;
|
|
requests[0].onload();
|
|
|
|
mockFile.status.should.eql(Dropzone.SUCCESS);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should emit error and errormultiple when response was not OK", function (done) {
|
|
dropzone.options.uploadMultiple = true;
|
|
|
|
let error = false;
|
|
let errormultiple = false;
|
|
let complete = false;
|
|
let completemultiple = false;
|
|
dropzone.on("error", () => (error = true));
|
|
dropzone.on("errormultiple", () => (errormultiple = true));
|
|
dropzone.on("complete", () => (complete = true));
|
|
dropzone.on("completemultiple", () => (completemultiple = true));
|
|
|
|
dropzone.addFile(mockFile);
|
|
|
|
return setTimeout(function () {
|
|
mockFile.status.should.eql(Dropzone.UPLOADING);
|
|
|
|
requests[0].status = 400;
|
|
requests[0].readyState = 4;
|
|
requests[0].responseHeaders = { "content-type": "text/plain" };
|
|
requests[0].onload();
|
|
|
|
expect(
|
|
true === error &&
|
|
error === errormultiple &&
|
|
errormultiple === complete &&
|
|
complete === completemultiple
|
|
).to.be.ok;
|
|
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should include hidden files in the form and unchecked checkboxes and radiobuttons should be excluded", function (done) {
|
|
let element = Dropzone.createElement(`<form action="/the/url">
|
|
<input type="hidden" name="test" value="hidden" />
|
|
<input type="checkbox" name="unchecked" value="1" />
|
|
<input type="checkbox" name="checked" value="value1" checked="checked" />
|
|
<input type="radio" value="radiovalue1" name="radio1" />
|
|
<input type="radio" value="radiovalue2" name="radio1" checked="checked" />
|
|
<select name="select"><option value="1">1</option><option value="2" selected>2</option></select>
|
|
</form>`);
|
|
dropzone = new Dropzone(element, { url: "/the/url" });
|
|
|
|
let formData = null;
|
|
dropzone.on("sending", function (file, xhr, tformData) {
|
|
formData = tformData;
|
|
return sinon.spy(tformData, "append");
|
|
});
|
|
|
|
let mock1 = getMockFile();
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
formData.append.callCount.should.equal(5);
|
|
|
|
formData.append.args[0][0].should.eql("test");
|
|
formData.append.args[0][1].should.eql("hidden");
|
|
|
|
formData.append.args[1][0].should.eql("checked");
|
|
formData.append.args[1][1].should.eql("value1");
|
|
|
|
formData.append.args[2][0].should.eql("radio1");
|
|
formData.append.args[2][1].should.eql("radiovalue2");
|
|
|
|
formData.append.args[3][0].should.eql("select");
|
|
formData.append.args[3][1].should.eql("2");
|
|
|
|
formData.append.args[4][0].should.eql("file");
|
|
formData.append.args[4][1].should.equal(mock1);
|
|
|
|
// formData.append.args[1][0].should.eql "myName[]"
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should all values of a select that has the multiple attribute", function (done) {
|
|
let element = Dropzone.createElement(`<form action="/the/url">
|
|
<select name="select" multiple>
|
|
<option value="value1">1</option>
|
|
<option value="value2" selected>2</option>
|
|
<option value="value3">3</option>
|
|
<option value="value4" selected>4</option>
|
|
</select>
|
|
</form>`);
|
|
dropzone = new Dropzone(element, { url: "/the/url" });
|
|
|
|
let formData = null;
|
|
dropzone.on("sending", function (file, xhr, tformData) {
|
|
formData = tformData;
|
|
return sinon.spy(tformData, "append");
|
|
});
|
|
|
|
let mock1 = getMockFile();
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
formData.append.callCount.should.equal(3);
|
|
|
|
formData.append.args[0][0].should.eql("select");
|
|
formData.append.args[0][1].should.eql("value2");
|
|
|
|
formData.append.args[1][0].should.eql("select");
|
|
formData.append.args[1][1].should.eql("value4");
|
|
|
|
formData.append.args[2][0].should.eql("file");
|
|
formData.append.args[2][1].should.equal(mock1);
|
|
|
|
// formData.append.args[1][0].should.eql "myName[]"
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
describe("settings()", function () {
|
|
it("should correctly set `withCredentials` on the xhr object", function () {
|
|
dropzone.uploadFile(mockFile);
|
|
requests.length.should.eql(1);
|
|
requests[0].withCredentials.should.eql(false);
|
|
dropzone.options.withCredentials = true;
|
|
dropzone.uploadFile(mockFile);
|
|
requests.length.should.eql(2);
|
|
return requests[1].withCredentials.should.eql(true);
|
|
});
|
|
|
|
it("should correctly override headers on the xhr object", function () {
|
|
dropzone.options.headers = { "Foo-Header": "foobar" };
|
|
dropzone.uploadFile(mockFile);
|
|
return requests[0].requestHeaders["Foo-Header"].should.eql("foobar");
|
|
});
|
|
|
|
it("should not set headers on the xhr object that are empty", function () {
|
|
dropzone.options.headers = { "X-Requested-With": null };
|
|
dropzone.uploadFile(mockFile);
|
|
return Object.keys(requests[0].requestHeaders).should.not.contain(
|
|
"X-Requested-With"
|
|
);
|
|
});
|
|
|
|
it("should properly use the paramName without [n] as file upload if uploadMultiple is false", function (done) {
|
|
dropzone.options.uploadMultiple = false;
|
|
dropzone.options.paramName = "myName";
|
|
|
|
let formData = [];
|
|
let sendingCount = 0;
|
|
dropzone.on("sending", function (files, xhr, tformData) {
|
|
sendingCount++;
|
|
|
|
formData.push(tformData);
|
|
return sinon.spy(tformData, "append");
|
|
});
|
|
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
|
|
return setTimeout(function () {
|
|
sendingCount.should.equal(2);
|
|
|
|
formData.length.should.equal(2);
|
|
formData[0].append.callCount.should.equal(1);
|
|
formData[1].append.callCount.should.equal(1);
|
|
formData[0].append.args[0][0].should.eql("myName");
|
|
formData[0].append.args[0][0].should.eql("myName");
|
|
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should properly use the paramName with [n] as file upload if uploadMultiple is true", function (done) {
|
|
dropzone.options.uploadMultiple = true;
|
|
dropzone.options.paramName = "myName";
|
|
|
|
let formData = null;
|
|
let sendingMultipleCount = 0;
|
|
let sendingCount = 0;
|
|
dropzone.on("sending", (file, xhr, tformData) => sendingCount++);
|
|
dropzone.on("sendingmultiple", function (files, xhr, tformData) {
|
|
sendingMultipleCount++;
|
|
formData = tformData;
|
|
return sinon.spy(tformData, "append");
|
|
});
|
|
|
|
let mock1 = getMockFile();
|
|
let mock2 = getMockFile();
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
|
|
return setTimeout(function () {
|
|
sendingCount.should.equal(2);
|
|
sendingMultipleCount.should.equal(1);
|
|
dropzone.uploadFiles([mock1, mock2]);
|
|
formData.append.callCount.should.equal(2);
|
|
formData.append.args[0][0].should.eql("myName[0]");
|
|
formData.append.args[1][0].should.eql("myName[1]");
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should use resizeImage if dimensions are provided", function (done) {
|
|
sinon.stub(dropzone, "resizeImage");
|
|
sinon.stub(dropzone, "createThumbnail");
|
|
|
|
dropzone.options.resizeWidth = 400;
|
|
|
|
let mock1 = getMockFile("image/jpeg");
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
dropzone.resizeImage.callCount.should.eql(1);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should not use resizeImage for SVG if dimensions are provided", function (done) {
|
|
sinon.stub(dropzone, "uploadFiles");
|
|
|
|
dropzone.createThumbnail = function (
|
|
file,
|
|
width,
|
|
height,
|
|
resizeMethod,
|
|
fixOrientation,
|
|
callback
|
|
) {
|
|
callback(null, null);
|
|
};
|
|
|
|
dropzone.options.resizeWidth = 400;
|
|
|
|
let mock1 = getMockFile("image/svg+xml");
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
setTimeout(function () {
|
|
dropzone.uploadFiles.callCount.should.eql(1);
|
|
let uploadedFiles = dropzone.uploadFiles.getCall(0).args[0];
|
|
uploadedFiles.should.eql([mock1]);
|
|
done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should not use resizeImage if dimensions are not provided", function (done) {
|
|
sinon.stub(dropzone, "resizeImage");
|
|
sinon.stub(dropzone, "createThumbnail");
|
|
|
|
let mock1 = getMockFile("image/jpeg");
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
dropzone.resizeImage.callCount.should.eql(0);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
|
|
it("should not use resizeImage if file is not an image", function (done) {
|
|
sinon.stub(dropzone, "resizeImage");
|
|
sinon.stub(dropzone, "createThumbnail");
|
|
|
|
dropzone.options.resizeWidth = 400;
|
|
|
|
let mock1 = getMockFile("text/plain");
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
return setTimeout(function () {
|
|
dropzone.resizeImage.callCount.should.eql(0);
|
|
return done();
|
|
}, 10);
|
|
});
|
|
});
|
|
|
|
it("should not change the file name if the options.renameFile is not set", function (done) {
|
|
let mockFilename = "T3sT ;:_-.,!¨@&%&";
|
|
mockFile = getMockFile("text/html", mockFilename);
|
|
|
|
let renamedFilename = dropzone._renameFile(mockFile);
|
|
|
|
renamedFilename.should.equal(mockFilename);
|
|
return done();
|
|
});
|
|
|
|
it("should rename the file name if options.renamedFilename is set", function (done) {
|
|
dropzone.options.renameFile = (file) =>
|
|
file.name.toLowerCase().replace(/[^\w]/gi, "");
|
|
|
|
mockFile = getMockFile("text/html", "T3sT ;:_-.,!¨@&%&");
|
|
|
|
let renamedFilename = dropzone._renameFile(mockFile);
|
|
|
|
renamedFilename.should.equal("t3st_");
|
|
return done();
|
|
});
|
|
|
|
return describe("should properly set status of file", () =>
|
|
it("should correctly set `withCredentials` on the xhr object", function (done) {
|
|
dropzone.addFile(mockFile);
|
|
|
|
setTimeout(function () {
|
|
mockFile.status.should.eql(Dropzone.UPLOADING);
|
|
|
|
requests.length.should.equal(1);
|
|
requests[0].status = 400;
|
|
requests[0].readyState = 4;
|
|
requests[0].responseHeaders = { "content-type": "text/plain" };
|
|
|
|
requests[0].onload();
|
|
|
|
mockFile.status.should.eql(Dropzone.ERROR);
|
|
|
|
mockFile = getMockFile();
|
|
dropzone.addFile(mockFile);
|
|
|
|
setTimeout(function () {
|
|
mockFile.status.should.eql(Dropzone.UPLOADING);
|
|
|
|
requests.length.should.equal(2);
|
|
requests[1].status = 200;
|
|
requests[1].readyState = 4;
|
|
requests[1].responseHeaders = { "content-type": "text/plain" };
|
|
|
|
requests[1].onload();
|
|
|
|
mockFile.status.should.eql(Dropzone.SUCCESS);
|
|
return done();
|
|
}, 10);
|
|
}, 10);
|
|
}));
|
|
});
|
|
|
|
describe("transformFile()", function () {
|
|
it("should be invoked and the result should be uploaded if configured", (done) => {
|
|
sinon.stub(dropzone, "_uploadData");
|
|
|
|
let mock1 = getMockFile("text/html", "original-file");
|
|
let mock2 = getMockFile("text/html", "transformed-file");
|
|
|
|
dropzone.options.transformFile = (file, done) => {
|
|
file.should.eql(mock1);
|
|
done(mock2);
|
|
};
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
setTimeout(function () {
|
|
dropzone._uploadData.callCount.should.equal(1);
|
|
let uploadedFiles = dropzone._uploadData.args[0][0];
|
|
let uploadedDataBlocks = dropzone._uploadData.args[0][1];
|
|
uploadedFiles[0].should.equal(mock1);
|
|
uploadedDataBlocks[0].data.should.equal(mock2);
|
|
done();
|
|
}, 10);
|
|
});
|
|
it("should be used as a basis for chunked uploads", (done) => {
|
|
sinon.stub(dropzone, "_uploadData");
|
|
|
|
dropzone.options.chunking = true;
|
|
dropzone.options.chunkSize = 1;
|
|
dropzone.options.parallelChunkUploads = true;
|
|
|
|
let mock1 = getMockFile("text/html", "original-file", [
|
|
"Veeeeery long file",
|
|
]); // 18 bytes
|
|
let mock2 = getMockFile("text/html", "transformed-file", ["2b"]); // only 2 bytes
|
|
|
|
dropzone.options.transformFile = (file, done) => {
|
|
file.should.eql(mock1);
|
|
done(mock2);
|
|
};
|
|
|
|
dropzone.addFile(mock1);
|
|
|
|
setTimeout(async function () {
|
|
dropzone._uploadData.callCount.should.equal(2);
|
|
|
|
// the same file should be passed on each call.
|
|
dropzone._uploadData.args[0][0][0].should.eql(mock1);
|
|
dropzone._uploadData.args[1][0][0].should.eql(mock1);
|
|
|
|
// Since we only allow chunks of 1 byte, there should be 2 chunks,
|
|
// because the transformed file only has 2 bytes.
|
|
// If this would equal to 18 bytes, then the wrong file would have
|
|
// been chunked.
|
|
mock1.upload.totalChunkCount.should.eql(2);
|
|
|
|
let uploadedDataBlocks1 = dropzone._uploadData.args[0][1][0];
|
|
let uploadedDataBlocks2 = dropzone._uploadData.args[1][1][0];
|
|
|
|
let block1Text = await uploadedDataBlocks1.data.text();
|
|
let block2Text = await uploadedDataBlocks2.data.text();
|
|
block1Text.should.equal("2");
|
|
block2Text.should.equal("b");
|
|
done();
|
|
}, 10);
|
|
});
|
|
});
|
|
|
|
return describe("complete file", () =>
|
|
it("should properly emit the queuecomplete event when the complete queue is finished", function (done) {
|
|
let mock1 = getMockFile("text/html", "mock1");
|
|
let mock2 = getMockFile("text/html", "mock2");
|
|
let mock3 = getMockFile("text/html", "mock3");
|
|
mock1.status = Dropzone.ADDED;
|
|
mock2.status = Dropzone.ADDED;
|
|
mock3.status = Dropzone.ADDED;
|
|
|
|
dropzone.uploadFiles = function (files) {
|
|
return setTimeout(() => {
|
|
return this._finished(files, null, null);
|
|
}, 1);
|
|
};
|
|
|
|
let completedFiles = 0;
|
|
dropzone.on("complete", (file) => completedFiles++);
|
|
|
|
dropzone.on("queuecomplete", function () {
|
|
completedFiles.should.equal(3);
|
|
return done();
|
|
});
|
|
|
|
dropzone.addFile(mock1);
|
|
dropzone.addFile(mock2);
|
|
return dropzone.addFile(mock3);
|
|
}));
|
|
});
|
|
});
|