Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/rb/spec/unit/selenium/webdriver/support/select_spec.rb
1865 views
1
# frozen_string_literal: true
2
3
# Licensed to the Software Freedom Conservancy (SFC) under one
4
# or more contributor license agreements. See the NOTICE file
5
# distributed with this work for additional information
6
# regarding copyright ownership. The SFC licenses this file
7
# to you under the Apache License, Version 2.0 (the
8
# "License"); you may not use this file except in compliance
9
# with the License. You may obtain a copy of the License at
10
#
11
# http://www.apache.org/licenses/LICENSE-2.0
12
#
13
# Unless required by applicable law or agreed to in writing,
14
# software distributed under the License is distributed on an
15
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
# KIND, either express or implied. See the License for the
17
# specific language governing permissions and limitations
18
# under the License.
19
20
require File.expand_path('../spec_helper', __dir__)
21
22
module Selenium
23
module WebDriver
24
module Support
25
describe Select do
26
let(:select) do
27
select_element = instance_double(Element, tag_name: 'select')
28
allow(select_element).to receive(:dom_attribute).with(:multiple)
29
select_element
30
end
31
32
let(:multi_select) do
33
select_element = instance_double(Element, tag_name: 'select')
34
allow(select_element).to receive(:dom_attribute).with(:multiple).and_return 'multiple'
35
select_element
36
end
37
38
it 'raises ArgumentError if passed a non-select Element' do
39
link = instance_double(Element, tag_name: 'a')
40
41
expect { described_class.new link }.to raise_error(ArgumentError)
42
end
43
44
it 'indicates whether a select is multiple correctly' do
45
selects = Array.new(4) { instance_double(Element, tag_name: 'select') }
46
47
allow(selects[0]).to receive(:dom_attribute).with(:multiple).and_return('false')
48
allow(selects[1]).to receive(:dom_attribute).with(:multiple).and_return(nil)
49
allow(selects[2]).to receive(:dom_attribute).with(:multiple).and_return('true')
50
allow(selects[3]).to receive(:dom_attribute).with(:multiple).and_return('multiple')
51
52
expect(described_class.new(selects[0])).not_to be_multiple
53
expect(described_class.new(selects[1])).not_to be_multiple
54
expect(described_class.new(selects[2])).to be_multiple
55
expect(described_class.new(selects[3])).to be_multiple
56
end
57
58
it 'returns all options' do
59
options = []
60
allow(multi_select).to receive(:find_elements).and_return(options)
61
62
expect(described_class.new(multi_select).options).to eql(options)
63
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
64
end
65
66
it 'returns all selected options' do
67
bad_option = instance_double(Element, selected?: false)
68
good_option = instance_double(Element, selected?: true)
69
allow(multi_select).to receive(:find_elements).and_return([bad_option, good_option])
70
71
opts = described_class.new(multi_select).selected_options
72
73
expect(opts.size).to eq(1)
74
expect(opts.first).to eq(good_option)
75
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
76
end
77
78
it 'returns the first selected option' do
79
first_option = instance_double(Element, selected?: true)
80
second_option = instance_double(Element, selected?: true)
81
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
82
83
option = described_class.new(multi_select).first_selected_option
84
expect(option).to eq(first_option)
85
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
86
end
87
88
it 'raises a NoSuchElementError if nothing is selected' do
89
option = instance_double(Element, selected?: false)
90
allow(multi_select).to receive(:find_elements).and_return([option])
91
92
expect { described_class.new(multi_select).first_selected_option }.to raise_error(Error::NoSuchElementError)
93
end
94
95
it 'allows options to be selected by visible text' do
96
option = instance_double(Element, selected?: false, enabled?: true, click: nil)
97
allow(multi_select).to receive(:find_elements).and_return([option])
98
99
described_class.new(multi_select).select_by(:text, 'fish')
100
expect(option).to have_received(:click)
101
expect(multi_select).to have_received(:find_elements).with(xpath: './/option[normalize-space(.) = "fish"]')
102
end
103
104
it 'allows options to be selected by index' do
105
first_option = instance_double(Element, selected?: true, enabled?: true, click: nil)
106
second_option = instance_double(Element, selected?: false, enabled?: true, click: nil)
107
108
allow(first_option).to receive(:property).with(:index).and_return 0
109
allow(second_option).to receive(:property).with(:index).and_return 1
110
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
111
112
described_class.new(multi_select).select_by(:index, 1)
113
expect(first_option).to have_received(:property).with(:index)
114
expect(second_option).to have_received(:property).with(:index)
115
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
116
expect(first_option).not_to have_received(:click)
117
expect(second_option).to have_received(:click).once
118
end
119
120
it 'allows options to be selected by returned value' do
121
first_option = instance_double(Element, selected?: false, enabled?: true, click: nil)
122
allow(multi_select).to receive(:find_elements).and_return([first_option])
123
124
described_class.new(multi_select).select_by(:value, 'b')
125
126
expect(multi_select).to have_received(:find_elements).with(xpath: './/option[@value = "b"]')
127
expect(first_option).to have_received(:click).once
128
expect(multi_select).to have_received(:find_elements).with(xpath: './/option[@value = "b"]')
129
end
130
131
it 'can deselect all when select supports multiple selections' do
132
first_option = instance_double(Element, selected?: true, click: nil)
133
second_option = instance_double(Element, selected?: false, click: nil)
134
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
135
136
described_class.new(multi_select).deselect_all
137
138
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
139
expect(first_option).to have_received(:click).once
140
expect(second_option).not_to have_received(:click)
141
end
142
143
it 'can not deselect all when select does not support multiple selections' do
144
expect { described_class.new(select).deselect_all }.to raise_error(Error::UnsupportedOperationError)
145
end
146
147
it 'can deselect options by visible text' do
148
first_option = instance_double(Element, selected?: true, click: nil)
149
second_option = instance_double(Element, selected?: false, click: nil)
150
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
151
152
described_class.new(multi_select).deselect_by(:text, 'b')
153
154
expect(multi_select).to have_received(:find_elements).with(xpath: './/option[normalize-space(.) = "b"]')
155
expect(first_option).to have_received(:click).once
156
expect(second_option).not_to have_received(:click)
157
end
158
159
it 'can deselect options by index' do
160
first_option = instance_double(Element, selected?: true, click: nil)
161
second_option = instance_double(Element, click: nil)
162
163
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
164
allow(first_option).to receive(:property).with(:index).and_return(2)
165
allow(second_option).to receive(:property).with(:index).and_return(1)
166
167
described_class.new(multi_select).deselect_by(:index, 2)
168
169
expect(first_option).to have_received(:click).once
170
expect(second_option).not_to have_received(:click)
171
expect(multi_select).to have_received(:find_elements).with(tag_name: 'option')
172
end
173
174
it 'can deselect options by returned value' do
175
first_option = instance_double(Element, selected?: true, click: nil)
176
second_option = instance_double(Element, selected?: false, click: nil)
177
allow(multi_select).to receive(:find_elements).and_return([first_option, second_option])
178
179
described_class.new(multi_select).deselect_by(:value, 'b')
180
181
expect(first_option).to have_received(:click).once
182
expect(second_option).not_to have_received(:click)
183
expect(multi_select).to have_received(:find_elements).with(xpath: './/option[@value = "b"]')
184
end
185
186
it 'falls back to slow lookups when "get by visible text fails" and there is a space' do
187
first_option = instance_double(Element, selected?: false, enabled?: true, text: 'foo bar', click: nil)
188
allow(select).to receive(:find_elements).and_return([], [first_option])
189
190
described_class.new(select).select_by(:text, 'foo bar')
191
192
expect(first_option).to have_received(:click).once
193
expect(select).to have_received(:find_elements).with(xpath: './/option[normalize-space(.) = "foo bar"]').once
194
expect(select).to have_received(:find_elements).with(xpath: './/option[contains(., "foo")]').once
195
end
196
197
it 'raises NoSuchElementError if there are no selects to select' do
198
allow(select).to receive(:find_elements).and_return []
199
200
select_element = described_class.new select
201
202
expect { select_element.select_by :index, 12 }.to raise_error(Error::NoSuchElementError)
203
expect { select_element.select_by :value, 'not there' }.to raise_error(Error::NoSuchElementError)
204
expect { select_element.select_by :text, 'also not there' }.to raise_error(Error::NoSuchElementError)
205
end
206
207
it 'raises NoSuchElementError if there are no selects to deselect' do
208
allow(multi_select).to receive(:find_elements).and_return []
209
210
select_element = described_class.new multi_select
211
212
expect { select_element.deselect_by :index, 12 }.to raise_error(Error::NoSuchElementError)
213
expect { select_element.deselect_by :value, 'not there' }.to raise_error(Error::NoSuchElementError)
214
expect { select_element.deselect_by :text, 'also not there' }.to raise_error(Error::NoSuchElementError)
215
end
216
217
it 'raises UnsupportedOperationError if trying to deselect options in non-multiselect' do
218
select_element = described_class.new select
219
220
expect { select_element.deselect_by :index, 0 }.to raise_error(Error::UnsupportedOperationError)
221
expect { select_element.deselect_by :value, 'not there' }.to raise_error(Error::UnsupportedOperationError)
222
expect { select_element.deselect_by :text, 'also not there' }.to raise_error(Error::UnsupportedOperationError)
223
end
224
end # Select
225
226
describe Escaper do
227
it 'converts an unquoted string into one with quotes' do
228
expect(described_class.escape('abc')).to eq('"abc"')
229
expect(described_class.escape('abc aqewqqw')).to eq('"abc aqewqqw"')
230
expect(described_class.escape('')).to eq('""')
231
expect(described_class.escape(' ')).to eq('" "')
232
expect(described_class.escape(' abc ')).to eq('" abc "')
233
end
234
235
it 'double quotes a string that contains a single quote' do
236
expect(described_class.escape("f'oo")).to eq(%("f'oo"))
237
end
238
239
it 'single quotes a string that contains a double quote' do
240
expect(described_class.escape('f"oo')).to eq(%('f"oo'))
241
end
242
243
it 'provides concatenated strings when string to escape contains both single and double quotes' do
244
expect(described_class.escape(%(f"o'o))).to eq(%{concat("f", '"', "o'o")})
245
end
246
247
it 'provides concatenated strings when string ends with quote' do
248
expect(described_class.escape(%('"))).to eq(%{concat("'", '"')})
249
end
250
end
251
end # Support
252
end # WebDriver
253
end # Selenium
254
255