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
5import urllib
6
7from marionette_driver.by import By
8
9from marionette_harness import MarionetteTestCase
10
11
12def inline(doc):
13    return "data:text/html;charset=utf-8,{}".format(urllib.quote(doc))
14
15
16class SelectTestCase(MarionetteTestCase):
17    def assertSelected(self, option_element):
18        self.assertTrue(option_element.is_selected(), "<option> element not selected")
19        self.assertTrue(self.marionette.execute_script(
20            "return arguments[0].selected", script_args=[option_element], sandbox=None),
21            "<option> selected attribute not updated")
22
23    def assertNotSelected(self, option_element):
24        self.assertFalse(option_element.is_selected(), "<option> is selected")
25        self.assertFalse(self.marionette.execute_script(
26            "return arguments[0].selected", script_args=[option_element], sandbox=None),
27            "<option> selected attribute not updated")
28
29
30class TestSelect(SelectTestCase):
31    def test_single(self):
32        self.marionette.navigate(inline("""
33            <select>
34              <option>first
35              <option>second
36            </select>"""))
37        select = self.marionette.find_element(By.TAG_NAME, "select")
38        options = self.marionette.find_elements(By.TAG_NAME, "option")
39
40        self.assertSelected(options[0])
41        options[1].click()
42        self.assertSelected(options[1])
43
44    def test_deselect(self):
45        self.marionette.navigate(inline("""
46          <select>
47            <option>first
48            <option>second
49            <option>third
50          </select>"""))
51        select = self.marionette.find_element(By.TAG_NAME, "select")
52        options = self.marionette.find_elements(By.TAG_NAME, "option")
53
54        options[0].click()
55        self.assertSelected(options[0])
56        options[1].click()
57        self.assertSelected(options[1])
58        options[2].click()
59        self.assertSelected(options[2])
60        options[0].click()
61        self.assertSelected(options[0])
62
63    def test_out_of_view(self):
64        self.marionette.navigate(inline("""
65          <select>
66            <option>1
67            <option>2
68            <option>3
69            <option>4
70            <option>5
71            <option>6
72            <option>7
73            <option>8
74            <option>9
75            <option>10
76            <option>11
77            <option>12
78            <option>13
79            <option>14
80            <option>15
81            <option>16
82            <option>17
83            <option>18
84            <option>19
85            <option>20
86          </select>"""))
87        select = self.marionette.find_element(By.TAG_NAME, "select")
88        options = self.marionette.find_elements(By.TAG_NAME, "option")
89
90        options[14].click()
91        self.assertSelected(options[14])
92
93
94class TestSelectMultiple(SelectTestCase):
95    def test_single(self):
96        self.marionette.navigate(inline("<select multiple> <option>first </select>"))
97        option = self.marionette.find_element(By.TAG_NAME, "option")
98        option.click()
99        self.assertSelected(option)
100
101    def test_multiple(self):
102        self.marionette.navigate(inline("""
103          <select multiple>
104            <option>first
105            <option>second
106            <option>third
107          </select>"""))
108        select = self.marionette.find_element(By.TAG_NAME, "select")
109        options = select.find_elements(By.TAG_NAME, "option")
110
111        options[1].click()
112        self.assertSelected(options[1])
113
114        options[2].click()
115        self.assertSelected(options[2])
116        self.assertSelected(options[1])
117
118    def test_deselect_selected(self):
119        self.marionette.navigate(inline("<select multiple> <option>first </select>"))
120        option = self.marionette.find_element(By.TAG_NAME, "option")
121        option.click()
122        self.assertSelected(option)
123        option.click()
124        self.assertNotSelected(option)
125
126    def test_deselect_preselected(self):
127        self.marionette.navigate(inline("""
128          <select multiple>
129            <option selected>first
130          </select>"""))
131        option = self.marionette.find_element(By.TAG_NAME, "option")
132        self.assertSelected(option)
133        option.click()
134        self.assertNotSelected(option)
135
136    def test_out_of_view(self):
137        self.marionette.navigate(inline("""
138          <select multiple>
139            <option>1
140            <option>2
141            <option>3
142            <option>4
143            <option>5
144            <option>6
145            <option>7
146            <option>8
147            <option>9
148            <option>10
149            <option>11
150            <option>12
151            <option>13
152            <option>14
153            <option>15
154            <option>16
155            <option>17
156            <option>18
157            <option>19
158            <option>20
159          </select>"""))
160        select = self.marionette.find_element(By.TAG_NAME, "select")
161        options = self.marionette.find_elements(By.TAG_NAME, "option")
162
163        options[-1].click()
164        self.assertSelected(options[-1])
165