test_file_upload.py (5043B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 from tempfile import NamedTemporaryFile as tempfile 6 7 from urllib.parse import quote 8 9 from marionette_driver import By, errors, expected 10 from marionette_driver.wait import Wait 11 from marionette_harness import MarionetteTestCase 12 13 14 single = "data:text/html,{}".format(quote("<input type=file>")) 15 multiple = "data:text/html,{}".format(quote("<input type=file multiple>")) 16 upload = lambda url: "data:text/html,{}".format( 17 quote( 18 """ 19 <form action='{}' method=post enctype='multipart/form-data'> 20 <input type=file> 21 <input type=submit> 22 </form>""".format( 23 url 24 ) 25 ) 26 ) 27 28 29 class TestFileUpload(MarionetteTestCase): 30 def test_sets_one_file(self): 31 self.marionette.navigate(single) 32 input = self.input 33 34 exp = None 35 with tempfile() as f: 36 input.send_keys(f.name) 37 exp = [f.name] 38 39 files = self.get_file_names(input) 40 self.assertEqual(len(files), 1) 41 self.assertFileNamesEqual(files, exp) 42 43 def test_sets_multiple_files(self): 44 self.marionette.navigate(multiple) 45 input = self.input 46 47 exp = None 48 with tempfile() as a, tempfile() as b: 49 input.send_keys(a.name) 50 input.send_keys(b.name) 51 exp = [a.name, b.name] 52 53 files = self.get_file_names(input) 54 self.assertEqual(len(files), 2) 55 self.assertFileNamesEqual(files, exp) 56 57 def test_sets_multiple_indentical_files(self): 58 self.marionette.navigate(multiple) 59 input = self.input 60 61 exp = [] 62 with tempfile() as f: 63 input.send_keys(f.name) 64 input.send_keys(f.name) 65 exp = f.name 66 67 files = self.get_file_names(input) 68 self.assertEqual(len(files), 2) 69 self.assertFileNamesEqual(files, exp) 70 71 def test_clear_file(self): 72 self.marionette.navigate(single) 73 input = self.input 74 75 with tempfile() as f: 76 input.send_keys(f.name) 77 78 self.assertEqual(len(self.get_files(input)), 1) 79 input.clear() 80 self.assertEqual(len(self.get_files(input)), 0) 81 82 def test_clear_files(self): 83 self.marionette.navigate(multiple) 84 input = self.input 85 86 with tempfile() as a, tempfile() as b: 87 input.send_keys(a.name) 88 input.send_keys(b.name) 89 90 self.assertEqual(len(self.get_files(input)), 2) 91 input.clear() 92 self.assertEqual(len(self.get_files(input)), 0) 93 94 def test_illegal_file(self): 95 self.marionette.navigate(single) 96 with self.assertRaisesRegex(errors.MarionetteException, "File not found"): 97 self.input.send_keys("rochefort") 98 99 def test_upload(self): 100 self.marionette.navigate(upload(self.marionette.absolute_url("file_upload"))) 101 url = self.marionette.get_url() 102 103 with tempfile() as f: 104 f.write("camembert".encode()) 105 f.flush() 106 self.input.send_keys(f.name) 107 self.submit.click() 108 109 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 110 lambda m: m.get_url() != url, 111 message="URL didn't change after submitting a file upload", 112 ) 113 self.assertIn("multipart/form-data", self.body.text) 114 115 def test_change_event(self): 116 self.marionette.navigate(single) 117 self.marionette.execute_script( 118 """ 119 window.changeEvs = []; 120 let el = arguments[arguments.length - 1]; 121 el.addEventListener("change", ev => window.changeEvs.push(ev)); 122 console.log(window.changeEvs.length); 123 """, 124 script_args=(self.input,), 125 sandbox=None, 126 ) 127 128 with tempfile() as f: 129 self.input.send_keys(f.name) 130 131 nevs = self.marionette.execute_script( 132 "return window.changeEvs.length", sandbox=None 133 ) 134 self.assertEqual(1, nevs) 135 136 def find_inputs(self): 137 return self.marionette.find_elements(By.TAG_NAME, "input") 138 139 @property 140 def input(self): 141 return self.find_inputs()[0] 142 143 @property 144 def submit(self): 145 return self.find_inputs()[1] 146 147 @property 148 def body(self): 149 return Wait(self.marionette).until( 150 expected.element_present(By.TAG_NAME, "body") 151 ) 152 153 def get_file_names(self, el): 154 fl = self.get_files(el) 155 return [f["name"] for f in fl] 156 157 def get_files(self, el): 158 return self.marionette.execute_script( 159 "return arguments[0].files", script_args=[el] 160 ) 161 162 def assertFileNamesEqual(self, act, exp): 163 # File array returned from browser doesn't contain full path names, 164 # this cuts off the path of the expected files. 165 filenames = [f.rsplit("/", 0)[-1] for f in act] 166 self.assertListEqual(filenames, act)