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(
'
Hallo
'
);
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("");
return element.tagName.should.equal("DIV");
});
});
describe("Dropzone.elementInside()", function () {
let element = Dropzone.createElement(
''
);
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(''
);
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(''));
tmpElements.push(
Dropzone.createElement('')
);
tmpElements.push(
Dropzone.createElement('')
);
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(
''
);
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(''),
{ clickable: true, acceptedFiles: "audio/*,video/*" }
),
"using acceptedMimeTypes": new Dropzone(
Dropzone.createElement(''),
{ clickable: true, acceptedMimeTypes: "audio/*,video/*" }
),
};
it("should not add an accept attribute if no acceptParameter", function () {
let dropzone = new Dropzone(
Dropzone.createElement(''),
{ 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(
''
);
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(
''
);
let msg = Dropzone.createElement('TEST
');
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("");
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("2.1 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("");
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("0 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("2 MB");
dropzone
.filesize(2 * 1024 * 1024)
.should.eql("2.1 MB");
dropzone
.filesize(2 * 1000 * 1000 * 1000)
.should.eql("2 GB");
dropzone
.filesize(2 * 1024 * 1024 * 1024)
.should.eql("2.1 GB");
dropzone
.filesize(2.5111 * 1000 * 1000 * 1000)
.should.eql("2.5 GB");
dropzone.filesize(1.1 * 1000).should.eql("1.1 KB");
return dropzone
.filesize(999 * 1000)
.should.eql("1 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("2 MB");
return dropzone
.filesize(2 * 1000 * 1000)
.should.eql("1.9 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(``);
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("");
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('')
);
element.appendChild(
Dropzone.createElement('')
);
return expect(dropzone.getExistingFallback()).to.equal(undefined);
});
it("should return divs as fallback", function () {
let fallback = Dropzone.createElement(
''
);
element.appendChild(fallback);
return fallback.should.equal(dropzone.getExistingFallback());
});
it("should return forms as fallback", function () {
let fallback = Dropzone.createElement(
''
);
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("");
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 =
' 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(' Remove')
);
});
it("should attach an event handler to data-dz-remove links", function () {
dropzone.options.previewTemplate = `\
\
`;
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(``);
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(``);
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);
}));
});
});