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 5from __future__ import absolute_import, print_function 6 7import types 8 9import six 10from six.moves.urllib.parse import quote 11 12from marionette_driver.by import By 13from marionette_harness import MarionetteTestCase 14 15 16boolean_attributes = { 17 "audio": ["autoplay", "controls", "loop", "muted"], 18 "button": ["autofocus", "disabled", "formnovalidate"], 19 "details": ["open"], 20 "dialog": ["open"], 21 "fieldset": ["disabled"], 22 "form": ["novalidate"], 23 "iframe": ["allowfullscreen"], 24 "img": ["ismap"], 25 "input": [ 26 "autofocus", 27 "checked", 28 "disabled", 29 "formnovalidate", 30 "multiple", 31 "readonly", 32 "required", 33 ], 34 "menuitem": ["checked", "default", "disabled"], 35 "ol": ["reversed"], 36 "optgroup": ["disabled"], 37 "option": ["disabled", "selected"], 38 "script": ["async", "defer"], 39 "select": ["autofocus", "disabled", "multiple", "required"], 40 "textarea": ["autofocus", "disabled", "readonly", "required"], 41 "track": ["default"], 42 "video": ["autoplay", "controls", "loop", "muted"], 43} 44 45 46def inline(doc, doctype="html"): 47 if doctype == "html": 48 return "data:text/html;charset=utf-8,{}".format(quote(doc)) 49 elif doctype == "xhtml": 50 return "data:application/xhtml+xml,{}".format( 51 quote( 52 r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 53 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 54<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 55 <head> 56 <title>XHTML might be the future</title> 57 </head> 58 59 <body> 60 {} 61 </body> 62</html>""".format( 63 doc 64 ) 65 ) 66 ) 67 68 69attribute = inline("<input foo=bar>") 70input = inline("<input>") 71disabled = inline("<input disabled=baz>") 72check = inline("<input type=checkbox>") 73 74 75class TestIsElementEnabled(MarionetteTestCase): 76 def test_is_enabled(self): 77 test_html = self.marionette.absolute_url("test.html") 78 self.marionette.navigate(test_html) 79 l = self.marionette.find_element(By.NAME, "myCheckBox") 80 self.assertTrue(l.is_enabled()) 81 self.marionette.execute_script("arguments[0].disabled = true;", [l]) 82 self.assertFalse(l.is_enabled()) 83 84 85class TestIsElementDisplayed(MarionetteTestCase): 86 def test_is_displayed(self): 87 test_html = self.marionette.absolute_url("test.html") 88 self.marionette.navigate(test_html) 89 l = self.marionette.find_element(By.NAME, "myCheckBox") 90 self.assertTrue(l.is_displayed()) 91 self.marionette.execute_script("arguments[0].hidden = true;", [l]) 92 self.assertFalse(l.is_displayed()) 93 94 95class TestGetElementAttribute(MarionetteTestCase): 96 def test_normal_attribute(self): 97 self.marionette.navigate(inline("<p style=foo>")) 98 el = self.marionette.find_element(By.TAG_NAME, "p") 99 attr = el.get_attribute("style") 100 self.assertIsInstance(attr, six.string_types) 101 self.assertEqual("foo", attr) 102 103 def test_boolean_attributes(self): 104 for tag, attrs in six.iteritems(boolean_attributes): 105 for attr in attrs: 106 print("testing boolean attribute <{0} {1}>".format(tag, attr)) 107 doc = inline("<{0} {1}>".format(tag, attr)) 108 self.marionette.navigate(doc) 109 el = self.marionette.find_element(By.TAG_NAME, tag) 110 res = el.get_attribute(attr) 111 self.assertIsInstance(res, six.string_types) 112 self.assertEqual("true", res) 113 114 def test_global_boolean_attributes(self): 115 self.marionette.navigate(inline("<p hidden>foo")) 116 el = self.marionette.find_element(By.TAG_NAME, "p") 117 attr = el.get_attribute("hidden") 118 self.assertIsInstance(attr, six.string_types) 119 self.assertEqual("true", attr) 120 121 self.marionette.navigate(inline("<p>foo")) 122 el = self.marionette.find_element(By.TAG_NAME, "p") 123 attr = el.get_attribute("hidden") 124 self.assertIsNone(attr) 125 126 self.marionette.navigate(inline("<p itemscope>foo")) 127 el = self.marionette.find_element(By.TAG_NAME, "p") 128 attr = el.get_attribute("itemscope") 129 self.assertIsInstance(attr, six.string_types) 130 self.assertEqual("true", attr) 131 132 self.marionette.navigate(inline("<p>foo")) 133 el = self.marionette.find_element(By.TAG_NAME, "p") 134 attr = el.get_attribute("itemscope") 135 self.assertIsNone(attr) 136 137 # TODO(ato): Test for custom elements 138 139 def test_xhtml(self): 140 doc = inline('<p hidden="true">foo</p>', doctype="xhtml") 141 self.marionette.navigate(doc) 142 el = self.marionette.find_element(By.TAG_NAME, "p") 143 attr = el.get_attribute("hidden") 144 self.assertIsInstance(attr, six.string_types) 145 self.assertEqual("true", attr) 146 147 148class TestGetElementProperty(MarionetteTestCase): 149 def test_get(self): 150 self.marionette.navigate(disabled) 151 el = self.marionette.find_element(By.TAG_NAME, "input") 152 prop = el.get_property("disabled") 153 self.assertIsInstance(prop, bool) 154 self.assertTrue(prop) 155 156 def test_missing_property_returns_default(self): 157 self.marionette.navigate(input) 158 el = self.marionette.find_element(By.TAG_NAME, "input") 159 prop = el.get_property("checked") 160 self.assertIsInstance(prop, bool) 161 self.assertFalse(prop) 162 163 def test_attribute_not_returned(self): 164 self.marionette.navigate(attribute) 165 el = self.marionette.find_element(By.TAG_NAME, "input") 166 self.assertEqual(el.get_property("foo"), None) 167 168 def test_manipulated_element(self): 169 self.marionette.navigate(check) 170 el = self.marionette.find_element(By.TAG_NAME, "input") 171 self.assertEqual(el.get_property("checked"), False) 172 173 el.click() 174 self.assertEqual(el.get_property("checked"), True) 175 176 el.click() 177 self.assertEqual(el.get_property("checked"), False) 178