1<!DOCTYPE html> 2<meta charset=utf-8> 3<title>File constructor</title> 4<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-file"> 5<script src="/resources/testharness.js"></script> 6<script src="/resources/testharnessreport.js"></script> 7<div id="log"></div> 8<script> 9const to_string_obj = { toString: () => 'a string' }; 10const to_string_throws = { toString: () => { throw new Error('expected'); } }; 11 12test(function() { 13 assert_true("File" in window, "window should have a File property."); 14}, "File interface object exists"); 15 16test(t => { 17 assert_throws_js(TypeError, () => new File(), 18 'Bits argument is required'); 19 assert_throws_js(TypeError, () => new File([]), 20 'Name argument is required'); 21}, 'Required arguments'); 22 23function test_first_argument(arg1, expectedSize, testName) { 24 test(function() { 25 var file = new File(arg1, "dummy"); 26 assert_true(file instanceof File); 27 assert_equals(file.name, "dummy"); 28 assert_equals(file.size, expectedSize); 29 assert_equals(file.type, ""); 30 // assert_false(file.isClosed); XXX: File.isClosed doesn't seem to be implemented 31 assert_not_equals(file.lastModified, ""); 32 }, testName); 33} 34 35test_first_argument([], 0, "empty fileBits"); 36test_first_argument(["bits"], 4, "DOMString fileBits"); 37test_first_argument([""], 16, "Unicode DOMString fileBits"); 38test_first_argument([new String('string object')], 13, "String object fileBits"); 39test_first_argument([new Blob()], 0, "Empty Blob fileBits"); 40test_first_argument([new Blob(["bits"])], 4, "Blob fileBits"); 41test_first_argument([new File([], 'world.txt')], 0, "Empty File fileBits"); 42test_first_argument([new File(["bits"], 'world.txt')], 4, "File fileBits"); 43test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits"); 44test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits"); 45test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]), 46 new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits"); 47test_first_argument([12], 2, "Number in fileBits"); 48test_first_argument([[1,2,3]], 5, "Array in fileBits"); 49test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]" 50test_first_argument([document.body], 24, "HTMLBodyElement in fileBits"); // "[object HTMLBodyElement]" 51test_first_argument([to_string_obj], 8, "Object with toString in fileBits"); 52test_first_argument({[Symbol.iterator]() { 53 let i = 0; 54 return {next: () => [ 55 {done:false, value:'ab'}, 56 {done:false, value:'cde'}, 57 {done:true} 58 ][i++]}; 59}}, 5, 'Custom @@iterator'); 60 61[ 62 'hello', 63 0, 64 null 65].forEach(arg => { 66 test(t => { 67 assert_throws_js(TypeError, () => new File(arg, 'world.html'), 68 'Constructor should throw for invalid bits argument'); 69 }, `Invalid bits argument: ${JSON.stringify(arg)}`); 70}); 71 72test(t => { 73 assert_throws_js(Error, () => new File([to_string_throws], 'name.txt'), 74 'Constructor should propagate exceptions'); 75}, 'Bits argument: object that throws'); 76 77 78function test_second_argument(arg2, expectedFileName, testName) { 79 test(function() { 80 var file = new File(["bits"], arg2); 81 assert_true(file instanceof File); 82 assert_equals(file.name, expectedFileName); 83 }, testName); 84} 85 86test_second_argument("dummy", "dummy", "Using fileName"); 87test_second_argument("dummy/foo", "dummy/foo", 88 "No replacement when using special character in fileName"); 89test_second_argument(null, "null", "Using null fileName"); 90test_second_argument(1, "1", "Using number fileName"); 91test_second_argument('', '', "Using empty string fileName"); 92test_second_argument(document.body, '[object HTMLBodyElement]', "Using object fileName"); 93 94// testing the third argument 95[ 96 {type: 'text/plain', expected: 'text/plain'}, 97 {type: 'text/plain;charset=UTF-8', expected: 'text/plain;charset=utf-8'}, 98 {type: 'TEXT/PLAIN', expected: 'text/plain'}, 99 {type: '/', expected: ''}, 100 {type: 'ascii/nonprintable\u001F', expected: ''}, 101 {type: 'ascii/nonprintable\u007F', expected: ''}, 102 {type: 'nonascii\u00EE', expected: ''}, 103 {type: 'nonascii\u1234', expected: ''}, 104 {type: 'nonparsable', expected: 'nonparsable'} 105].forEach(testCase => { 106 test(t => { 107 var file = new File(["bits"], "dummy", { type: testCase.type}); 108 assert_true(file instanceof File); 109 assert_equals(file.type, testCase.expected); 110 }, `Using type in File constructor: ${testCase.type}`); 111}); 112test(function() { 113 var file = new File(["bits"], "dummy", { lastModified: 42 }); 114 assert_true(file instanceof File); 115 assert_equals(file.lastModified, 42); 116}, "Using lastModified"); 117test(function() { 118 var file = new File(["bits"], "dummy", { name: "foo" }); 119 assert_true(file instanceof File); 120 assert_equals(file.name, "dummy"); 121}, "Misusing name"); 122test(function() { 123 var file = new File(["bits"], "dummy", { unknownKey: "value" }); 124 assert_true(file instanceof File); 125 assert_equals(file.name, "dummy"); 126}, "Unknown properties are ignored"); 127 128[ 129 123, 130 123.4, 131 true, 132 'abc' 133].forEach(arg => { 134 test(t => { 135 assert_throws_js(TypeError, () => new File(['bits'], 'name.txt', arg), 136 'Constructor should throw for invalid property bag type'); 137 }, `Invalid property bag: ${JSON.stringify(arg)}`); 138}); 139 140[ 141 null, 142 undefined, 143 [1,2,3], 144 /regex/, 145 function() {} 146].forEach(arg => { 147 test(t => { 148 assert_equals(new File(['bits'], 'name.txt', arg).size, 4, 149 'Constructor should accept object-ish property bag type'); 150 }, `Unusual but valid property bag: ${arg}`); 151}); 152 153test(t => { 154 assert_throws_js(Error, 155 () => new File(['bits'], 'name.txt', {type: to_string_throws}), 156 'Constructor should propagate exceptions'); 157}, 'Property bag propagates exceptions'); 158 159</script> 160