Unreviewed. Update W3C WebDriver imported tests.
[WebKit-https.git] / WebDriverTests / imported / w3c / webdriver / tests / interaction / element_clear.py
1 import pytest
2
3 from tests.support.asserts import assert_error, assert_success
4 from tests.support.inline import inline
5
6
7 @pytest.fixture(scope="session")
8 def text_file(tmpdir_factory):
9     fh = tmpdir_factory.mktemp("tmp").join("hello.txt")
10     fh.write("hello")
11     return fh
12
13
14 def element_clear(session, element):
15     return session.transport.send("POST", "/session/%s/element/%s/clear" %
16                                   (session.session_id, element.id))
17
18
19 def test_closed_context(session, create_window):
20     new_window = create_window()
21     session.window_handle = new_window
22     session.url = inline("<input>")
23     element = session.find.css("input", all=False)
24     session.close()
25
26     response = element_clear(session, element)
27     assert_error(response, "no such window")
28
29
30 def test_connected_element(session):
31     session.url = inline("<input>")
32     element = session.find.css("input", all=False)
33
34     session.url = inline("<input>")
35     response = element_clear(session, element)
36     assert_error(response, "stale element reference")
37
38
39 def test_pointer_interactable(session):
40     session.url = inline("<input style='margin-left: -1000px' value=foobar>")
41     element = session.find.css("input", all=False)
42
43     response = element_clear(session, element)
44     assert_error(response, "element not interactable")
45
46
47 def test_keyboard_interactable(session):
48     session.url = inline("""
49         <input value=foobar>
50         <div></div>
51
52         <style>
53         div {
54           position: absolute;
55           background: blue;
56           top: 0;
57         }
58         </style>
59         """)
60     element = session.find.css("input", all=False)
61     assert element.property("value") == "foobar"
62
63     response = element_clear(session, element)
64     assert_success(response)
65     assert element.property("value") == ""
66
67
68 @pytest.mark.parametrize("type,value,default",
69                          [("number", "42", ""),
70                           ("range", "42", "50"),
71                           ("email", "foo@example.com", ""),
72                           ("password", "password", ""),
73                           ("search", "search", ""),
74                           ("tel", "999", ""),
75                           ("text", "text", ""),
76                           ("url", "https://example.com/", ""),
77                           ("color", "#ff0000", "#000000"),
78                           ("date", "2017-12-26", ""),
79                           ("datetime", "2017-12-26T19:48", ""),
80                           ("datetime-local", "2017-12-26T19:48", ""),
81                           ("time", "19:48", ""),
82                           ("month", "2017-11", ""),
83                           ("week", "2017-W52", "")])
84 def test_input(session, type, value, default):
85     session.url = inline("<input type=%s value='%s'>" % (type, value))
86     element = session.find.css("input", all=False)
87     assert element.property("value") == value
88
89     response = element_clear(session, element)
90     assert_success(response)
91     assert element.property("value") == default
92
93
94 @pytest.mark.parametrize("type",
95                          ["number",
96                           "range",
97                           "email",
98                           "password",
99                           "search",
100                           "tel",
101                           "text",
102                           "url",
103                           "color",
104                           "date",
105                           "datetime",
106                           "datetime-local",
107                           "time",
108                           "month",
109                           "week",
110                           "file"])
111 def test_input_disabled(session, type):
112     session.url = inline("<input type=%s disabled>" % type)
113     element = session.find.css("input", all=False)
114
115     response = element_clear(session, element)
116     assert_error(response, "invalid element state")
117
118
119 @pytest.mark.parametrize("type",
120                          ["number",
121                           "range",
122                           "email",
123                           "password",
124                           "search",
125                           "tel",
126                           "text",
127                           "url",
128                           "color",
129                           "date",
130                           "datetime",
131                           "datetime-local",
132                           "time",
133                           "month",
134                           "week",
135                           "file"])
136 def test_input_readonly(session, type):
137     session.url = inline("<input type=%s readonly>" % type)
138     element = session.find.css("input", all=False)
139
140     response = element_clear(session, element)
141     assert_error(response, "invalid element state")
142
143
144 def test_textarea(session):
145     session.url = inline("<textarea>foobar</textarea>")
146     element = session.find.css("textarea", all=False)
147     assert element.property("value") == "foobar"
148
149     response = element_clear(session, element)
150     assert_success(response)
151     assert element.property("value") == ""
152
153
154 def test_textarea_disabled(session):
155     session.url = inline("<textarea disabled></textarea>")
156     element = session.find.css("textarea", all=False)
157
158     response = element_clear(session, element)
159     assert_error(response, "invalid element state")
160
161
162 def test_textarea_readonly(session):
163     session.url = inline("<textarea readonly></textarea>")
164     element = session.find.css("textarea", all=False)
165
166     response = element_clear(session, element)
167     assert_error(response, "invalid element state")
168
169
170 def test_input_file(session, text_file):
171     session.url = inline("<input type=file>")
172     element = session.find.css("input", all=False)
173     element.send_keys(str(text_file))
174
175     response = element_clear(session, element)
176     assert_success(response)
177     assert element.property("value") == ""
178
179
180 def test_input_file_multiple(session, text_file):
181     session.url = inline("<input type=file multiple>")
182     element = session.find.css("input", all=False)
183     element.send_keys(str(text_file))
184     element.send_keys(str(text_file))
185
186     response = element_clear(session, element)
187     assert_success(response)
188     assert element.property("value") == ""
189
190
191 def test_select(session):
192     session.url = inline("""
193         <select disabled>
194           <option>foo
195         </select>
196         """)
197     select = session.find.css("select", all=False)
198     option = session.find.css("option", all=False)
199
200     response = element_clear(session, select)
201     assert_error(response, "invalid element state")
202     response = element_clear(session, option)
203     assert_error(response, "invalid element state")
204
205
206 def test_button(session):
207     session.url = inline("<button></button>")
208     button = session.find.css("button", all=False)
209
210     response = element_clear(session, button)
211     assert_error(response, "invalid element state")
212
213
214 def test_button_with_subtree(session):
215     """
216     Whilst an <input> is normally editable, the focusable area
217     where it is placed will default to the <button>.  I.e. if you
218     try to click <input> to focus it, you will hit the <button>.
219     """
220     session.url = inline("""
221         <button>
222           <input value=foobar>
223         </button>
224         """)
225     text_field = session.find.css("input", all=False)
226
227     response = element_clear(session, text_field)
228     assert_error(response, "element not interactable")
229
230
231 def test_contenteditable(session):
232     session.url = inline("<p contenteditable>foobar</p>")
233     element = session.find.css("p", all=False)
234     assert element.property("innerHTML") == "foobar"
235
236     response = element_clear(session, element)
237     assert_success(response)
238     assert element.property("innerHTML") == ""
239
240
241 def test_contenteditable_focus(session):
242     session.url = inline("""
243         <p contenteditable>foobar</p>
244
245         <script>
246         window.events = [];
247         let p = document.querySelector("p");
248         for (let ev of ["focus", "blur"]) {
249           p.addEventListener(ev, ({type}) => window.events.push(type));
250         }
251         </script>
252         """)
253     element = session.find.css("p", all=False)
254     assert element.property("innerHTML") == "foobar"
255
256     response = element_clear(session, element)
257     assert_success(response)
258     assert element.property("innerHTML") == ""
259     assert session.execute_script("return window.events") == ["focus", "blur"]
260
261
262 def test_designmode(session):
263     session.url = inline("foobar")
264     element = session.find.css("body", all=False)
265     assert element.property("innerHTML") == "foobar"
266     session.execute_script("document.designMode = 'on'")
267
268     response = element_clear(session, element)
269     assert_success(response)
270     assert element.property("innerHTML") == "<br>"
271
272
273 def test_resettable_element_focus(session):
274     session.url = inline("""
275         <input value="foobar">
276
277         <script>
278         window.events = [];
279         let input = document.querySelector("input");
280         for (let ev of ["focus", "blur"]) {
281           input.addEventListener(ev, ({type}) => window.events.push(type));
282         }
283         </script>
284         """)
285     element = session.find.css("input", all=False)
286     assert element.property("value") == "foobar"
287
288     response = element_clear(session, element)
289     assert_success(response)
290     assert element.property("value") == ""
291     assert session.execute_script("return window.events") == ["focus", "blur"]
292
293
294 def test_resettable_element_focus_when_empty(session):
295     session.url = inline("""
296         <input>
297
298         <script>
299         window.events = [];
300         let p = document.querySelector("input");
301         for (let ev of ["focus", "blur"]) {
302           p.addEventListener(ev, ({type}) => window.events.push(type));
303         }
304         </script>
305         """)
306     element = session.find.css("input", all=False)
307     assert element.property("value") == ""
308
309     response = element_clear(session, element)
310     assert_success(response)
311     assert element.property("value") == ""
312     assert session.execute_script("return window.events") == []
313
314
315 @pytest.mark.parametrize("type,invalid_value",
316                          [("number", "foo"),
317                           ("range", "foo"),
318                           ("email", "foo"),
319                           ("url", "foo"),
320                           ("color", "foo"),
321                           ("date", "foo"),
322                           ("datetime", "foo"),
323                           ("datetime-local", "foo"),
324                           ("time", "foo"),
325                           ("month", "foo"),
326                           ("week", "foo")])
327 def test_resettable_element_does_not_satisfy_validation_constraints(session, type, invalid_value):
328     """
329     Some UAs allow invalid input to certain types of constrained
330     form controls.  For example, Gecko allows non-valid characters
331     to be typed into <input type=number> but Chrome does not.
332     Since we want to test that Element Clear works for clearing the
333     invalid characters in these UAs, it is fine to skip this test
334     where UAs do not allow the element to not satisfy its constraints.
335     """
336     session.url = inline("<input type=%s>" % type)
337     element = session.find.css("input", all=False)
338
339     def is_valid(element):
340         return session.execute_script("""
341             let [input] = arguments;
342             return input.validity.valid;
343             """, args=(element,))
344
345     # value property does not get updated if the input is invalid
346     element.send_keys(invalid_value)
347
348     # UA does not allow invalid input for this form control type
349     if is_valid(element):
350         return
351
352     response = element_clear(session, element)
353     assert_success(response)
354     assert is_valid(element)
355
356
357 @pytest.mark.parametrize("type",
358                          ["checkbox",
359                           "radio",
360                           "hidden",
361                           "submit",
362                           "button",
363                           "image"])
364 def test_non_editable_inputs(session, type):
365     session.url = inline("<input type=%s>" % type)
366     element = session.find.css("input", all=False)
367
368     response = element_clear(session, element)
369     assert_error(response, "invalid element state")
370
371
372 def test_scroll_into_view(session):
373     session.url = inline("""
374         <input value=foobar>
375         <div style='height: 200vh; width: 5000vh'>
376         """)
377     element = session.find.css("input", all=False)
378     assert element.property("value") == "foobar"
379     assert session.execute_script("return window.scrollY") == 0
380
381     # scroll to the bottom right of the page
382     session.execute_script("""
383         let {scrollWidth, scrollHeight} = document.body;
384         window.scrollTo(scrollWidth, scrollHeight);
385         """)
386
387     # clear and scroll back to the top of the page
388     response = element_clear(session, element)
389     assert_success(response)
390     assert element.property("value") == ""
391
392     # check if element cleared is scrolled into view
393     rect = session.execute_script("""
394         let [input] = arguments;
395         return input.getBoundingClientRect();
396         """, args=(element,))
397     window = session.execute_script("""
398         let {innerHeight, innerWidth, pageXOffset, pageYOffset} = window;
399         return {innerHeight, innerWidth, pageXOffset, pageYOffset};
400         """)
401
402     assert rect["top"] < (window["innerHeight"] + window["pageYOffset"]) and \
403            rect["left"] < (window["innerWidth"] + window["pageXOffset"]) and \
404            (rect["top"] + element.rect["height"]) > window["pageYOffset"] and \
405            (rect["left"] + element.rect["width"]) > window["pageXOffset"]