test.js 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461
  1. import Dropzone from "../src/dropzone.js";
  2. describe("Dropzone", function () {
  3. let getMockFile = (
  4. type = "text/html",
  5. filename = "test file name",
  6. contents = ["file contents"]
  7. ) => {
  8. let file = new File(contents, filename, { type: type });
  9. file.status = Dropzone.ADDED;
  10. file.accepted = true;
  11. file.upload = {
  12. filename: filename,
  13. };
  14. return file;
  15. };
  16. let xhr = null;
  17. beforeEach(() => (xhr = sinon.useFakeXMLHttpRequest()));
  18. describe("Emitter", function () {
  19. let emitter = null;
  20. beforeEach(() => (emitter = new Dropzone.prototype.Emitter()));
  21. it(".on() should return the object itself", () =>
  22. emitter.on("test", function () {}).should.equal(emitter));
  23. it(".on() should properly register listeners", function () {
  24. (emitter._callbacks === undefined).should.be.true;
  25. let callback = function () {};
  26. let callback2 = function () {};
  27. emitter.on("test", callback);
  28. emitter.on("test", callback2);
  29. emitter.on("test2", callback);
  30. emitter._callbacks.test.length.should.equal(2);
  31. emitter._callbacks.test[0].should.equal(callback);
  32. emitter._callbacks.test[1].should.equal(callback2);
  33. emitter._callbacks.test2.length.should.equal(1);
  34. return emitter._callbacks.test2[0].should.equal(callback);
  35. });
  36. it(".emit() should return the object itself", () =>
  37. emitter.emit("test").should.equal(emitter));
  38. it(".emit() should properly invoke all registered callbacks with arguments", function () {
  39. let callCount1 = 0;
  40. let callCount12 = 0;
  41. let callCount2 = 0;
  42. let callback1 = function (var1, var2) {
  43. callCount1++;
  44. var1.should.equal("callback1 var1");
  45. return var2.should.equal("callback1 var2");
  46. };
  47. let callback12 = function (var1, var2) {
  48. callCount12++;
  49. var1.should.equal("callback1 var1");
  50. return var2.should.equal("callback1 var2");
  51. };
  52. let callback2 = function (var1, var2) {
  53. callCount2++;
  54. var1.should.equal("callback2 var1");
  55. return var2.should.equal("callback2 var2");
  56. };
  57. emitter.on("test1", callback1);
  58. emitter.on("test1", callback12);
  59. emitter.on("test2", callback2);
  60. callCount1.should.equal(0);
  61. callCount12.should.equal(0);
  62. callCount2.should.equal(0);
  63. emitter.emit("test1", "callback1 var1", "callback1 var2");
  64. callCount1.should.equal(1);
  65. callCount12.should.equal(1);
  66. callCount2.should.equal(0);
  67. emitter.emit("test2", "callback2 var1", "callback2 var2");
  68. callCount1.should.equal(1);
  69. callCount12.should.equal(1);
  70. callCount2.should.equal(1);
  71. emitter.emit("test1", "callback1 var1", "callback1 var2");
  72. callCount1.should.equal(2);
  73. callCount12.should.equal(2);
  74. return callCount2.should.equal(1);
  75. });
  76. return describe(".off()", function () {
  77. let callback1 = function () {};
  78. let callback2 = function () {};
  79. let callback3 = function () {};
  80. let callback4 = function () {};
  81. beforeEach(
  82. () =>
  83. (emitter._callbacks = {
  84. test1: [callback1, callback2],
  85. test2: [callback3],
  86. test3: [callback1, callback4],
  87. test4: [],
  88. })
  89. );
  90. it("should work without any listeners", function () {
  91. emitter._callbacks = undefined;
  92. let emt = emitter.off();
  93. emitter._callbacks.should.eql({});
  94. return emt.should.equal(emitter);
  95. });
  96. it("should properly remove all event listeners", function () {
  97. let emt = emitter.off();
  98. emitter._callbacks.should.eql({});
  99. return emt.should.equal(emitter);
  100. });
  101. it("should properly remove all event listeners for specific event", function () {
  102. emitter.off("test1");
  103. (emitter._callbacks["test1"] === undefined).should.be.true;
  104. emitter._callbacks["test2"].length.should.equal(1);
  105. emitter._callbacks["test3"].length.should.equal(2);
  106. let emt = emitter.off("test2");
  107. (emitter._callbacks["test2"] === undefined).should.be.true;
  108. return emt.should.equal(emitter);
  109. });
  110. it("should properly remove specific event listener", function () {
  111. emitter.off("test1", callback1);
  112. emitter._callbacks["test1"].length.should.equal(1);
  113. emitter._callbacks["test1"][0].should.equal(callback2);
  114. emitter._callbacks["test3"].length.should.equal(2);
  115. let emt = emitter.off("test3", callback4);
  116. emitter._callbacks["test3"].length.should.equal(1);
  117. emitter._callbacks["test3"][0].should.equal(callback1);
  118. return emt.should.equal(emitter);
  119. });
  120. });
  121. });
  122. describe("static functions", function () {
  123. describe("Dropzone.isBrowserSupported()", function () {
  124. let initialValue;
  125. beforeEach(() => {
  126. initialValue = Dropzone.blockedBrowsers;
  127. });
  128. afterEach(() => {
  129. Dropzone.blockedBrowsers = initialValue;
  130. Dropzone.blacklistedBrowsers = undefined;
  131. });
  132. it("should use blockedBrowsers usually", () => {
  133. let initialValue = Dropzone.blockedBrowsers;
  134. Dropzone.isBrowserSupported().should.be.true;
  135. initialValue.should.equal(Dropzone.blockedBrowsers);
  136. Dropzone.blockedBrowsers = [/HeadlessChrome/];
  137. Dropzone.isBrowserSupported().should.be.false;
  138. });
  139. it("should user blacklistedBrowsers if its set", () => {
  140. let initialValue = Dropzone.blockedBrowsers;
  141. Dropzone.isBrowserSupported().should.be.true;
  142. Dropzone.blacklistedBrowsers = [/HeadlessChrome/];
  143. Dropzone.isBrowserSupported().should.be.false;
  144. initialValue.should.not.equal(Dropzone.blockedBrowsers);
  145. Dropzone.blockedBrowsers.should.equal(Dropzone.blacklistedBrowsers);
  146. });
  147. });
  148. describe("Dropzone.createElement()", function () {
  149. let element = Dropzone.createElement(
  150. '<div class="test"><span>Hallo</span></div>'
  151. );
  152. it("should properly create an element from a string", () =>
  153. element.tagName.should.equal("DIV"));
  154. it("should properly add the correct class", () =>
  155. element.classList.contains("test").should.be.ok);
  156. it("should properly create child elements", () =>
  157. element.querySelector("span").tagName.should.equal("SPAN"));
  158. it("should always return only one element", function () {
  159. element = Dropzone.createElement("<div></div><span></span>");
  160. return element.tagName.should.equal("DIV");
  161. });
  162. });
  163. describe("Dropzone.elementInside()", function () {
  164. let element = Dropzone.createElement(
  165. '<div id="test"><div class="child1"><div class="child2"></div></div></div>'
  166. );
  167. document.body.appendChild(element);
  168. let child1 = element.querySelector(".child1");
  169. let child2 = element.querySelector(".child2");
  170. after(() => document.body.removeChild(element));
  171. it("should return yes if elements are the same", () =>
  172. Dropzone.elementInside(element, element).should.be.ok);
  173. it("should return yes if element is direct child", () =>
  174. Dropzone.elementInside(child1, element).should.be.ok);
  175. it("should return yes if element is some child", function () {
  176. Dropzone.elementInside(child2, element).should.be.ok;
  177. return Dropzone.elementInside(child2, document.body).should.be.ok;
  178. });
  179. it("should return no unless element is some child", function () {
  180. Dropzone.elementInside(element, child1).should.not.be.ok;
  181. return Dropzone.elementInside(document.body, child1).should.not.be.ok;
  182. });
  183. });
  184. describe("Dropzone.optionsForElement()", function () {
  185. let testOptions = {
  186. url: "/some/url",
  187. method: "put",
  188. };
  189. before(() => (Dropzone.options.testElement = testOptions));
  190. after(() => delete Dropzone.options.testElement);
  191. let element = document.createElement("div");
  192. it("should take options set in Dropzone.options from camelized id", function () {
  193. element.id = "test-element";
  194. return Dropzone.optionsForElement(element).should.equal(testOptions);
  195. });
  196. it("should return undefined if no options set", function () {
  197. element.id = "test-element2";
  198. return expect(Dropzone.optionsForElement(element)).to.equal(undefined);
  199. });
  200. it("should return undefined and not throw if it's a form with an input element of the name 'id'", function () {
  201. element = Dropzone.createElement('<form><input name="id" /</form>');
  202. return expect(Dropzone.optionsForElement(element)).to.equal(undefined);
  203. });
  204. it("should ignore input fields with the name='id'", function () {
  205. element = Dropzone.createElement(
  206. '<form id="test-element"><input type="hidden" name="id" value="fooo" /></form>'
  207. );
  208. return Dropzone.optionsForElement(element).should.equal(testOptions);
  209. });
  210. });
  211. describe("Dropzone.forElement()", function () {
  212. let element = document.createElement("div");
  213. element.id = "some-test-element";
  214. let dropzone = null;
  215. before(function () {
  216. document.body.appendChild(element);
  217. return (dropzone = new Dropzone(element, { url: "/test" }));
  218. });
  219. after(function () {
  220. dropzone.disable();
  221. return document.body.removeChild(element);
  222. });
  223. it("should throw an exception if no dropzone attached", () =>
  224. expect(() =>
  225. Dropzone.forElement(document.createElement("div"))
  226. ).to.throw(
  227. "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."
  228. ));
  229. it("should accept css selectors", () =>
  230. expect(Dropzone.forElement("#some-test-element")).to.equal(dropzone));
  231. it("should accept native elements", () =>
  232. expect(Dropzone.forElement(element)).to.equal(dropzone));
  233. });
  234. describe("Dropzone.discover()", function () {
  235. let element1 = document.createElement("div");
  236. element1.className = "dropzone";
  237. let element2 = element1.cloneNode();
  238. let element3 = element1.cloneNode();
  239. element1.id = "test-element-1";
  240. element2.id = "test-element-2";
  241. element3.id = "test-element-3";
  242. describe("specific options", function () {
  243. before(function () {
  244. Dropzone.options.testElement1 = { url: "test-url" };
  245. Dropzone.options.testElement2 = false; // Disabled
  246. document.body.appendChild(element1);
  247. document.body.appendChild(element2);
  248. return Dropzone.discover();
  249. });
  250. after(function () {
  251. document.body.removeChild(element1);
  252. return document.body.removeChild(element2);
  253. });
  254. it("should find elements with a .dropzone class", () =>
  255. element1.dropzone.should.be.ok);
  256. it("should not create dropzones with disabled options", () =>
  257. expect(element2.dropzone).to.not.be.ok);
  258. });
  259. return describe("Dropzone.autoDiscover", function () {
  260. before(function () {
  261. Dropzone.options.testElement3 = { url: "test-url" };
  262. return document.body.appendChild(element3);
  263. });
  264. after(() => document.body.removeChild(element3));
  265. it("should create dropzones even if Dropzone.autoDiscover == false", function () {
  266. // Because the check is in the actual contentLoaded function.
  267. Dropzone.autoDiscover = false;
  268. Dropzone.discover();
  269. return expect(element3.dropzone).to.be.ok;
  270. });
  271. it("should not automatically be called if Dropzone.autoDiscover == false", function () {
  272. Dropzone.autoDiscover = false;
  273. Dropzone.discover = () => expect(false).to.be.ok;
  274. return Dropzone._autoDiscoverFunction();
  275. });
  276. });
  277. });
  278. describe("Dropzone.isValidFile()", function () {
  279. it("should return true if called without acceptedFiles", () =>
  280. Dropzone.isValidFile({ type: "some/type" }, null).should.be.ok);
  281. it("should properly validate if called with concrete mime types", function () {
  282. let acceptedMimeTypes = "text/html,image/jpeg,application/json";
  283. Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
  284. .ok;
  285. Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
  286. .be.ok;
  287. Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
  288. .should.be.ok;
  289. return Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes)
  290. .should.not.be.ok;
  291. });
  292. it("should properly validate if called with base mime types", function () {
  293. let acceptedMimeTypes = "text/*,image/*,application/*";
  294. Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
  295. .ok;
  296. Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
  297. .be.ok;
  298. Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
  299. .should.be.ok;
  300. Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes).should.be
  301. .ok;
  302. return Dropzone.isValidFile({ type: "some/type" }, acceptedMimeTypes)
  303. .should.not.be.ok;
  304. });
  305. it("should properly validate if called with mixed mime types", function () {
  306. let acceptedMimeTypes = "text/*,image/jpeg,application/*";
  307. Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
  308. .ok;
  309. Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes).should
  310. .be.ok;
  311. Dropzone.isValidFile({ type: "image/bmp" }, acceptedMimeTypes).should
  312. .not.be.ok;
  313. Dropzone.isValidFile({ type: "application/json" }, acceptedMimeTypes)
  314. .should.be.ok;
  315. return Dropzone.isValidFile({ type: "some/type" }, acceptedMimeTypes)
  316. .should.not.be.ok;
  317. });
  318. it("should properly validate even with spaces in between", function () {
  319. let acceptedMimeTypes = "text/html , image/jpeg, application/json";
  320. Dropzone.isValidFile({ type: "text/html" }, acceptedMimeTypes).should.be
  321. .ok;
  322. return Dropzone.isValidFile({ type: "image/jpeg" }, acceptedMimeTypes)
  323. .should.be.ok;
  324. });
  325. it("should properly validate extensions", function () {
  326. let acceptedMimeTypes = "text/html , image/jpeg, .pdf ,.png";
  327. Dropzone.isValidFile(
  328. { name: "somxsfsd", type: "text/html" },
  329. acceptedMimeTypes
  330. ).should.be.ok;
  331. Dropzone.isValidFile(
  332. { name: "somesdfsdf", type: "image/jpeg" },
  333. acceptedMimeTypes
  334. ).should.be.ok;
  335. Dropzone.isValidFile(
  336. { name: "somesdfadfadf", type: "application/json" },
  337. acceptedMimeTypes
  338. ).should.not.be.ok;
  339. Dropzone.isValidFile(
  340. { name: "some-file file.pdf", type: "random/type" },
  341. acceptedMimeTypes
  342. ).should.be.ok;
  343. // .pdf has to be in the end
  344. Dropzone.isValidFile(
  345. { name: "some-file.pdf file.gif", type: "random/type" },
  346. acceptedMimeTypes
  347. ).should.not.be.ok;
  348. return Dropzone.isValidFile(
  349. { name: "some-file file.png", type: "random/type" },
  350. acceptedMimeTypes
  351. ).should.be.ok;
  352. });
  353. });
  354. return describe("Dropzone.confirm", function () {
  355. beforeEach(() => sinon.stub(window, "confirm"));
  356. afterEach(() => window.confirm.restore());
  357. it("should forward to window.confirm and call the callbacks accordingly", function () {
  358. let rejected;
  359. let accepted = (rejected = false);
  360. window.confirm.returns(true);
  361. Dropzone.confirm(
  362. "test question",
  363. () => (accepted = true),
  364. () => (rejected = true)
  365. );
  366. window.confirm.args[0][0].should.equal("test question");
  367. accepted.should.equal(true);
  368. rejected.should.equal(false);
  369. accepted = rejected = false;
  370. window.confirm.returns(false);
  371. Dropzone.confirm(
  372. "test question 2",
  373. () => (accepted = true),
  374. () => (rejected = true)
  375. );
  376. window.confirm.args[1][0].should.equal("test question 2");
  377. accepted.should.equal(false);
  378. return rejected.should.equal(true);
  379. });
  380. it("should not error if rejected is not provided", function () {
  381. let rejected;
  382. let accepted = (rejected = false);
  383. window.confirm.returns(false);
  384. Dropzone.confirm("test question", () => (accepted = true));
  385. window.confirm.args[0][0].should.equal("test question");
  386. // Nothing should have changed since there is no rejected function.
  387. accepted.should.equal(false);
  388. return rejected.should.equal(false);
  389. });
  390. });
  391. });
  392. describe("Dropzone.getElement() / getElements()", function () {
  393. let tmpElements = [];
  394. beforeEach(function () {
  395. tmpElements = [];
  396. tmpElements.push(Dropzone.createElement('<div class="tmptest"></div>'));
  397. tmpElements.push(
  398. Dropzone.createElement('<div id="tmptest1" class="random"></div>')
  399. );
  400. tmpElements.push(
  401. Dropzone.createElement('<div class="random div"></div>')
  402. );
  403. return tmpElements.forEach((el) => document.body.appendChild(el));
  404. });
  405. afterEach(() => tmpElements.forEach((el) => document.body.removeChild(el)));
  406. describe(".getElement()", function () {
  407. it("should accept a string", function () {
  408. let el = Dropzone.getElement(".tmptest");
  409. el.should.equal(tmpElements[0]);
  410. el = Dropzone.getElement("#tmptest1");
  411. return el.should.equal(tmpElements[1]);
  412. });
  413. it("should accept a node", function () {
  414. let el = Dropzone.getElement(tmpElements[2]);
  415. return el.should.equal(tmpElements[2]);
  416. });
  417. it("should fail if invalid selector", function () {
  418. let errorMessage =
  419. "Invalid `clickable` option provided. Please provide a CSS selector or a plain HTML element.";
  420. expect(() => Dropzone.getElement("lblasdlfsfl", "clickable")).to.throw(
  421. errorMessage
  422. );
  423. expect(() =>
  424. Dropzone.getElement({ lblasdlfsfl: "lblasdlfsfl" }, "clickable")
  425. ).to.throw(errorMessage);
  426. return expect(() =>
  427. Dropzone.getElement(["lblasdlfsfl"], "clickable")
  428. ).to.throw(errorMessage);
  429. });
  430. });
  431. return describe(".getElements()", function () {
  432. it("should accept a list of strings", function () {
  433. let els = Dropzone.getElements([".tmptest", "#tmptest1"]);
  434. return els.should.eql([tmpElements[0], tmpElements[1]]);
  435. });
  436. it("should accept a list of nodes", function () {
  437. let els = Dropzone.getElements([tmpElements[0], tmpElements[2]]);
  438. return els.should.eql([tmpElements[0], tmpElements[2]]);
  439. });
  440. it("should accept a mixed list", function () {
  441. let els = Dropzone.getElements(["#tmptest1", tmpElements[2]]);
  442. return els.should.eql([tmpElements[1], tmpElements[2]]);
  443. });
  444. it("should accept a string selector", function () {
  445. let els = Dropzone.getElements(".random");
  446. return els.should.eql([tmpElements[1], tmpElements[2]]);
  447. });
  448. it("should accept a single node", function () {
  449. let els = Dropzone.getElements(tmpElements[1]);
  450. return els.should.eql([tmpElements[1]]);
  451. });
  452. it("should fail if invalid selector", function () {
  453. let errorMessage =
  454. "Invalid `clickable` option provided. Please provide a CSS selector, a plain HTML element or a list of those.";
  455. expect(() => Dropzone.getElements("lblasdlfsfl", "clickable")).to.throw(
  456. errorMessage
  457. );
  458. return expect(() =>
  459. Dropzone.getElements(["lblasdlfsfl"], "clickable")
  460. ).to.throw(errorMessage);
  461. });
  462. });
  463. });
  464. describe("constructor()", function () {
  465. let dropzone = null;
  466. afterEach(function () {
  467. if (dropzone != null) {
  468. return dropzone.destroy();
  469. }
  470. });
  471. it("should throw an exception if the element is invalid", () =>
  472. expect(() => (dropzone = new Dropzone("#invalid-element"))).to.throw(
  473. "Invalid dropzone element."
  474. ));
  475. it("should throw an exception if assigned twice to the same element", function () {
  476. let element = document.createElement("div");
  477. dropzone = new Dropzone(element, { url: "url" });
  478. return expect(() => new Dropzone(element, { url: "url" })).to.throw(
  479. "Dropzone already attached."
  480. );
  481. });
  482. it("should throw an exception if both acceptedFiles and acceptedMimeTypes are specified", function () {
  483. let element = document.createElement("div");
  484. return expect(
  485. () =>
  486. (dropzone = new Dropzone(element, {
  487. url: "test",
  488. acceptedFiles: "param",
  489. acceptedMimeTypes: "types",
  490. }))
  491. ).to.throw(
  492. "You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."
  493. );
  494. });
  495. it("should set itself as element.dropzone", function () {
  496. let element = document.createElement("div");
  497. dropzone = new Dropzone(element, { url: "url" });
  498. return element.dropzone.should.equal(dropzone);
  499. });
  500. it("should add itself to Dropzone.instances", function () {
  501. let element = document.createElement("div");
  502. dropzone = new Dropzone(element, { url: "url" });
  503. return Dropzone.instances[Dropzone.instances.length - 1].should.equal(
  504. dropzone
  505. );
  506. });
  507. it("should use the action attribute not the element with the name action", function () {
  508. let element = Dropzone.createElement(
  509. '<form action="real-action"><input type="hidden" name="action" value="wrong-action" /></form>'
  510. );
  511. dropzone = new Dropzone(element);
  512. return dropzone.options.url.should.equal("real-action");
  513. });
  514. return describe("options", function () {
  515. let element = null;
  516. let element2 = null;
  517. beforeEach(function () {
  518. element = document.createElement("div");
  519. element.id = "test-element";
  520. element2 = document.createElement("div");
  521. element2.id = "test-element2";
  522. return (Dropzone.options.testElement = {
  523. url: "/some/url",
  524. parallelUploads: 10,
  525. });
  526. });
  527. afterEach(() => delete Dropzone.options.testElement);
  528. it("should take the options set in Dropzone.options", function () {
  529. dropzone = new Dropzone(element);
  530. dropzone.options.url.should.equal("/some/url");
  531. return dropzone.options.parallelUploads.should.equal(10);
  532. });
  533. it("should prefer passed options over Dropzone.options", function () {
  534. dropzone = new Dropzone(element, { url: "/some/other/url" });
  535. return dropzone.options.url.should.equal("/some/other/url");
  536. });
  537. it("should take the default options if nothing set in Dropzone.options", function () {
  538. dropzone = new Dropzone(element2, { url: "/some/url" });
  539. return dropzone.options.parallelUploads.should.equal(2);
  540. });
  541. it("should call the fallback function if forceFallback == true", (done) =>
  542. (dropzone = new Dropzone(element, {
  543. url: "/some/other/url",
  544. forceFallback: true,
  545. fallback() {
  546. return done();
  547. },
  548. })));
  549. it("should set acceptedFiles if deprecated acceptedMimetypes option has been passed", function () {
  550. dropzone = new Dropzone(element, {
  551. url: "/some/other/url",
  552. acceptedMimeTypes: "my/type",
  553. });
  554. return dropzone.options.acceptedFiles.should.equal("my/type");
  555. });
  556. return describe("options.clickable", function () {
  557. let clickableElement = null;
  558. dropzone = null;
  559. beforeEach(function () {
  560. clickableElement = document.createElement("div");
  561. clickableElement.className = "some-clickable";
  562. return document.body.appendChild(clickableElement);
  563. });
  564. afterEach(function () {
  565. document.body.removeChild(clickableElement);
  566. if (dropzone != null) {
  567. return dropzone.destroy;
  568. }
  569. });
  570. it("should use the default element if clickable == true", function () {
  571. dropzone = new Dropzone(element, { clickable: true });
  572. return dropzone.clickableElements.should.eql([dropzone.element]);
  573. });
  574. it("should lookup the element if clickable is a CSS selector", function () {
  575. dropzone = new Dropzone(element, { clickable: ".some-clickable" });
  576. return dropzone.clickableElements.should.eql([clickableElement]);
  577. });
  578. it("should simply use the provided element", function () {
  579. dropzone = new Dropzone(element, { clickable: clickableElement });
  580. return dropzone.clickableElements.should.eql([clickableElement]);
  581. });
  582. it("should accept multiple clickable elements", function () {
  583. dropzone = new Dropzone(element, {
  584. clickable: [document.body, ".some-clickable"],
  585. });
  586. return dropzone.clickableElements.should.eql([
  587. document.body,
  588. clickableElement,
  589. ]);
  590. });
  591. it("should throw an exception if the element is invalid", () =>
  592. expect(
  593. () =>
  594. (dropzone = new Dropzone(element, {
  595. clickable: ".some-invalid-clickable",
  596. }))
  597. ).to.throw(
  598. "Invalid `clickable` option provided. Please provide a CSS selector, a plain HTML element or a list of those."
  599. ));
  600. });
  601. });
  602. });
  603. describe("init()", function () {
  604. describe("clickable", function () {
  605. let dropzones = {
  606. "using acceptedFiles": new Dropzone(
  607. Dropzone.createElement('<form action="/"></form>'),
  608. { clickable: true, acceptedFiles: "audio/*,video/*" }
  609. ),
  610. "using acceptedMimeTypes": new Dropzone(
  611. Dropzone.createElement('<form action="/"></form>'),
  612. { clickable: true, acceptedMimeTypes: "audio/*,video/*" }
  613. ),
  614. };
  615. it("should not add an accept attribute if no acceptParameter", function () {
  616. let dropzone = new Dropzone(
  617. Dropzone.createElement('<form action="/"></form>'),
  618. { clickable: true, acceptParameter: null, acceptedMimeTypes: null }
  619. );
  620. return dropzone.hiddenFileInput.hasAttribute("accept").should.be.false;
  621. });
  622. return (() => {
  623. let result = [];
  624. for (let name in dropzones) {
  625. var dropzone = dropzones[name];
  626. result.push(
  627. describe(name, () =>
  628. (function (dropzone) {
  629. it("should create a hidden file input if clickable", function () {
  630. dropzone.hiddenFileInput.should.be.ok;
  631. dropzone.hiddenFileInput.tagName.should.equal("INPUT");
  632. });
  633. it("should have a tabindex of -1", function () {
  634. dropzone.hiddenFileInput.tabIndex.should.equal(-1);
  635. });
  636. it("should use the acceptParameter", () =>
  637. dropzone.hiddenFileInput
  638. .getAttribute("accept")
  639. .should.equal("audio/*,video/*"));
  640. it("should create a new input element when something is selected to reset the input field", () =>
  641. (() => {
  642. let result1 = [];
  643. for (let i = 0; i <= 3; i++) {
  644. let { hiddenFileInput } = dropzone;
  645. let event = document.createEvent("HTMLEvents");
  646. event.initEvent("change", true, true);
  647. hiddenFileInput.dispatchEvent(event);
  648. dropzone.hiddenFileInput.should.not.equal(
  649. hiddenFileInput
  650. );
  651. result1.push(
  652. Dropzone.elementInside(hiddenFileInput, document).should
  653. .not.be.ok
  654. );
  655. }
  656. return result1;
  657. })());
  658. })(dropzone)
  659. )
  660. );
  661. }
  662. return result;
  663. })();
  664. });
  665. it("should create a .dz-message element", function () {
  666. let element = Dropzone.createElement(
  667. '<form class="dropzone" action="/"></form>'
  668. );
  669. let dropzone = new Dropzone(element, {
  670. clickable: true,
  671. acceptParameter: null,
  672. acceptedMimeTypes: null,
  673. });
  674. return element.querySelector(".dz-message").should.be.instanceof(Element);
  675. });
  676. it("should not create a .dz-message element if there already is one", function () {
  677. let element = Dropzone.createElement(
  678. '<form class="dropzone" action="/"></form>'
  679. );
  680. let msg = Dropzone.createElement('<div class="dz-message">TEST</div>');
  681. element.appendChild(msg);
  682. let dropzone = new Dropzone(element, {
  683. clickable: true,
  684. acceptParameter: null,
  685. acceptedMimeTypes: null,
  686. });
  687. element.querySelector(".dz-message").should.equal(msg);
  688. return element.querySelectorAll(".dz-message").length.should.equal(1);
  689. });
  690. });
  691. describe("options", function () {
  692. let element = null;
  693. let dropzone = null;
  694. beforeEach(function () {
  695. element = Dropzone.createElement("<div></div>");
  696. return (dropzone = new Dropzone(element, {
  697. maxFilesize: 4,
  698. url: "url",
  699. acceptedMimeTypes: "audio/*,image/png",
  700. maxFiles: 3,
  701. }));
  702. });
  703. return describe("file specific", function () {
  704. let file = null;
  705. beforeEach(function () {
  706. file = {
  707. name: "test name",
  708. size: 2 * 1024 * 1024,
  709. width: 200,
  710. height: 100,
  711. upload: {
  712. filename: "test name",
  713. },
  714. };
  715. return dropzone.options.addedfile.call(dropzone, file);
  716. });
  717. describe(".addedFile()", () =>
  718. it("should properly create the previewElement", function () {
  719. file.previewElement.should.be.instanceof(Element);
  720. file.previewElement
  721. .querySelector("[data-dz-name]")
  722. .innerHTML.should.eql("test name");
  723. return file.previewElement
  724. .querySelector("[data-dz-size]")
  725. .innerHTML.should.eql("<strong>2.1</strong> MB");
  726. }));
  727. describe(".error()", function () {
  728. it("should properly insert the error", function () {
  729. dropzone.options.error.call(dropzone, file, "test message");
  730. return file.previewElement
  731. .querySelector("[data-dz-errormessage]")
  732. .innerHTML.should.eql("test message");
  733. });
  734. it("should properly insert the error when provided with an object containing the error", function () {
  735. dropzone.options.error.call(dropzone, file, {
  736. error: "test message",
  737. });
  738. return file.previewElement
  739. .querySelector("[data-dz-errormessage]")
  740. .innerHTML.should.eql("test message");
  741. });
  742. });
  743. describe(".thumbnail()", () =>
  744. it("should properly insert the error", function () {
  745. let transparentGif =
  746. "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
  747. dropzone.options.thumbnail.call(dropzone, file, transparentGif);
  748. let thumbnail = file.previewElement.querySelector(
  749. "[data-dz-thumbnail]"
  750. );
  751. thumbnail.src.should.eql(transparentGif);
  752. return thumbnail.alt.should.eql("test name");
  753. }));
  754. describe(".uploadprogress()", () =>
  755. it("should properly set the width", function () {
  756. dropzone.options.uploadprogress.call(dropzone, file, 0);
  757. file.previewElement
  758. .querySelector("[data-dz-uploadprogress]")
  759. .style.width.should.eql("0%");
  760. dropzone.options.uploadprogress.call(dropzone, file, 80);
  761. file.previewElement
  762. .querySelector("[data-dz-uploadprogress]")
  763. .style.width.should.eql("80%");
  764. dropzone.options.uploadprogress.call(dropzone, file, 90);
  765. file.previewElement
  766. .querySelector("[data-dz-uploadprogress]")
  767. .style.width.should.eql("90%");
  768. dropzone.options.uploadprogress.call(dropzone, file, 100);
  769. return file.previewElement
  770. .querySelector("[data-dz-uploadprogress]")
  771. .style.width.should.eql("100%");
  772. }));
  773. return describe(".resize()", function () {
  774. describe("with default thumbnail settings", function () {
  775. it("should properly return target dimensions for 'contain'", function () {
  776. let info = dropzone.options.resize.call(
  777. dropzone,
  778. file,
  779. 120,
  780. 120,
  781. "crop"
  782. );
  783. info.trgWidth.should.eql(120);
  784. info.trgHeight.should.eql(100);
  785. info = dropzone.options.resize.call(
  786. dropzone,
  787. file,
  788. 100,
  789. 100,
  790. "crop"
  791. );
  792. info.trgWidth.should.eql(100);
  793. return info.trgHeight.should.eql(100);
  794. });
  795. it("should properly return target dimensions for 'contain'", function () {
  796. let info = dropzone.options.resize.call(
  797. dropzone,
  798. file,
  799. 120,
  800. 120,
  801. "contain"
  802. );
  803. info.trgWidth.should.eql(120);
  804. info.trgHeight.should.eql(60);
  805. info = dropzone.options.resize.call(
  806. dropzone,
  807. file,
  808. 100,
  809. 100,
  810. "contain"
  811. );
  812. info.trgWidth.should.eql(100);
  813. return info.trgHeight.should.eql(50);
  814. });
  815. });
  816. return describe("with null thumbnail settings", function () {
  817. it("should properly return target dimensions for crop", function () {
  818. let testSettings = [
  819. [null, null],
  820. [null, 80],
  821. [150, null],
  822. ];
  823. return (() => {
  824. let result = [];
  825. for (let i = 0; i < testSettings.length; i++) {
  826. let setting = testSettings[i];
  827. let info = dropzone.options.resize.call(
  828. dropzone,
  829. file,
  830. setting[0],
  831. setting[1],
  832. "crop"
  833. );
  834. if (i === 0) {
  835. info.trgWidth.should.eql(200);
  836. info.trgHeight.should.eql(100);
  837. }
  838. if (i === 1) {
  839. info.trgWidth.should.eql(160);
  840. info.trgHeight.should.eql(80);
  841. }
  842. if (i === 2) {
  843. info.trgWidth.should.eql(150);
  844. result.push(info.trgHeight.should.eql(75));
  845. } else {
  846. result.push(undefined);
  847. }
  848. }
  849. return result;
  850. })();
  851. });
  852. it("should properly return target dimensions for contain", function () {
  853. let testSettings = [
  854. [null, 80],
  855. [150, null],
  856. ];
  857. return (() => {
  858. let result = [];
  859. for (let i = 0; i < testSettings.length; i++) {
  860. let setting = testSettings[i];
  861. let info = dropzone.options.resize.call(
  862. dropzone,
  863. file,
  864. setting[0],
  865. setting[1],
  866. "contain"
  867. );
  868. if (i === 0) {
  869. info.trgWidth.should.eql(160);
  870. info.trgHeight.should.eql(80);
  871. }
  872. if (i === 1) {
  873. info.trgWidth.should.eql(150);
  874. result.push(info.trgHeight.should.eql(75));
  875. } else {
  876. result.push(undefined);
  877. }
  878. }
  879. return result;
  880. })();
  881. });
  882. });
  883. });
  884. });
  885. });
  886. describe("instance", function () {
  887. let element = null;
  888. let dropzone = null;
  889. let requests = null;
  890. beforeEach(function () {
  891. requests = [];
  892. xhr.onCreate = (xhr) => requests.push(xhr);
  893. element = Dropzone.createElement("<div></div>");
  894. document.body.appendChild(element);
  895. return (dropzone = new Dropzone(element, {
  896. maxFilesize: 4,
  897. maxFiles: 100,
  898. url: "url",
  899. acceptedMimeTypes: "audio/*,image/png",
  900. uploadprogress() {},
  901. }));
  902. });
  903. afterEach(function () {
  904. document.body.removeChild(element);
  905. dropzone.destroy();
  906. return xhr.restore();
  907. });
  908. describe(".accept()", function () {
  909. it("should pass if the filesize is OK", () =>
  910. dropzone.accept(
  911. { size: 2 * 1024 * 1024, type: "audio/mp3" },
  912. (err) => expect(err).to.be.undefined
  913. ));
  914. it("shouldn't pass if the filesize is too big", () =>
  915. dropzone.accept({ size: 10 * 1024 * 1024, type: "audio/mp3" }, (err) =>
  916. err.should.eql("File is too big (10MiB). Max filesize: 4MiB.")
  917. ));
  918. it("should properly accept files which mime types are listed in acceptedFiles", function () {
  919. dropzone.accept(
  920. { type: "audio/mp3" },
  921. (err) => expect(err).to.be.undefined
  922. );
  923. dropzone.accept(
  924. { type: "image/png" },
  925. (err) => expect(err).to.be.undefined
  926. );
  927. return dropzone.accept(
  928. { type: "audio/wav" },
  929. (err) => expect(err).to.be.undefined
  930. );
  931. });
  932. it("should properly reject files when the mime type isn't listed in acceptedFiles", () =>
  933. dropzone.accept({ type: "image/jpeg" }, (err) =>
  934. err.should.eql("You can't upload files of this type.")
  935. ));
  936. it("should fail if maxFiles has been exceeded and call the event maxfilesexceeded", function () {
  937. sinon.stub(dropzone, "getAcceptedFiles");
  938. let file = { type: "audio/mp3" };
  939. dropzone.getAcceptedFiles.returns({ length: 99 });
  940. dropzone.options.dictMaxFilesExceeded =
  941. "You can only upload {{maxFiles}} files.";
  942. let called = false;
  943. dropzone.on("maxfilesexceeded", function (lfile) {
  944. lfile.should.equal(file);
  945. return (called = true);
  946. });
  947. dropzone.accept(file, (err) => expect(err).to.be.undefined);
  948. called.should.not.be.ok;
  949. dropzone.getAcceptedFiles.returns({ length: 100 });
  950. dropzone.accept(file, (err) =>
  951. expect(err).to.equal("You can only upload 100 files.")
  952. );
  953. called.should.be.ok;
  954. return dropzone.getAcceptedFiles.restore();
  955. });
  956. it("should properly handle if maxFiles is 0", function () {
  957. let file = { type: "audio/mp3" };
  958. dropzone.options.maxFiles = 0;
  959. let called = false;
  960. dropzone.on("maxfilesexceeded", function (lfile) {
  961. lfile.should.equal(file);
  962. return (called = true);
  963. });
  964. dropzone.accept(file, (err) =>
  965. expect(err).to.equal("You can not upload any more files.")
  966. );
  967. return called.should.be.ok;
  968. });
  969. });
  970. describe(".removeFile()", () =>
  971. it("should abort uploading if file is currently being uploaded", function (done) {
  972. let mockFile = getMockFile();
  973. dropzone.uploadFile = function (file) {};
  974. dropzone.accept = (file, done) => done();
  975. sinon.stub(dropzone, "cancelUpload");
  976. dropzone.addFile(mockFile);
  977. return setTimeout(function () {
  978. mockFile.status.should.equal(Dropzone.UPLOADING);
  979. dropzone.getUploadingFiles()[0].should.equal(mockFile);
  980. dropzone.cancelUpload.callCount.should.equal(0);
  981. dropzone.removeFile(mockFile);
  982. dropzone.cancelUpload.callCount.should.equal(1);
  983. return done();
  984. }, 100);
  985. }));
  986. describe(".cancelUpload()", function () {
  987. it("should properly cancel upload if file currently uploading", function (done) {
  988. let mockFile = getMockFile();
  989. dropzone.accept = (file, done) => done();
  990. dropzone.addFile(mockFile);
  991. return setTimeout(function () {
  992. mockFile.status.should.equal(Dropzone.UPLOADING);
  993. dropzone.getUploadingFiles()[0].should.equal(mockFile);
  994. dropzone.cancelUpload(mockFile);
  995. mockFile.status.should.equal(Dropzone.CANCELED);
  996. dropzone.getUploadingFiles().length.should.equal(0);
  997. dropzone.getQueuedFiles().length.should.equal(0);
  998. return done();
  999. }, 10);
  1000. });
  1001. it("should properly cancel the upload if file is not yet uploading", function () {
  1002. let mockFile = getMockFile();
  1003. dropzone.accept = (file, done) => done();
  1004. // Making sure the file stays in the queue.
  1005. dropzone.options.parallelUploads = 0;
  1006. dropzone.addFile(mockFile);
  1007. mockFile.status.should.equal(Dropzone.QUEUED);
  1008. dropzone.getQueuedFiles()[0].should.equal(mockFile);
  1009. dropzone.cancelUpload(mockFile);
  1010. mockFile.status.should.equal(Dropzone.CANCELED);
  1011. dropzone.getQueuedFiles().length.should.equal(0);
  1012. return dropzone.getUploadingFiles().length.should.equal(0);
  1013. });
  1014. it("should call processQueue()", function (done) {
  1015. let mockFile = getMockFile();
  1016. dropzone.accept = (file, done) => done();
  1017. // Making sure the file stays in the queue.
  1018. dropzone.options.parallelUploads = 0;
  1019. sinon.spy(dropzone, "processQueue");
  1020. dropzone.addFile(mockFile);
  1021. return setTimeout(function () {
  1022. dropzone.processQueue.callCount.should.equal(1);
  1023. dropzone.cancelUpload(mockFile);
  1024. dropzone.processQueue.callCount.should.equal(2);
  1025. return done();
  1026. }, 10);
  1027. });
  1028. it("should properly cancel all files with the same XHR if uploadMultiple is true", function (done) {
  1029. let mock1 = getMockFile();
  1030. let mock2 = getMockFile();
  1031. let mock3 = getMockFile();
  1032. dropzone.accept = (file, done) => done();
  1033. // Making sure the file stays in the queue.
  1034. dropzone.options.uploadMultiple = true;
  1035. dropzone.options.parallelUploads = 3;
  1036. sinon.spy(dropzone, "processFiles");
  1037. dropzone.addFile(mock1);
  1038. dropzone.addFile(mock2);
  1039. dropzone.addFile(mock3);
  1040. return setTimeout(function () {
  1041. dropzone.processFiles.callCount.should.equal(1);
  1042. sinon.spy(mock1.xhr, "abort");
  1043. dropzone.cancelUpload(mock1);
  1044. expect(mock1.xhr === mock2.xhr && mock2.xhr === mock3.xhr).to.be.ok;
  1045. mock1.status.should.equal(Dropzone.CANCELED);
  1046. mock2.status.should.equal(Dropzone.CANCELED);
  1047. mock3.status.should.equal(Dropzone.CANCELED);
  1048. // The XHR should only be aborted once!
  1049. mock1.xhr.abort.callCount.should.equal(1);
  1050. return done();
  1051. }, 10);
  1052. });
  1053. });
  1054. describe(".disable()", () =>
  1055. it("should properly cancel all pending uploads", function (done) {
  1056. dropzone.accept = (file, done) => done();
  1057. dropzone.options.parallelUploads = 1;
  1058. dropzone.addFile(getMockFile());
  1059. dropzone.addFile(getMockFile());
  1060. return setTimeout(function () {
  1061. dropzone.getUploadingFiles().length.should.equal(1);
  1062. dropzone.getQueuedFiles().length.should.equal(1);
  1063. dropzone.files.length.should.equal(2);
  1064. sinon.spy(requests[0], "abort");
  1065. requests[0].abort.callCount.should.equal(0);
  1066. dropzone.disable();
  1067. requests[0].abort.callCount.should.equal(1);
  1068. dropzone.getUploadingFiles().length.should.equal(0);
  1069. dropzone.getQueuedFiles().length.should.equal(0);
  1070. dropzone.files.length.should.equal(2);
  1071. dropzone.files[0].status.should.equal(Dropzone.CANCELED);
  1072. dropzone.files[1].status.should.equal(Dropzone.CANCELED);
  1073. return done();
  1074. }, 10);
  1075. }));
  1076. describe(".destroy()", function () {
  1077. it("should properly cancel all pending uploads and remove all file references", function (done) {
  1078. dropzone.accept = (file, done) => done();
  1079. dropzone.options.parallelUploads = 1;
  1080. dropzone.addFile(getMockFile());
  1081. dropzone.addFile(getMockFile());
  1082. return setTimeout(function () {
  1083. dropzone.getUploadingFiles().length.should.equal(1);
  1084. dropzone.getQueuedFiles().length.should.equal(1);
  1085. dropzone.files.length.should.equal(2);
  1086. sinon.spy(dropzone, "disable");
  1087. dropzone.destroy();
  1088. dropzone.disable.callCount.should.equal(1);
  1089. element.should.not.have.property("dropzone");
  1090. return done();
  1091. }, 10);
  1092. });
  1093. it("should be able to create instance of dropzone on the same element after destroy", function () {
  1094. dropzone.destroy();
  1095. return (() =>
  1096. new Dropzone(element, {
  1097. maxFilesize: 4,
  1098. url: "url",
  1099. acceptedMimeTypes: "audio/*,image/png",
  1100. uploadprogress() {},
  1101. })).should.not.throw(Error);
  1102. });
  1103. it("should remove itself from Dropzone.instances", function () {
  1104. (Dropzone.instances.indexOf(dropzone) !== -1).should.be.ok;
  1105. dropzone.destroy();
  1106. return (Dropzone.instances.indexOf(dropzone) === -1).should.be.ok;
  1107. });
  1108. });
  1109. describe(".filesize()", function () {
  1110. it("should handle files with 0 size properly", () =>
  1111. dropzone.filesize(0).should.eql("<strong>0</strong> b"));
  1112. it("should convert to KiloBytes, etc..", function () {
  1113. dropzone.options.filesizeBase.should.eql(1000); // Just making sure the default config is correct
  1114. dropzone.filesize(2 * 1000 * 1000).should.eql("<strong>2</strong> MB");
  1115. dropzone
  1116. .filesize(2 * 1024 * 1024)
  1117. .should.eql("<strong>2.1</strong> MB");
  1118. dropzone
  1119. .filesize(2 * 1000 * 1000 * 1000)
  1120. .should.eql("<strong>2</strong> GB");
  1121. dropzone
  1122. .filesize(2 * 1024 * 1024 * 1024)
  1123. .should.eql("<strong>2.1</strong> GB");
  1124. dropzone
  1125. .filesize(2.5111 * 1000 * 1000 * 1000)
  1126. .should.eql("<strong>2.5</strong> GB");
  1127. dropzone.filesize(1.1 * 1000).should.eql("<strong>1.1</strong> KB");
  1128. return dropzone
  1129. .filesize(999 * 1000)
  1130. .should.eql("<strong>1</strong> MB");
  1131. });
  1132. it("should convert to KibiBytes, etc.. when the filesizeBase is changed to 1024", function () {
  1133. dropzone.options.filesizeBase = 1024;
  1134. dropzone.filesize(2 * 1024 * 1024).should.eql("<strong>2</strong> MB");
  1135. return dropzone
  1136. .filesize(2 * 1000 * 1000)
  1137. .should.eql("<strong>1.9</strong> MB");
  1138. });
  1139. });
  1140. describe("._updateMaxFilesReachedClass()", function () {
  1141. it("should properly add the dz-max-files-reached class", function () {
  1142. dropzone.getAcceptedFiles = () => ({ length: 10 });
  1143. dropzone.options.maxFiles = 10;
  1144. dropzone.element.classList.contains("dz-max-files-reached").should.not
  1145. .be.ok;
  1146. dropzone._updateMaxFilesReachedClass();
  1147. return dropzone.element.classList.contains("dz-max-files-reached")
  1148. .should.be.ok;
  1149. });
  1150. it("should fire the 'maxfilesreached' event when appropriate", function () {
  1151. let spy = sinon.spy();
  1152. dropzone.on("maxfilesreached", () => spy());
  1153. dropzone.getAcceptedFiles = () => ({ length: 9 });
  1154. dropzone.options.maxFiles = 10;
  1155. dropzone._updateMaxFilesReachedClass();
  1156. spy.notCalled.should.be.true;
  1157. dropzone.getAcceptedFiles = () => ({ length: 10 });
  1158. dropzone._updateMaxFilesReachedClass();
  1159. spy.called.should.be.true;
  1160. dropzone.getAcceptedFiles = () => ({ length: 11 });
  1161. dropzone._updateMaxFilesReachedClass();
  1162. spy.calledOnce.should.be.true;
  1163. }); //ie, it has not been called again
  1164. it("should properly remove the dz-max-files-reached class", function () {
  1165. dropzone.getAcceptedFiles = () => ({ length: 10 });
  1166. dropzone.options.maxFiles = 10;
  1167. dropzone.element.classList.contains("dz-max-files-reached").should.not
  1168. .be.ok;
  1169. dropzone._updateMaxFilesReachedClass();
  1170. dropzone.element.classList.contains("dz-max-files-reached").should.be
  1171. .ok;
  1172. dropzone.getAcceptedFiles = () => ({ length: 9 });
  1173. dropzone._updateMaxFilesReachedClass();
  1174. return dropzone.element.classList.contains("dz-max-files-reached")
  1175. .should.not.be.ok;
  1176. });
  1177. });
  1178. return describe("events", () => {
  1179. describe("progress updates", () =>
  1180. it("should properly emit a totaluploadprogress event", function (done) {
  1181. dropzone.files = [
  1182. {
  1183. size: 1990,
  1184. accepted: true,
  1185. status: Dropzone.UPLOADING,
  1186. upload: {
  1187. progress: 20,
  1188. total: 2000, // The bytes to upload are higher than the file size
  1189. bytesSent: 400,
  1190. },
  1191. },
  1192. {
  1193. size: 1990,
  1194. accepted: true,
  1195. status: Dropzone.UPLOADING,
  1196. upload: {
  1197. progress: 10,
  1198. total: 2000, // The bytes to upload are higher than the file size
  1199. bytesSent: 200,
  1200. },
  1201. },
  1202. ];
  1203. let _called = 0;
  1204. dropzone.on("totaluploadprogress", function (progress) {
  1205. progress.should.equal(totalProgressExpectation);
  1206. if (++_called === 3) {
  1207. return done();
  1208. }
  1209. });
  1210. var totalProgressExpectation = 15;
  1211. dropzone.emit("uploadprogress", {});
  1212. totalProgressExpectation = 97.5;
  1213. dropzone.files[0].upload.bytesSent = 2000;
  1214. dropzone.files[1].upload.bytesSent = 1900;
  1215. // It shouldn't matter that progress is not properly updated since the total size
  1216. // should be calculated from the bytes
  1217. dropzone.emit("uploadprogress", {});
  1218. totalProgressExpectation = 100;
  1219. dropzone.files[0].upload.bytesSent = 2000;
  1220. dropzone.files[1].upload.bytesSent = 2000;
  1221. // It shouldn't matter that progress is not properly updated since the total size
  1222. // should be calculated from the bytes
  1223. dropzone.emit("uploadprogress", {});
  1224. // Just so the afterEach hook doesn't try to cancel them.
  1225. dropzone.files[0].status = Dropzone.CANCELED;
  1226. return (dropzone.files[1].status = Dropzone.CANCELED);
  1227. }));
  1228. it("should emit DOM events", function (done) {
  1229. let element = Dropzone.createElement(`<form action="/the/url">
  1230. <input type="hidden" name="test" value="hidden" />
  1231. <input type="checkbox" name="unchecked" value="1" />
  1232. <input type="checkbox" name="checked" value="value1" checked="checked" />
  1233. <input type="radio" value="radiovalue1" name="radio1" />
  1234. <input type="radio" value="radiovalue2" name="radio1" checked="checked" />
  1235. <select name="select"><option value="1">1</option><option value="2" selected>2</option></select>
  1236. </form>`);
  1237. dropzone = new Dropzone(element, { url: "/the/url" });
  1238. var domEventTriggered = false;
  1239. element.addEventListener("dropzone:sending", function (evt) {
  1240. domEventTriggered = true;
  1241. });
  1242. let mock1 = getMockFile();
  1243. dropzone.addFile(mock1);
  1244. return setTimeout(function () {
  1245. expect(domEventTriggered).to.equal(true);
  1246. done();
  1247. }, 10);
  1248. });
  1249. });
  1250. });
  1251. describe("helper function", function () {
  1252. let element = null;
  1253. let dropzone = null;
  1254. beforeEach(function () {
  1255. element = Dropzone.createElement("<div></div>");
  1256. return (dropzone = new Dropzone(element, { url: "url" }));
  1257. });
  1258. describe("getExistingFallback()", function () {
  1259. it("should return undefined if no fallback", () =>
  1260. expect(dropzone.getExistingFallback()).to.equal(undefined));
  1261. it("should only return the fallback element if it contains exactly fallback", function () {
  1262. element.appendChild(
  1263. Dropzone.createElement('<form class="fallbacks"></form>')
  1264. );
  1265. element.appendChild(
  1266. Dropzone.createElement('<form class="sfallback"></form>')
  1267. );
  1268. return expect(dropzone.getExistingFallback()).to.equal(undefined);
  1269. });
  1270. it("should return divs as fallback", function () {
  1271. let fallback = Dropzone.createElement(
  1272. '<form class=" abc fallback test "></form>'
  1273. );
  1274. element.appendChild(fallback);
  1275. return fallback.should.equal(dropzone.getExistingFallback());
  1276. });
  1277. it("should return forms as fallback", function () {
  1278. let fallback = Dropzone.createElement(
  1279. '<div class=" abc fallback test "></div>'
  1280. );
  1281. element.appendChild(fallback);
  1282. return fallback.should.equal(dropzone.getExistingFallback());
  1283. });
  1284. });
  1285. describe("getFallbackForm()", function () {
  1286. it("should use the paramName without [0] if uploadMultiple is false", function () {
  1287. dropzone.options.uploadMultiple = false;
  1288. dropzone.options.paramName = "myFile";
  1289. let fallback = dropzone.getFallbackForm();
  1290. let fileInput = fallback.querySelector("input[type=file]");
  1291. return fileInput.name.should.equal("myFile");
  1292. });
  1293. it("should properly add [0] to the file name if uploadMultiple is true", function () {
  1294. dropzone.options.uploadMultiple = true;
  1295. dropzone.options.paramName = "myFile";
  1296. let fallback = dropzone.getFallbackForm();
  1297. let fileInput = fallback.querySelector("input[type=file]");
  1298. return fileInput.name.should.equal("myFile[0]");
  1299. });
  1300. });
  1301. describe("getAcceptedFiles() / getRejectedFiles()", function () {
  1302. let mock2, mock3, mock4;
  1303. let mock1 = (mock2 = mock3 = mock4 = null);
  1304. beforeEach(function () {
  1305. mock1 = getMockFile();
  1306. mock2 = getMockFile();
  1307. mock3 = getMockFile();
  1308. mock4 = getMockFile();
  1309. dropzone.options.accept = function (file, done) {
  1310. if (file === mock1 || file === mock3) {
  1311. return done();
  1312. } else {
  1313. return done("error");
  1314. }
  1315. };
  1316. dropzone.addFile(mock1);
  1317. dropzone.addFile(mock2);
  1318. dropzone.addFile(mock3);
  1319. return dropzone.addFile(mock4);
  1320. });
  1321. it("getAcceptedFiles() should only return accepted files", () =>
  1322. dropzone.getAcceptedFiles().should.eql([mock1, mock3]));
  1323. it("getRejectedFiles() should only return rejected files", () =>
  1324. dropzone.getRejectedFiles().should.eql([mock2, mock4]));
  1325. });
  1326. describe("getQueuedFiles()", () =>
  1327. it("should return all files with the status Dropzone.QUEUED", function () {
  1328. let mock1 = getMockFile();
  1329. let mock2 = getMockFile();
  1330. let mock3 = getMockFile();
  1331. let mock4 = getMockFile();
  1332. dropzone.options.accept = (file, done) => (file.done = done);
  1333. dropzone.addFile(mock1);
  1334. dropzone.addFile(mock2);
  1335. dropzone.addFile(mock3);
  1336. dropzone.addFile(mock4);
  1337. dropzone.getQueuedFiles().should.eql([]);
  1338. mock1.done();
  1339. mock3.done();
  1340. dropzone.getQueuedFiles().should.eql([mock1, mock3]);
  1341. mock1.status.should.equal(Dropzone.QUEUED);
  1342. mock3.status.should.equal(Dropzone.QUEUED);
  1343. mock2.status.should.equal(Dropzone.ADDED);
  1344. return mock4.status.should.equal(Dropzone.ADDED);
  1345. }));
  1346. describe("getUploadingFiles()", () =>
  1347. it("should return all files with the status Dropzone.UPLOADING", function (done) {
  1348. let mock1 = getMockFile();
  1349. let mock2 = getMockFile();
  1350. let mock3 = getMockFile();
  1351. let mock4 = getMockFile();
  1352. dropzone.options.accept = (file, _done) => (file.done = _done);
  1353. dropzone.uploadFile = function () {};
  1354. dropzone.addFile(mock1);
  1355. dropzone.addFile(mock2);
  1356. dropzone.addFile(mock3);
  1357. dropzone.addFile(mock4);
  1358. dropzone.getUploadingFiles().should.eql([]);
  1359. mock1.done();
  1360. mock3.done();
  1361. return setTimeout(function () {
  1362. dropzone.getUploadingFiles().should.eql([mock1, mock3]);
  1363. mock1.status.should.equal(Dropzone.UPLOADING);
  1364. mock3.status.should.equal(Dropzone.UPLOADING);
  1365. mock2.status.should.equal(Dropzone.ADDED);
  1366. mock4.status.should.equal(Dropzone.ADDED);
  1367. return done();
  1368. }, 10);
  1369. }));
  1370. describe("getActiveFiles()", () =>
  1371. it("should return all files with the status Dropzone.UPLOADING or Dropzone.QUEUED", function (done) {
  1372. let mock1 = getMockFile();
  1373. let mock2 = getMockFile();
  1374. let mock3 = getMockFile();
  1375. let mock4 = getMockFile();
  1376. dropzone.options.accept = (file, _done) => (file.done = _done);
  1377. dropzone.uploadFile = function () {};
  1378. dropzone.options.parallelUploads = 2;
  1379. dropzone.addFile(mock1);
  1380. dropzone.addFile(mock2);
  1381. dropzone.addFile(mock3);
  1382. dropzone.addFile(mock4);
  1383. dropzone.getActiveFiles().should.eql([]);
  1384. mock1.done();
  1385. mock3.done();
  1386. mock4.done();
  1387. return setTimeout(function () {
  1388. dropzone.getActiveFiles().should.eql([mock1, mock3, mock4]);
  1389. mock1.status.should.equal(Dropzone.UPLOADING);
  1390. mock3.status.should.equal(Dropzone.UPLOADING);
  1391. mock2.status.should.equal(Dropzone.ADDED);
  1392. mock4.status.should.equal(Dropzone.QUEUED);
  1393. return done();
  1394. }, 10);
  1395. }));
  1396. return describe("getFilesWithStatus()", () =>
  1397. it("should return all files with provided status", function () {
  1398. let mock1 = getMockFile();
  1399. let mock2 = getMockFile();
  1400. let mock3 = getMockFile();
  1401. let mock4 = getMockFile();
  1402. dropzone.options.accept = (file, _done) => (file.done = _done);
  1403. dropzone.uploadFile = function () {};
  1404. dropzone.addFile(mock1);
  1405. dropzone.addFile(mock2);
  1406. dropzone.addFile(mock3);
  1407. dropzone.addFile(mock4);
  1408. dropzone
  1409. .getFilesWithStatus(Dropzone.ADDED)
  1410. .should.eql([mock1, mock2, mock3, mock4]);
  1411. mock1.status = Dropzone.UPLOADING;
  1412. mock3.status = Dropzone.QUEUED;
  1413. mock4.status = Dropzone.QUEUED;
  1414. dropzone.getFilesWithStatus(Dropzone.ADDED).should.eql([mock2]);
  1415. dropzone.getFilesWithStatus(Dropzone.UPLOADING).should.eql([mock1]);
  1416. return dropzone
  1417. .getFilesWithStatus(Dropzone.QUEUED)
  1418. .should.eql([mock3, mock4]);
  1419. }));
  1420. });
  1421. describe("file handling", function () {
  1422. let mockFile = null;
  1423. let dropzone = null;
  1424. beforeEach(function () {
  1425. mockFile = getMockFile();
  1426. let element = Dropzone.createElement("<div></div>");
  1427. dropzone = new Dropzone(element, { url: "/the/url" });
  1428. });
  1429. afterEach(() => dropzone.destroy());
  1430. describe("addFile()", function () {
  1431. it("should properly set the status of the file", function () {
  1432. let doneFunction = null;
  1433. dropzone.accept = (file, done) => (doneFunction = done);
  1434. dropzone.processFile = function () {};
  1435. dropzone.uploadFile = function () {};
  1436. dropzone.addFile(mockFile);
  1437. mockFile.status.should.eql(Dropzone.ADDED);
  1438. doneFunction();
  1439. mockFile.status.should.eql(Dropzone.QUEUED);
  1440. mockFile = getMockFile();
  1441. dropzone.addFile(mockFile);
  1442. mockFile.status.should.eql(Dropzone.ADDED);
  1443. doneFunction("error");
  1444. return mockFile.status.should.eql(Dropzone.ERROR);
  1445. });
  1446. it("should properly set the status of the file if autoProcessQueue is false and not call processQueue", function (done) {
  1447. let doneFunction = null;
  1448. dropzone.options.autoProcessQueue = false;
  1449. dropzone.accept = (file, done) => (doneFunction = done);
  1450. dropzone.processFile = function () {};
  1451. dropzone.uploadFile = function () {};
  1452. dropzone.addFile(mockFile);
  1453. sinon.stub(dropzone, "processQueue");
  1454. mockFile.status.should.eql(Dropzone.ADDED);
  1455. doneFunction();
  1456. mockFile.status.should.eql(Dropzone.QUEUED);
  1457. dropzone.processQueue.callCount.should.equal(0);
  1458. return setTimeout(function () {
  1459. dropzone.processQueue.callCount.should.equal(0);
  1460. return done();
  1461. }, 10);
  1462. });
  1463. it("should not add the file to the queue if autoQueue is false", function () {
  1464. let doneFunction = null;
  1465. dropzone.options.autoQueue = false;
  1466. dropzone.accept = (file, done) => (doneFunction = done);
  1467. dropzone.processFile = function () {};
  1468. dropzone.uploadFile = function () {};
  1469. dropzone.addFile(mockFile);
  1470. mockFile.status.should.eql(Dropzone.ADDED);
  1471. doneFunction();
  1472. return mockFile.status.should.eql(Dropzone.ADDED);
  1473. });
  1474. it("should create a remove link if configured to do so", function () {
  1475. dropzone.options.addRemoveLinks = true;
  1476. dropzone.processFile = function () {};
  1477. dropzone.uploadFile = function () {};
  1478. sinon.stub(dropzone, "processQueue");
  1479. dropzone.addFile(mockFile);
  1480. return dropzone.files[0].previewElement.querySelector(
  1481. "a[data-dz-remove].dz-remove"
  1482. ).should.be.ok;
  1483. });
  1484. it("should create a remove link with HTML if configured to do so", function () {
  1485. dropzone.options.addRemoveLinks = true;
  1486. dropzone.options.dictRemoveFile =
  1487. '<i class="icon icon-class"></i> Remove';
  1488. dropzone.processFile = function () {};
  1489. dropzone.uploadFile = function () {};
  1490. sinon.stub(dropzone, "processQueue");
  1491. dropzone.addFile(mockFile);
  1492. return (
  1493. dropzone.files[0].previewElement.querySelector(
  1494. "a[data-dz-remove].dz-remove"
  1495. ).should.be.ok &&
  1496. dropzone.files[0].previewElement
  1497. .querySelector("a[data-dz-remove].dz-remove")
  1498. .innerHTML.should.equal('<i class="icon icon-class"></i> Remove')
  1499. );
  1500. });
  1501. it("should attach an event handler to data-dz-remove links", function () {
  1502. dropzone.options.previewTemplate = `\
  1503. <div class="dz-preview dz-file-preview">
  1504. <div class="dz-details">
  1505. <div class="dz-filename"><span data-dz-name></span></div>
  1506. <div class="dz-size" data-dz-size></div>
  1507. <img data-dz-thumbnail />
  1508. </div>
  1509. <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
  1510. <div class="dz-success-mark"><span>✔</span></div>
  1511. <div class="dz-error-mark"><span>✘</span></div>
  1512. <div class="dz-error-message"><span data-dz-errormessage></span></div>
  1513. <a class="link1" data-dz-remove></a>
  1514. <a class="link2" data-dz-remove></a>
  1515. </div>\
  1516. `;
  1517. sinon.stub(dropzone, "processQueue");
  1518. dropzone.addFile(mockFile);
  1519. let file = dropzone.files[0];
  1520. let removeLink1 = file.previewElement.querySelector(
  1521. "a[data-dz-remove].link1"
  1522. );
  1523. let removeLink2 = file.previewElement.querySelector(
  1524. "a[data-dz-remove].link2"
  1525. );
  1526. sinon.stub(dropzone, "removeFile");
  1527. let event = document.createEvent("HTMLEvents");
  1528. event.initEvent("click", true, true);
  1529. removeLink1.dispatchEvent(event);
  1530. dropzone.removeFile.callCount.should.eql(1);
  1531. event = document.createEvent("HTMLEvents");
  1532. event.initEvent("click", true, true);
  1533. removeLink2.dispatchEvent(event);
  1534. return dropzone.removeFile.callCount.should.eql(2);
  1535. });
  1536. return describe("thumbnails", function () {
  1537. it("should properly queue the thumbnail creation", function (done) {
  1538. let ct_callback;
  1539. let doneFunction;
  1540. dropzone.accept = (file, done) => (doneFunction = done);
  1541. dropzone.processFile = function () {};
  1542. dropzone.uploadFile = function () {};
  1543. let mock1 = getMockFile("image/jpg");
  1544. let mock2 = getMockFile("image/jpg");
  1545. let mock3 = getMockFile("image/jpg");
  1546. let ct_file;
  1547. dropzone.createThumbnail = function (
  1548. file,
  1549. thumbnailWidth,
  1550. thumbnailHeight,
  1551. resizeMethod,
  1552. fixOrientation,
  1553. callback
  1554. ) {
  1555. ct_file = file;
  1556. ct_callback = callback;
  1557. };
  1558. sinon.spy(dropzone, "createThumbnail");
  1559. dropzone.addFile(mock1);
  1560. dropzone.addFile(mock2);
  1561. dropzone.addFile(mock3);
  1562. dropzone.files.length.should.eql(3);
  1563. return setTimeout(function () {
  1564. dropzone.createThumbnail.callCount.should.eql(1);
  1565. mock1.should.equal(ct_file);
  1566. ct_callback();
  1567. dropzone.createThumbnail.callCount.should.eql(2);
  1568. mock2.should.equal(ct_file);
  1569. ct_callback();
  1570. dropzone.createThumbnail.callCount.should.eql(3);
  1571. mock3.should.equal(ct_file);
  1572. return done();
  1573. }, 10);
  1574. });
  1575. return describe("when file is SVG", () =>
  1576. it("should use the SVG image itself", function (done) {
  1577. let createBlob = function (data, type) {
  1578. try {
  1579. return new Blob([data], { type });
  1580. } catch (e) {
  1581. let BlobBuilder =
  1582. window.BlobBuilder ||
  1583. window.WebKitBlobBuilder ||
  1584. window.MozBlobBuilder ||
  1585. window.MSBlobBuilder;
  1586. let builder = new BlobBuilder();
  1587. builder.append(data.buffer || data);
  1588. return builder.getBlob(type);
  1589. }
  1590. };
  1591. let blob = createBlob("foo", "image/svg+xml");
  1592. return dropzone.createThumbnail(
  1593. blob,
  1594. dropzone.options.thumbnailWidth,
  1595. dropzone.options.thumbnailHeight,
  1596. "crop",
  1597. false,
  1598. function (dataURI, canvas) {
  1599. let fileReader = new FileReader();
  1600. fileReader.onload = function () {
  1601. fileReader.result.should.equal(dataURI);
  1602. return done();
  1603. };
  1604. return fileReader.readAsDataURL(blob);
  1605. }
  1606. );
  1607. }));
  1608. });
  1609. });
  1610. describe("enqueueFile()", function () {
  1611. it("should be wrapped by enqueueFiles()", function () {
  1612. sinon.stub(dropzone, "enqueueFile");
  1613. let mock1 = getMockFile();
  1614. let mock2 = getMockFile();
  1615. let mock3 = getMockFile();
  1616. dropzone.enqueueFiles([mock1, mock2, mock3]);
  1617. dropzone.enqueueFile.callCount.should.equal(3);
  1618. dropzone.enqueueFile.args[0][0].should.equal(mock1);
  1619. dropzone.enqueueFile.args[1][0].should.equal(mock2);
  1620. return dropzone.enqueueFile.args[2][0].should.equal(mock3);
  1621. });
  1622. it("should fail if the file has already been processed", function () {
  1623. mockFile.status = Dropzone.ERROR;
  1624. expect(() => dropzone.enqueueFile(mockFile)).to.throw(
  1625. "This file can't be queued because it has already been processed or was rejected."
  1626. );
  1627. mockFile.status = Dropzone.COMPLETE;
  1628. expect(() => dropzone.enqueueFile(mockFile)).to.throw(
  1629. "This file can't be queued because it has already been processed or was rejected."
  1630. );
  1631. mockFile.status = Dropzone.UPLOADING;
  1632. return expect(() => dropzone.enqueueFile(mockFile)).to.throw(
  1633. "This file can't be queued because it has already been processed or was rejected."
  1634. );
  1635. });
  1636. it("should set the status to QUEUED and call processQueue asynchronously if everything's ok", function (done) {
  1637. mockFile.status = Dropzone.ADDED;
  1638. sinon.stub(dropzone, "processQueue");
  1639. dropzone.processQueue.callCount.should.equal(0);
  1640. dropzone.enqueueFile(mockFile);
  1641. mockFile.status.should.equal(Dropzone.QUEUED);
  1642. dropzone.processQueue.callCount.should.equal(0);
  1643. return setTimeout(function () {
  1644. dropzone.processQueue.callCount.should.equal(1);
  1645. return done();
  1646. }, 10);
  1647. });
  1648. });
  1649. describe("uploadFiles()", function () {
  1650. let requests;
  1651. beforeEach(function () {
  1652. requests = [];
  1653. return (xhr.onCreate = (xhr) => requests.push(xhr));
  1654. });
  1655. afterEach(() => xhr.restore());
  1656. // Removed this test because multiple filenames can be transmitted now
  1657. // it "should properly urlencode the filename for the headers"
  1658. it("should be wrapped by uploadFile()", function () {
  1659. sinon.stub(dropzone, "uploadFiles");
  1660. dropzone.uploadFile(mockFile);
  1661. dropzone.uploadFiles.callCount.should.equal(1);
  1662. return dropzone.uploadFiles.calledWith([mockFile]).should.be.ok;
  1663. });
  1664. it("should use url options if strings", function (done) {
  1665. dropzone.addFile(mockFile);
  1666. return setTimeout(function () {
  1667. expect(requests.length).to.equal(1);
  1668. expect(requests[0].url).to.equal(dropzone.options.url);
  1669. expect(requests[0].method).to.equal(dropzone.options.method);
  1670. return done();
  1671. }, 10);
  1672. });
  1673. it("should call url options if functions", function (done) {
  1674. let method = "PUT";
  1675. let url = "/custom/upload/url";
  1676. dropzone.options.method = sinon.stub().returns(method);
  1677. dropzone.options.url = sinon.stub().returns(url);
  1678. dropzone.addFile(mockFile);
  1679. return setTimeout(function () {
  1680. dropzone.options.method.callCount.should.equal(1);
  1681. dropzone.options.url.callCount.should.equal(1);
  1682. sinon.assert.calledWith(dropzone.options.method, [mockFile]);
  1683. sinon.assert.calledWith(dropzone.options.url, [mockFile]);
  1684. expect(requests.length).to.equal(1);
  1685. expect(requests[0].url).to.equal(url);
  1686. expect(requests[0].method).to.equal(method);
  1687. return done();
  1688. }, 10);
  1689. });
  1690. it("should use the timeout option", function (done) {
  1691. dropzone.options.timeout = 10000;
  1692. dropzone.addFile(mockFile);
  1693. return setTimeout(function () {
  1694. expect(requests[0].timeout).to.equal(10000);
  1695. return done();
  1696. }, 10);
  1697. });
  1698. it("should properly handle if timeout is null", function (done) {
  1699. dropzone.options.timeout = null;
  1700. dropzone.addFile(mockFile);
  1701. return setTimeout(function () {
  1702. expect(requests[0].timeout).to.equal(0);
  1703. return done();
  1704. }, 10);
  1705. });
  1706. it("should ignore the onreadystate callback if readyState != 4", function (done) {
  1707. dropzone.addFile(mockFile);
  1708. return setTimeout(function () {
  1709. mockFile.status.should.eql(Dropzone.UPLOADING);
  1710. requests[0].status = 200;
  1711. requests[0].readyState = 3;
  1712. requests[0].responseHeaders = { "content-type": "text/plain" };
  1713. requests[0].onload();
  1714. mockFile.status.should.eql(Dropzone.UPLOADING);
  1715. requests[0].readyState = 4;
  1716. requests[0].onload();
  1717. mockFile.status.should.eql(Dropzone.SUCCESS);
  1718. return done();
  1719. }, 10);
  1720. });
  1721. it("should emit error and errormultiple when response was not OK", function (done) {
  1722. dropzone.options.uploadMultiple = true;
  1723. let error = false;
  1724. let errormultiple = false;
  1725. let complete = false;
  1726. let completemultiple = false;
  1727. dropzone.on("error", () => (error = true));
  1728. dropzone.on("errormultiple", () => (errormultiple = true));
  1729. dropzone.on("complete", () => (complete = true));
  1730. dropzone.on("completemultiple", () => (completemultiple = true));
  1731. dropzone.addFile(mockFile);
  1732. return setTimeout(function () {
  1733. mockFile.status.should.eql(Dropzone.UPLOADING);
  1734. requests[0].status = 400;
  1735. requests[0].readyState = 4;
  1736. requests[0].responseHeaders = { "content-type": "text/plain" };
  1737. requests[0].onload();
  1738. expect(
  1739. true === error &&
  1740. error === errormultiple &&
  1741. errormultiple === complete &&
  1742. complete === completemultiple
  1743. ).to.be.ok;
  1744. return done();
  1745. }, 10);
  1746. });
  1747. it("should include hidden files in the form and unchecked checkboxes and radiobuttons should be excluded", function (done) {
  1748. let element = Dropzone.createElement(`<form action="/the/url">
  1749. <input type="hidden" name="test" value="hidden" />
  1750. <input type="checkbox" name="unchecked" value="1" />
  1751. <input type="checkbox" name="checked" value="value1" checked="checked" />
  1752. <input type="radio" value="radiovalue1" name="radio1" />
  1753. <input type="radio" value="radiovalue2" name="radio1" checked="checked" />
  1754. <select name="select"><option value="1">1</option><option value="2" selected>2</option></select>
  1755. </form>`);
  1756. dropzone = new Dropzone(element, { url: "/the/url" });
  1757. let formData = null;
  1758. dropzone.on("sending", function (file, xhr, tformData) {
  1759. formData = tformData;
  1760. return sinon.spy(tformData, "append");
  1761. });
  1762. let mock1 = getMockFile();
  1763. dropzone.addFile(mock1);
  1764. return setTimeout(function () {
  1765. formData.append.callCount.should.equal(5);
  1766. formData.append.args[0][0].should.eql("test");
  1767. formData.append.args[0][1].should.eql("hidden");
  1768. formData.append.args[1][0].should.eql("checked");
  1769. formData.append.args[1][1].should.eql("value1");
  1770. formData.append.args[2][0].should.eql("radio1");
  1771. formData.append.args[2][1].should.eql("radiovalue2");
  1772. formData.append.args[3][0].should.eql("select");
  1773. formData.append.args[3][1].should.eql("2");
  1774. formData.append.args[4][0].should.eql("file");
  1775. formData.append.args[4][1].should.equal(mock1);
  1776. // formData.append.args[1][0].should.eql "myName[]"
  1777. return done();
  1778. }, 10);
  1779. });
  1780. it("should all values of a select that has the multiple attribute", function (done) {
  1781. let element = Dropzone.createElement(`<form action="/the/url">
  1782. <select name="select" multiple>
  1783. <option value="value1">1</option>
  1784. <option value="value2" selected>2</option>
  1785. <option value="value3">3</option>
  1786. <option value="value4" selected>4</option>
  1787. </select>
  1788. </form>`);
  1789. dropzone = new Dropzone(element, { url: "/the/url" });
  1790. let formData = null;
  1791. dropzone.on("sending", function (file, xhr, tformData) {
  1792. formData = tformData;
  1793. return sinon.spy(tformData, "append");
  1794. });
  1795. let mock1 = getMockFile();
  1796. dropzone.addFile(mock1);
  1797. return setTimeout(function () {
  1798. formData.append.callCount.should.equal(3);
  1799. formData.append.args[0][0].should.eql("select");
  1800. formData.append.args[0][1].should.eql("value2");
  1801. formData.append.args[1][0].should.eql("select");
  1802. formData.append.args[1][1].should.eql("value4");
  1803. formData.append.args[2][0].should.eql("file");
  1804. formData.append.args[2][1].should.equal(mock1);
  1805. // formData.append.args[1][0].should.eql "myName[]"
  1806. return done();
  1807. }, 10);
  1808. });
  1809. describe("settings()", function () {
  1810. it("should correctly set `withCredentials` on the xhr object", function () {
  1811. dropzone.uploadFile(mockFile);
  1812. requests.length.should.eql(1);
  1813. requests[0].withCredentials.should.eql(false);
  1814. dropzone.options.withCredentials = true;
  1815. dropzone.uploadFile(mockFile);
  1816. requests.length.should.eql(2);
  1817. return requests[1].withCredentials.should.eql(true);
  1818. });
  1819. it("should correctly override headers on the xhr object", function () {
  1820. dropzone.options.headers = { "Foo-Header": "foobar" };
  1821. dropzone.uploadFile(mockFile);
  1822. return requests[0].requestHeaders["Foo-Header"].should.eql("foobar");
  1823. });
  1824. it("should not set headers on the xhr object that are empty", function () {
  1825. dropzone.options.headers = { "X-Requested-With": null };
  1826. dropzone.uploadFile(mockFile);
  1827. return Object.keys(requests[0].requestHeaders).should.not.contain(
  1828. "X-Requested-With"
  1829. );
  1830. });
  1831. it("should properly use the paramName without [n] as file upload if uploadMultiple is false", function (done) {
  1832. dropzone.options.uploadMultiple = false;
  1833. dropzone.options.paramName = "myName";
  1834. let formData = [];
  1835. let sendingCount = 0;
  1836. dropzone.on("sending", function (files, xhr, tformData) {
  1837. sendingCount++;
  1838. formData.push(tformData);
  1839. return sinon.spy(tformData, "append");
  1840. });
  1841. let mock1 = getMockFile();
  1842. let mock2 = getMockFile();
  1843. dropzone.addFile(mock1);
  1844. dropzone.addFile(mock2);
  1845. return setTimeout(function () {
  1846. sendingCount.should.equal(2);
  1847. formData.length.should.equal(2);
  1848. formData[0].append.callCount.should.equal(1);
  1849. formData[1].append.callCount.should.equal(1);
  1850. formData[0].append.args[0][0].should.eql("myName");
  1851. formData[0].append.args[0][0].should.eql("myName");
  1852. return done();
  1853. }, 10);
  1854. });
  1855. it("should properly use the paramName with [n] as file upload if uploadMultiple is true", function (done) {
  1856. dropzone.options.uploadMultiple = true;
  1857. dropzone.options.paramName = "myName";
  1858. let formData = null;
  1859. let sendingMultipleCount = 0;
  1860. let sendingCount = 0;
  1861. dropzone.on("sending", (file, xhr, tformData) => sendingCount++);
  1862. dropzone.on("sendingmultiple", function (files, xhr, tformData) {
  1863. sendingMultipleCount++;
  1864. formData = tformData;
  1865. return sinon.spy(tformData, "append");
  1866. });
  1867. let mock1 = getMockFile();
  1868. let mock2 = getMockFile();
  1869. dropzone.addFile(mock1);
  1870. dropzone.addFile(mock2);
  1871. return setTimeout(function () {
  1872. sendingCount.should.equal(2);
  1873. sendingMultipleCount.should.equal(1);
  1874. dropzone.uploadFiles([mock1, mock2]);
  1875. formData.append.callCount.should.equal(2);
  1876. formData.append.args[0][0].should.eql("myName[0]");
  1877. formData.append.args[1][0].should.eql("myName[1]");
  1878. return done();
  1879. }, 10);
  1880. });
  1881. it("should use resizeImage if dimensions are provided", function (done) {
  1882. sinon.stub(dropzone, "resizeImage");
  1883. sinon.stub(dropzone, "createThumbnail");
  1884. dropzone.options.resizeWidth = 400;
  1885. let mock1 = getMockFile("image/jpeg");
  1886. dropzone.addFile(mock1);
  1887. return setTimeout(function () {
  1888. dropzone.resizeImage.callCount.should.eql(1);
  1889. return done();
  1890. }, 10);
  1891. });
  1892. it("should not use resizeImage for SVG if dimensions are provided", function (done) {
  1893. sinon.stub(dropzone, "uploadFiles");
  1894. dropzone.createThumbnail = function (
  1895. file,
  1896. width,
  1897. height,
  1898. resizeMethod,
  1899. fixOrientation,
  1900. callback
  1901. ) {
  1902. callback(null, null);
  1903. };
  1904. dropzone.options.resizeWidth = 400;
  1905. let mock1 = getMockFile("image/svg+xml");
  1906. dropzone.addFile(mock1);
  1907. setTimeout(function () {
  1908. dropzone.uploadFiles.callCount.should.eql(1);
  1909. let uploadedFiles = dropzone.uploadFiles.getCall(0).args[0];
  1910. uploadedFiles.should.eql([mock1]);
  1911. done();
  1912. }, 10);
  1913. });
  1914. it("should not use resizeImage if dimensions are not provided", function (done) {
  1915. sinon.stub(dropzone, "resizeImage");
  1916. sinon.stub(dropzone, "createThumbnail");
  1917. let mock1 = getMockFile("image/jpeg");
  1918. dropzone.addFile(mock1);
  1919. return setTimeout(function () {
  1920. dropzone.resizeImage.callCount.should.eql(0);
  1921. return done();
  1922. }, 10);
  1923. });
  1924. it("should not use resizeImage if file is not an image", function (done) {
  1925. sinon.stub(dropzone, "resizeImage");
  1926. sinon.stub(dropzone, "createThumbnail");
  1927. dropzone.options.resizeWidth = 400;
  1928. let mock1 = getMockFile("text/plain");
  1929. dropzone.addFile(mock1);
  1930. return setTimeout(function () {
  1931. dropzone.resizeImage.callCount.should.eql(0);
  1932. return done();
  1933. }, 10);
  1934. });
  1935. });
  1936. it("should not change the file name if the options.renameFile is not set", function (done) {
  1937. let mockFilename = "T3sT ;:_-.,!¨@&%&";
  1938. mockFile = getMockFile("text/html", mockFilename);
  1939. let renamedFilename = dropzone._renameFile(mockFile);
  1940. renamedFilename.should.equal(mockFilename);
  1941. return done();
  1942. });
  1943. it("should rename the file name if options.renamedFilename is set", function (done) {
  1944. dropzone.options.renameFile = (file) =>
  1945. file.name.toLowerCase().replace(/[^\w]/gi, "");
  1946. mockFile = getMockFile("text/html", "T3sT ;:_-.,!¨@&%&");
  1947. let renamedFilename = dropzone._renameFile(mockFile);
  1948. renamedFilename.should.equal("t3st_");
  1949. return done();
  1950. });
  1951. return describe("should properly set status of file", () =>
  1952. it("should correctly set `withCredentials` on the xhr object", function (done) {
  1953. dropzone.addFile(mockFile);
  1954. setTimeout(function () {
  1955. mockFile.status.should.eql(Dropzone.UPLOADING);
  1956. requests.length.should.equal(1);
  1957. requests[0].status = 400;
  1958. requests[0].readyState = 4;
  1959. requests[0].responseHeaders = { "content-type": "text/plain" };
  1960. requests[0].onload();
  1961. mockFile.status.should.eql(Dropzone.ERROR);
  1962. mockFile = getMockFile();
  1963. dropzone.addFile(mockFile);
  1964. setTimeout(function () {
  1965. mockFile.status.should.eql(Dropzone.UPLOADING);
  1966. requests.length.should.equal(2);
  1967. requests[1].status = 200;
  1968. requests[1].readyState = 4;
  1969. requests[1].responseHeaders = { "content-type": "text/plain" };
  1970. requests[1].onload();
  1971. mockFile.status.should.eql(Dropzone.SUCCESS);
  1972. return done();
  1973. }, 10);
  1974. }, 10);
  1975. }));
  1976. });
  1977. describe("transformFile()", function () {
  1978. it("should be invoked and the result should be uploaded if configured", (done) => {
  1979. sinon.stub(dropzone, "_uploadData");
  1980. let mock1 = getMockFile("text/html", "original-file");
  1981. let mock2 = getMockFile("text/html", "transformed-file");
  1982. dropzone.options.transformFile = (file, done) => {
  1983. file.should.eql(mock1);
  1984. done(mock2);
  1985. };
  1986. dropzone.addFile(mock1);
  1987. setTimeout(function () {
  1988. dropzone._uploadData.callCount.should.equal(1);
  1989. let uploadedFiles = dropzone._uploadData.args[0][0];
  1990. let uploadedDataBlocks = dropzone._uploadData.args[0][1];
  1991. uploadedFiles[0].should.equal(mock1);
  1992. uploadedDataBlocks[0].data.should.equal(mock2);
  1993. done();
  1994. }, 10);
  1995. });
  1996. it("should be used as a basis for chunked uploads", (done) => {
  1997. sinon.stub(dropzone, "_uploadData");
  1998. dropzone.options.chunking = true;
  1999. dropzone.options.chunkSize = 1;
  2000. dropzone.options.parallelChunkUploads = true;
  2001. let mock1 = getMockFile("text/html", "original-file", [
  2002. "Veeeeery long file",
  2003. ]); // 18 bytes
  2004. let mock2 = getMockFile("text/html", "transformed-file", ["2b"]); // only 2 bytes
  2005. dropzone.options.transformFile = (file, done) => {
  2006. file.should.eql(mock1);
  2007. done(mock2);
  2008. };
  2009. dropzone.addFile(mock1);
  2010. setTimeout(async function () {
  2011. dropzone._uploadData.callCount.should.equal(2);
  2012. // the same file should be passed on each call.
  2013. dropzone._uploadData.args[0][0][0].should.eql(mock1);
  2014. dropzone._uploadData.args[1][0][0].should.eql(mock1);
  2015. // Since we only allow chunks of 1 byte, there should be 2 chunks,
  2016. // because the transformed file only has 2 bytes.
  2017. // If this would equal to 18 bytes, then the wrong file would have
  2018. // been chunked.
  2019. mock1.upload.totalChunkCount.should.eql(2);
  2020. let uploadedDataBlocks1 = dropzone._uploadData.args[0][1][0];
  2021. let uploadedDataBlocks2 = dropzone._uploadData.args[1][1][0];
  2022. let block1Text = await uploadedDataBlocks1.data.text();
  2023. let block2Text = await uploadedDataBlocks2.data.text();
  2024. block1Text.should.equal("2");
  2025. block2Text.should.equal("b");
  2026. done();
  2027. }, 10);
  2028. });
  2029. });
  2030. return describe("complete file", () =>
  2031. it("should properly emit the queuecomplete event when the complete queue is finished", function (done) {
  2032. let mock1 = getMockFile("text/html", "mock1");
  2033. let mock2 = getMockFile("text/html", "mock2");
  2034. let mock3 = getMockFile("text/html", "mock3");
  2035. mock1.status = Dropzone.ADDED;
  2036. mock2.status = Dropzone.ADDED;
  2037. mock3.status = Dropzone.ADDED;
  2038. dropzone.uploadFiles = function (files) {
  2039. return setTimeout(() => {
  2040. return this._finished(files, null, null);
  2041. }, 1);
  2042. };
  2043. let completedFiles = 0;
  2044. dropzone.on("complete", (file) => completedFiles++);
  2045. dropzone.on("queuecomplete", function () {
  2046. completedFiles.should.equal(3);
  2047. return done();
  2048. });
  2049. dropzone.addFile(mock1);
  2050. dropzone.addFile(mock2);
  2051. return dropzone.addFile(mock3);
  2052. }));
  2053. });
  2054. });