test_DataTransferItemList.html (9608B)
1 <html> 2 <head> 3 <title>Tests for the DataTransferItemList object</title> 4 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 5 <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 6 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> 7 </head> 8 <body style="height: 300px; overflow: auto;"> 9 <p id="display"> </p> 10 <img id="image" draggable="true" src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%18%00%00%00%18%02%03%00%00%00%9D%19%D5k%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%0CPLTE%FF%FF%FF%FF%FF%FF%F7%DC%13%00%00%00%03%80%01X%00%00%00%01tRNS%08N%3DPT%00%00%00%01bKGD%00%88%05%1DH%00%00%00%09pHYs%00%00%0B%11%00%00%0B%11%01%7Fd_%91%00%00%00%07tIME%07%D2%05%0C%14%0C%0D%D8%3F%1FQ%00%00%00%5CIDATx%9C%7D%8E%CB%09%C0%20%10D%07r%B7%20%2F%E9wV0%15h%EA%D9%12D4%BB%C1x%CC%5C%1E%0C%CC%07%C0%9C0%9Dd7()%C0A%D3%8D%E0%B8%10%1DiCHM%D0%AC%D2d%C3M%F1%B4%E7%FF%10%0BY%AC%25%93%CD%CBF%B5%B2%C0%3Alh%CD%AE%13%DF%A5%F7%E0%03byW%09A%B4%F3%E2%00%00%00%00IEND%AEB%60%82"> 11 <div id="over" style="width: 100px; height: 100px; border: 2px black dashed;"> 12 drag over here 13 </div> 14 15 <script> 16 function spin() { 17 // Defer to the event loop twice to wait for any events to be flushed out. 18 return new Promise(function(a) { 19 SimpleTest.executeSoon(function() { 20 SimpleTest.executeSoon(a) 21 }); 22 }); 23 } 24 25 add_task(async function() { 26 await spin(); 27 var draggable = document.getElementById('image'); 28 var over = document.getElementById('over'); 29 30 var dragstartFired = 0; 31 draggable.addEventListener('dragstart', onDragStart); 32 function onDragStart(e) { 33 draggable.removeEventListener('dragstart', onDragStart); 34 35 var dt = e.dataTransfer; 36 dragstartFired++; 37 38 ok(true, "dragStart event fired"); 39 var dtList = e.dataTransfer.items; 40 ok(dtList instanceof DataTransferItemList, 41 "DataTransfer.items returns a DataTransferItemList"); 42 43 for (var i = 0; i < dtList.length; i++) { 44 var item = dtList[i]; 45 ok(item instanceof DataTransferItem, 46 "operator[] returns DataTransferItem objects"); 47 if (item.kind == "file") { 48 var file = item.getAsFile(); 49 ok(file instanceof File, "getAsFile() returns File objects"); 50 } 51 } 52 53 dtList.clear(); 54 is(dtList.length, 0, "after .clear() DataTransferItemList should be empty"); 55 56 dtList.add("this is some text", "text/plain"); 57 dtList.add("<a href='www.mozilla.org'>this is a link</a>", "text/html"); 58 dtList.add("http://www.mozilla.org", "text/uri-list"); 59 dtList.add("this is custom-data", "custom-data"); 60 61 62 var file = new File(['<a id="a"><b id="b">hey!</b></a>'], "myfile.html", 63 {type: "text/html"}); 64 65 dtList.add(file); 66 67 checkTypes(["text/plain", "text/html", "text/uri-list", "custom-data", "text/html"], 68 dtList, "DataTransferItemList.add test"); 69 70 var files = e.dataTransfer.files; 71 is(files.length, 1, "DataTransfer.files should contain the one file we added earlier"); 72 is(files[0], file, "It should be the same file as the file we originally created"); 73 is(file, e.dataTransfer.mozGetDataAt("text/html", 1), 74 "It should be stored in index 1 for mozGetDataAt"); 75 76 var file2 = new File(['<a id="c"><b id="d">yo!</b></a>'], "myotherfile.html", 77 {type: "text/html"}); 78 dtList.add(file2); 79 80 todo(files.length == 2, "This test has chrome privileges, so the FileList objects aren't updated live"); 81 files = e.dataTransfer.files; 82 is(files.length, 2, "The files property should have been updated in place"); 83 is(files[1], file2, "It should be the same file as the file we originally created"); 84 is(file2, e.dataTransfer.mozGetDataAt("text/html", 2), 85 "It should be stored in index 2 for mozGetDataAt"); 86 87 var oldLength = dtList.length; 88 var randomString = "foo!"; 89 e.dataTransfer.mozSetDataAt("random/string", randomString, 3); 90 is(oldLength, dtList.length, 91 "Adding a non-file entry to a non-zero index should not add an item to the items list"); 92 93 var file3 = new File(['<a id="e"><b id="f">heya!</b></a>'], "yetanotherfile.html", 94 {type: "text/html"}); 95 e.dataTransfer.mozSetDataAt("random/string", file3, 3); 96 is(oldLength + 1, dtList.length, 97 "Replacing the entry with a file should add it to the list!"); 98 is(dtList[oldLength].getAsFile(), file3, "It should be stored in the last index as a file"); 99 is(dtList[oldLength].type, "text/html", "It should have the correct type"); 100 is(dtList[oldLength].kind, "file", "It should have the correct kind"); 101 102 todo(files.length == 3, "This test has chrome privileges, so the FileList objects aren't updated live"); 103 files = e.dataTransfer.files; 104 is(files[files.length - 1], file3, "It should also be in the files list"); 105 106 oldLength = dtList.length; 107 var nonstring = {}; 108 e.dataTransfer.mozSetDataAt("jsobject", nonstring, 0); 109 is(oldLength + 1, dtList.length, 110 "Adding a non-string object using the mozAPIs to index 0 should add an item to the dataTransfer"); 111 is(dtList[oldLength].type, "jsobject", "It should have the correct type"); 112 is(dtList[oldLength].kind, "other", "It should have the correct kind"); 113 114 // Clear the event's data and get it set up so we can read it later! 115 dtList.clear(); 116 117 dtList.add(file); 118 dtList.add("this is some text", "text/plain"); 119 is(e.dataTransfer.mozGetDataAt("text/html", 1), file); 120 } 121 122 var getAsStringCalled = 0; 123 var dragenterFired = 0; 124 over.addEventListener('dragenter', onDragEnter); 125 function onDragEnter(e) { 126 over.removeEventListener('dragenter', onDragEnter); 127 128 var dt = e.dataTransfer; 129 dragenterFired++; 130 131 // NOTE: This test is run with chrome privileges. 132 // For back-compat reasons, protected mode acts like readonly mode for 133 // chrome documents. 134 readOnly(e); 135 } 136 137 var dropFired = 0; 138 over.addEventListener('drop', onDrop); 139 function onDrop(e) { 140 over.removeEventListener('drop', onDrop); 141 142 var dt = e.dataTransfer; 143 dropFired++; 144 e.preventDefault(); 145 146 readOnly(e); 147 } 148 149 150 function readOnly(e) { 151 var dtList = e.dataTransfer.items; 152 var num = dtList.length; 153 154 // .clear() should have no effect 155 dtList.clear(); 156 is(dtList.length, num, 157 ".clear() should have no effect on the object during a readOnly event"); 158 159 // .remove(i) should throw InvalidStateError 160 for (var i = 0; i < dtList.length; i++) { 161 expectError(function() { dtList.remove(i); }, 162 "InvalidStateError", ".remove(" + i + ") during a readOnly event"); 163 } 164 165 // .add() should return null and have no effect 166 var data = [["This is a plain string", "text/plain"], 167 ["This is <em>HTML!</em>", "text/html"], 168 ["http://www.mozilla.org/", "text/uri-list"], 169 ["this is some custom data", "custom-data"]]; 170 171 for (var i = 0; i < data.length; i++) { 172 is(dtList.add(data[i][0], data[i][1]), null, 173 ".add() should return null during a readOnly event"); 174 175 is(dtList.length, num, ".add() should have no effect during a readOnly event"); 176 } 177 178 // .add() with a file should return null and have no effect 179 var file = new File(['<a id="a"><b id="b">hey!</b></a>'], "myfile.html", 180 {type: "text/html"}); 181 is(dtList.add(file), null, ".add() with a file should return null during a readOnly event"); 182 is(dtList.length, num, ".add() should have no effect during a readOnly event"); 183 184 // We should be able to access the files 185 is(e.dataTransfer.files.length, 1, "Should be able to access files"); 186 ok(e.dataTransfer.files[0], "File should be the same file!"); 187 is(e.dataTransfer.items.length, 2, "Should be able to see there are 2 items"); 188 189 is(e.dataTransfer.items[0].kind, "file", "First item should be a file"); 190 is(e.dataTransfer.items[1].kind, "string", "Second item should be a string"); 191 192 is(e.dataTransfer.items[0].type, "text/html", "first item should be text/html"); 193 is(e.dataTransfer.items[1].type, "text/plain", "second item should be text/plain"); 194 195 ok(e.dataTransfer.items[0].getAsFile(), "Should be able to get file"); 196 e.dataTransfer.items[1].getAsString(function(s) { 197 getAsStringCalled++; 198 is(s, "this is some text", "Should provide the correct string"); 199 }); 200 } 201 202 synthesizeDrop(draggable, over, null, null); 203 204 // Wait for the getAsString callbacks to complete 205 await spin(); 206 is(getAsStringCalled, 2, "getAsString should be called twice"); 207 208 // Sanity-check to make sure that the events were actually run 209 is(dragstartFired, 1, "dragstart fired"); 210 is(dragenterFired, 1, "dragenter fired"); 211 is(dropFired, 1, "drop fired"); 212 }); 213 214 function expectError(fn, eid, testid) { 215 var error = ""; 216 try { 217 fn(); 218 } catch (ex) { 219 error = ex.name; 220 } 221 is(error, eid, testid + " causes exception " + eid); 222 } 223 224 function checkTypes(aExpectedList, aDtList, aTestid) { 225 is(aDtList.length, aExpectedList.length, aTestid + " length test"); 226 for (var i = 0; i < aExpectedList.length; i++) { 227 is(aDtList[i].type, aExpectedList[i], aTestid + " type " + i); 228 } 229 } 230 </script> 231 232 </body> 233 </html>