selwet 0.0.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/selwet.rb +452 -896
  3. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc3ec7997b98a5c664f7d89b93934c83a6b1974a
4
- data.tar.gz: 270efcc87c357852ede662c652e14eb32636c8bf
3
+ metadata.gz: 7579dfc91aa79cd2d24639fced1ca7aba474cd84
4
+ data.tar.gz: cd0889c3d291b4a51bcdfd0508d75cd4c6f28b2b
5
5
  SHA512:
6
- metadata.gz: 660fa083b776931dc94d5b84d57a0e86bb42ddca187de4e7b0abf730cf5bf6d9388d7aed8bbc75a21e61b78895f1227d9689fa194859504bc90e6f8b23a9ea0f
7
- data.tar.gz: 85f054d4e39d3510368114b62b52bc7245d80b803e8776ca6625319d3ef9077f8d7240a96f12d4f9e887278dfa6769370ab86e5014dad9c4a409f63b4ac1c7c3
6
+ metadata.gz: c74973d8e71021f9e088599eae6ae8ed487cc4a27c2e2ccb51b58b1c2f648677b357ff9d92b6a20d350ebfecb9ff2038e53d61319ea4e06860b564b7c86daeaf
7
+ data.tar.gz: d2805aecb6db3c397c3255580c4ee4bb653ec8677cbcc57f523a3afdf6091b1cc097281f3eb655bfaac844b0a17518038ae70f341a5721c124825fa1d6bffcc9
data/lib/selwet.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  require 'selenium-webdriver'
4
4
  require 'test-unit'
5
5
  require 'shoulda-context'
6
- #Модуль SelWeT (Selenium Web Test) позволяет тестировать веб-страницы в одном, или нескольких браузерах. Если тестирование производится в нескольких браузерах, то оно проводится параллельно.
6
+ #SelWeT (Selenium Web Test) - гем для веб тестирования.
7
7
  module SelWeT
8
- #Класс Unit содержит методы для проверки элементов страницы, получения их текстового содержимого и значения поля href для ссылок, заполнения полей, select-ов и форм, указания файлов для загрузки, кликов по элементам и кнопкам алерта, проверки статуса для radio и checkbox, перехода на другую страницу, обновления страницы, проверки текущего URL, открытие ссылки в новом окне, смены и закрытия окна, создания скриншотов.
9
- #
8
+ #Класс Unit содержит необходимый набор методов для взаимодействия с браузером.
10
9
  #Тесты пишутся с использованием shoulda-context.
11
10
  #@example
12
11
  # #!/usr/bin/env ruby
@@ -15,192 +14,80 @@ module SelWeT
15
14
  #
16
15
  # class SelWeT::Unit
17
16
  #
18
- # set_browsers [:firefox, :chrome]
17
+ # set_browser :firefox
19
18
  # set_selenium_server_url 'http://127.0.0.1:4444/wd/hub'
20
19
  #
21
20
  # context "Example" do
22
- # should "About Us" do
21
+ #
22
+ # should "open page 'About Us'" do
23
23
  # Unit.go_to "http://inventos.ru/"
24
24
  # Unit.click '#menu-item-3795 a'
25
- # status, error = Unit.check_location 'http://inventos.ru/about/#top'
26
- # assert_equal true, status, error
25
+ # current_location = Unit.get_location
26
+ # assert_equal 'http://inventos.ru/about/#top', current_location, 'Invalid location!'
27
27
  # end
28
+ #
28
29
  # end
29
30
  #
30
31
  # end
31
- class Unit < Test::Unit::TestCase
32
- include SelWeT
33
- private
34
- @@url_selenium = nil
35
- @@start_url = nil
36
- @@browsers = nil
37
- @@opened_window = {}
38
- @@win_num = 0
32
+ class Unit < Test::Unit::TestCase
33
+
34
+ include SelWeT
35
+
36
+ private
39
37
 
40
- class << self
41
- #Запускает браузеры перед выполнением тестов.
42
- #Выполняется автоматически непосредственно перед запуском тестов.
43
- def startup
44
- @@driver = {}
45
- url = nil
46
- unless @@url_selenium
47
- puts 'URL for selenium server not specified!'
48
- exit 1
49
- else
50
- url = @@url_selenium
51
- end
52
- if @@browsers.nil?
53
- puts 'Browsers not specified!'
54
- exit 1
55
- end
56
- begin
57
- @@browsers.each do |browser|
58
- if [:firefox, :chrome, :ie, :safari].include? browser
59
- @@driver[browser.to_s] = Selenium::WebDriver.for(:remote, :desired_capabilities => browser, :url => url)
60
- @@driver[browser.to_s].manage.timeouts.implicit_wait = 15
61
- @@driver[browser.to_s].manage.timeouts.script_timeout = 15
62
- @@driver[browser.to_s].manage.timeouts.page_load = 15
63
- @@driver[browser.to_s].manage.window.maximize
64
- else
65
- puts "Bad browser #{browser}"
66
- end
67
- end
68
- rescue Exception => e
69
- puts "ERROR: #{e.to_s}"
70
- exit 1
71
- end
72
- if @@start_url
73
- go_to @@start_url
74
- end
75
- end
76
- #Закрывает все используемые браузеры после выполнения всех тестов.
77
- #Выполняется автоматически.
78
- def shutdown
79
- @@driver.each do |name, driver|
80
- begin
81
- driver.close
82
- driver.quit
83
- rescue
84
- puts 'Browser '+name+' not closed ...'
85
- end
86
- end
38
+ @@server_url = nil
39
+ @@timewait = 5
40
+ @@pageload_timewait = 5
41
+ @@browser = nil
42
+ @@handles = {}
43
+
44
+ class Error < RuntimeError
87
45
  end
88
- #Устанавливает URL Selenium Server. Необходимо использовать перед блоками тестов.
89
- #
90
- #@param url [String] URL запущенного Selenium Server
91
- #@example
92
- # class SelWeT::Unit
93
- # set_browsers [:firefox, :chrome]
94
- # set_selenium_server_url "http://localhost:4444/wd/hub"
95
- # ...
96
- def set_selenium_server_url url
97
- @@url_selenium = url
98
- end
99
- #Устанавливает стартовую страницу при запуске браузеров. Использовать только перед блоками тестов.
100
- #@param url [String] URL тестируемого сайта
101
- #@example
102
- # class SelWeT::Unit
103
- # set_browsers [:firefox, :chrome]
104
- # set_selenium_server_url "http://localhost:4444/wd/hub"
105
- # open_link "http://inventos.ru/"
106
- # ...
107
- def open_link url
108
- @@start_url = url
46
+
47
+ class ArgumentValueError < Error
109
48
  end
110
- #Устанавливает используемые для тестирования браузеры. Необходимо использовать перед блоками тестов.
111
- #@param params [Array] массив, содержащий одно или несколько из следующий значений: :firefox, :chrome, :ie, :safari. Для :chrome и :ie Selenium Server следует запускать с соответствующими драйверами.
112
- #@example
113
- # class SelWeT::Unit
114
- # set_browsers [:firefox, :chrome]
115
- # ...
116
- def set_browsers params
117
- @@browsers = params
49
+
50
+ class ElementIsMissingError < Error
118
51
  end
119
- #Переход по ссылке. Используется только в блоках should или setup
120
- #@param url [String] ссылка, по которой необходимо перейти.
52
+
53
+ class << self
54
+ #Кликает на кнопку 'Cancel' в окне алерта.
121
55
  #@example
122
56
  # class SelWeT::Unit
123
57
  #
124
- # set_browsers [:firefox, :chrome]
125
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
126
- # @@somePage = 'http://inventos.ru/produkty/#top'
127
- #
128
- # context "Example" do
129
- #
130
- # setup do
131
- # Unit.go_to @@somePage
132
- # end
133
58
  # ...
134
- #@see refresh
135
- def go_to url
136
- threads = []
137
- @@driver.each do |name, driver|
138
- threads << Thread.new do
139
- driver.navigate.to url
140
- end
141
- end
142
- threads.each(&:join)
143
- end
144
- #Переключиться на iframe. Используется только в блоках should или setup. Для дальнейшего взаимодействия с основной страницей необходимо выполнить {to_page}.
145
- #@param selector [String] css селектор на нужный iframe.
146
- #@example
147
- # class SelWeT::Unit
148
- #
149
- # ...
150
59
  #
151
60
  # context "Example" do
152
61
  #
153
- # should 'Show popup' do
154
- # Unit.to_frame 'iframe#frame1'
62
+ # should "TODO something" do
63
+ # ...
64
+ # Unit.alert_cancel
155
65
  # ...
156
- #@see to_page
157
- def to_frame selector
158
- threads = []
159
- status, message, tags = get_tag selector
160
- unless status
161
- return false, "to_frame: "+message
162
- end
163
- bad_values = []
164
- tags.each do |name, tag|
165
- if tag != 'iframe'
166
- bad_values << name +" : "+tag
167
- end
168
- end
169
- if bad_values.size != 0
170
- return false, "to_frame: #{bad_values.join(", ")} - It is not 'iframe'! "
171
- end
172
- @@driver.each do |name, driver|
173
- threads << Thread.new do
174
- element = driver.find_element(:css => selector)
175
- driver.action.move_to(element).perform
176
- driver.switch_to.frame element
177
- end
66
+ #@see click
67
+ #@see alert_ok
68
+ def alert_cancel
69
+ @@driver.switch_to.alert.dismiss
178
70
  end
179
- threads.each(&:join)
180
- return true
181
- end
182
- #Очистить кэш браузера
71
+ #Кликает на кнопку 'Ok' в окне алерта.
183
72
  #@example
184
73
  # class SelWeT::Unit
185
74
  #
186
- # ...
75
+ # ...
187
76
  #
188
77
  # context "Example" do
189
78
  #
190
- # should 'Do something' do
79
+ # should "TODO something" do
191
80
  # ...
192
- # Unit.clear_cache
81
+ # Unit.alert_ok
193
82
  # ...
194
- def clear_cache
195
- threads = []
196
- @@driver.each do |name, driver|
197
- threads << Thread.new do
198
- driver.manage.delete_all_cookies
83
+ #@see click
84
+ #@see alert_cancel
85
+ def alert_ok
86
+ @@driver.switch_to.alert.accept
199
87
  end
200
- end
201
- threads.each(&:join)
202
- end
203
- #Переключиться на основную страницу. Используется только в блоках should или setup.
88
+ #Возвращает состояние для radio и checkbox.
89
+ # @param selector [String] css селектор
90
+ # @return [FalseClass/TrueClass] checked ~ true, unchecked ~ false
204
91
  #@example
205
92
  # class SelWeT::Unit
206
93
  #
@@ -208,832 +95,501 @@ class Unit < Test::Unit::TestCase
208
95
  #
209
96
  # context "Example" do
210
97
  #
211
- # should 'Show popup' do
98
+ # should 'TODO something' do
99
+ # Unit.go_to 'http://some_page.com/
212
100
  # ...
213
- # Unit.to_page
101
+ # status = Unit.checked?(#my_checkbox_id')
214
102
  # ...
215
- #@see to_frame
216
- def to_page
217
- threads = []
218
- @@driver.each do |name, driver|
219
- threads << Thread.new do
220
- driver.switch_to.default_content
103
+ def checked? selector
104
+ raise(ArgumentValueError, "Invalid value of argument 'selector'") unless selector.class == String
105
+ if check_element(selector)
106
+ element = @@driver.find_element(:css => selector)
107
+ raise "Element #{selector} is not a checkbox/radio" unless ['radio', 'checkbox'].include?(element.tag_name)
108
+ raise "Element #{selector} not displayed" unless element.displayed?
109
+ return element.selected?.inspect
110
+ else
111
+ raise(ElementIsMissingError, "Element #{selector} is missing")
221
112
  end
222
113
  end
223
- threads.each(&:join)
224
- end
225
- #Выбирает элементы в select. Используется только в блоках should или setup. Работает как с обычными select, так и с select с множественным выбором. Если для select с множественным выбором не указать аргумент items, то выделение будет снято со всех option.
226
- # @param selector [String] css селектор select.
227
- # @param items [Array] массив значений, которые необходимо выбрать.
228
- #@example
229
- # class SelWeT::Unit
230
- #
231
- # ...
232
- #
233
- # context "Example" do
234
- #
235
- # should "TODO something" do
236
- # Unit.set_select_items 'select[name="some_name"]', ['value 1', 'value2']
237
- # ...
238
- def set_select_items selector, items = nil
239
- threads = []
240
- status = true
241
- errors = []
242
- @@driver.each do |name, driver|
243
- threads << Thread.new do
244
- thread_status = true
245
- begin
246
- element = driver.find_element(:css => selector)
247
- rescue Exception => e
248
- errors << name+' : Bad selector : '+selector
249
- thread_status = false
250
- status = false
251
- end
252
- if thread_status
253
- unless element.tag_name == 'select'
254
- status = false
255
- errors << "#{name} - set_select_items using only for select!"
256
- else
257
- option = Selenium::WebDriver::Support::Select.new(element)
258
- if option.multiple?
259
- option.deselect_all
260
- if items
261
- options = element.find_elements(:css => 'option')
262
- options.each do |item|
263
- if items.include? item.text
264
- items.delete item.text
265
- driver.action.key_down(:shift).click(item).key_up(:shift).perform
266
- end
267
- end
268
- if items.size > 0
269
- status = false
270
- errors << "set_select_items: Some passed option values were not found (#{name}): "+items.join(' ')
271
- end
272
- end
273
- else
274
- if items
275
- if items.size == 1
276
- begin
277
- option.select_by(:text, items[0])
278
- rescue
279
- status = false
280
- errors << "set_select_items: Option '#{items}' does not exist!"
281
- end
282
- else
283
- status = false
284
- errors << "set_select_items: '#{selector}' is not multiple! You must pass a single value."
285
- end
286
- end
287
- end
288
- end
289
- end
290
- end
114
+ #Проверяет наличие элемента на странице. Если нужно получить количество элементов, то в качестве второго аргумента следует передать true.
115
+ #@param selector [String] css селектор элемент
116
+ #@param num [FalseClass/TrueClass]
117
+ #@return [FalseClass/TrueClass, Fixnum] первое значение - результат проверки наличия элемента, второе - число элементов (возвращается, если агрумент num имеет значение true)
118
+ #@example
119
+ # context "Example" do
120
+ #
121
+ # should "TODO something" do
122
+ # ...
123
+ # assert_equal true, Unit.check_element 'a.menu'
124
+ # end
125
+ # ...
126
+ def check_element selector, num = nil
127
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
128
+ raise(ArgumentValueError, "Invalid value \"#{num}\" of argument 'num'") unless [FalseClass, TrueClass, NilClass].include?(num.class)
129
+ wait = Selenium::WebDriver::Wait.new(:timeout => @@timewait)
130
+ begin
131
+ wait.until { @@driver.find_element(:css => selector) }
132
+ rescue Selenium::WebDriver::Error::TimeOutError
133
+ return false
291
134
  end
292
- threads.each(&:join)
293
- return [status, errors.uniq.join("\n")]
294
- end
295
- #Кликает по элементу. Используется только в блоках should или setup. Селектор должен указывать только на один конкретный элемент.
296
- #@param selector [String] селектор элемента
297
- #@param browserName [Symbol] используется, если в разных браузерах нужно кликнуть на разные элементы. Принимает одно из следующих значений: :firefox, :chrome, :ie, :safari
298
- #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
135
+ if num
136
+ return true, @@driver.find_elements(:css => selector).size
137
+ else
138
+ return true
139
+ end
140
+ end
141
+ #Очистить кэш браузера
142
+ def clear_cache
143
+ @@driver.manage.delete_all_cookies
144
+ end
145
+ #Кликнуть на элемент.
146
+ #@param selector [String] css селектор элемента
299
147
  #@example
300
- # class SelWeT::Unit
301
- #
302
- # ...
303
- #
304
- # context "Example" do
148
+ # context "Example" do
305
149
  #
306
- # should "TODO something" do
307
- # ...
308
- # status, error = Unit.click 'input[type="submit"]'
150
+ # should "TODO something" do
309
151
  # ...
152
+ # Unit.click 'input[type="submit"]'
153
+ # ...
310
154
  #@see alert_ok
311
155
  #@see alert_cancel
312
- def click selector, browserName = nil
313
- threads = []
314
- status = true
315
- @@driver.each do |name, driver|
316
- if browserName.nil? or name == browserName.to_s
317
- threads << Thread.new do
318
- begin
319
- element = driver.find_element(:css => selector)
320
- wait = Selenium::WebDriver::Wait.new(:timeout => 15)
321
- wait.until { driver.find_element(:css => selector).displayed? }
322
- driver.action.move_to(element).perform
323
- element.click
324
- rescue Exception => e
325
- status = false
326
- end
327
- end
156
+ def click selector, desc = nil
157
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
158
+ raise(ArgumentValueError, "Invalid value \"#{desc}\" of argument 'desc'") unless [String, NilClass].include?(desc.class)
159
+ if check_element(selector)
160
+ element = @@driver.find_element(:css => selector)
161
+ raise "Element \"#{selector}\" is not displayed!" unless element.displayed?
162
+ element.click
163
+ else
164
+ raise(ElementIsMissingError, desc ? "Element #{desc} is missing" :"Element #{selector} is missing")
328
165
  end
329
166
  end
330
- threads.each(&:join)
331
- if status
332
- return [true, ""]
333
- else
334
- return [false, "click: Bad selector : #{selector}"]
335
- end
336
- end
337
- #Кликает на кнопку 'Ok' в окне алерта. Используется только в блоках should или setup.
338
- #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
167
+ #Закрыть окно с номером num. Окна нумируются в порядке их открытия. Нумирация начинается с 0. Если необходимо закрыть текущее окно, то перед закрытием необходимо переключиться на другое окно. После закрытия окна происходить их переупорядочивание. Так, например, если было закрыто первое окно (num = 0), то второе окно станет первым (было num = 1, стало num = 0) и т.д.
168
+ #@param num [Fixnum] номер окна
339
169
  #@example
340
- # class SelWeT::Unit
341
- #
342
- # ...
343
- #
344
- # context "Example" do
345
- #
346
- # should "TODO something" do
347
- # ...
348
- # Unit.alert_ok
349
- # ...
350
- #@see click
351
- #@see alert_cancel
352
- def alert_ok
353
- status = true
354
- error = nil
355
- threads = []
356
- @@driver.each_value do |driver|
357
- threads << Thread.new do
358
- begin
359
- driver.switch_to.alert.accept
360
- rescue
361
- status = false
362
- error = 'alert_ok: No alert!'
363
- end
170
+ # context "Example" do
171
+ #
172
+ # should 'TODO something' do
173
+ # Unit.close_window 2
174
+ # ...
175
+ #@see switch_to_window
176
+ def close_window num
177
+ raise ArgumentError.new("Invalid value \"#{num}\" of argument 'num'") unless num.class == Fixnum
178
+ update_window_handles
179
+ raise 'Invalid window number' unless @@handles.keys.include?(num.to_s)
180
+ current = @@handles.key(@@driver.window_handle)
181
+ raise 'Can not close active window' if num.to_s == current
182
+ @@driver.switch_to.window @@handles[num.to_s]
183
+ @@driver.close
184
+ @@handles.delete_if { |key, value| key == num.to_s }
185
+ @@driver.switch_to.window @@handles[current]
186
+ new_handles = {}
187
+ num = 0
188
+ @@handles.keys.sort.each do |key|
189
+ new_handles[num.to_s] = @@handles[key]
190
+ num += 1
191
+ end
192
+ @@handles = new_handles
193
+ end
194
+ #Проверяет, отображается ли элемент странице.
195
+ #@param selector [String] css селектор элемента
196
+ #@return [FalseClass/TrueClass]
197
+ #@example
198
+ # context "Example" do
199
+ #
200
+ # should "TODO something" do
201
+ # ...
202
+ # assert_equal true, Unit.displayed? '.menu'
203
+ # end
204
+ # ...
205
+ def displayed? selector
206
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
207
+ if check_element(selector)
208
+ return @@driver.find_element(:css => selector).displayed?
209
+ else
210
+ raise(ElementIsMissingError, "Element #{selector} is missing")
364
211
  end
365
212
  end
366
- threads.each(&:join)
367
- return status, error
368
- end
369
- #Кликает на кнопку 'Cancel' в окне алерта. Используется только в блоках should или setup.
370
- #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
213
+ #Заполнить поле или выбирает файл для загрузки.
214
+ # @param selector [String] css селектор
215
+ # @param value [String] значение, которое необходимо ввести
371
216
  #@example
372
- # class SelWeT::Unit
373
- #
374
- # set_browsers [:firefox, :chrome]
375
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
376
- # @@somePage = 'http://inventos.ru/produkty/#top'
377
- #
378
- # context "Example" do
217
+ # context "Example" do
379
218
  #
380
- # should "TODO something" do
381
- # ...
382
- # Unit.alert_cancel
383
- # ...
384
- #@see click
385
- #@see alert_ok
386
- def alert_cancel
387
- status = true
388
- error = nil
389
- threads = []
390
- @@driver.each_value do |driver|
391
- threads << Thread.new do
219
+ # should 'TODO something' do
220
+ # Unit.go_to @@somePage
221
+ # ...
222
+ # Unit.fill_in 'input#some_id', 'some text' #заполнить текстовое поле
223
+ # Unit.fill_in 'input#[type={"file"}]', '/path/to/file' #выбрать файл для загрузки
224
+ # ...
225
+ def fill_in selector, value
226
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
227
+ raise(ArgumentValueError, "Invalid value \"#{value}\" of argument 'value'") unless value.class == String
228
+ if check_element(selector)
229
+ element = @@driver.find_element(:css => selector)
230
+ raise "Element \"#{selector}\" not displayed!" unless element.displayed?
392
231
  begin
393
- driver.switch_to.alert.dismiss
232
+ @@driver.action.move_to(element).perform
233
+ element.clear
394
234
  rescue
395
- puts 'alert_ok: No alert!'
235
+ #skip this
396
236
  end
397
- end
237
+ element.send_keys(value)
238
+ else
239
+ raise(ElementIsMissingError, "Element #{selector} is missing")
240
+ end
398
241
  end
399
- threads.each(&:join)
400
- return status, error
401
- end
402
- #Проверяет наличие элемента. Используется только в блоках should или setup. Возвращает первым аргументом статус выполнения операции (Boolean), вторым - сообщение об ошибке, если она возникнет (String), третьим - текст, содержащийся в элементе (Hash). Третий аргумент имеет следующую структуру: !{"имя_браузера_1" =>["текст"], "имя_браузера_2" =>["текст"],...}. Если по данному селектору найдено более одного элемента, то количество элементов в массиве будет соответствовать их числу, то есть !{"имя_браузера_1" =>["текст_элемента_1", "текст_элемента_2", ...],...}. При установке параметра link
403
- # @param selector [String] css селектор элемента.
404
- # @param link [Boolean] параметр, позволяющий получить значение поля href. Работает только для ссылок.
405
- #@return [[Boolean, String, Hash]]
406
- #@example
407
- # class SelWeT::Unit
408
- #
409
- # set_browsers [:firefox, :chrome]
410
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
411
- # @@somePage = 'http://inventos.ru/produkty/#top'
412
- #
413
- # context "Example" do
242
+ #Навести курсор на элемент.
243
+ #@param selector [String] css селектор
244
+ # @example
245
+ # context "Example" do
414
246
  #
415
- # should "TODO something" do
416
- # status, error, data = Unit.checkElement 'a.menu'
417
- # status, error, data = Unit.checkElement 'a.toolbar', true
418
- # ...
419
- #@see checkElements
420
- def check_element selector, link = nil
421
- result = [true, "", []]
422
- threads = []
423
- data = {}
424
- @@driver.each do |name, driver|
425
- threads << Thread.new do
426
- begin
427
- wait = Selenium::WebDriver::Wait.new(:timeout => 15)
428
- wait.until { driver.find_element(:css => selector) }
429
- elements = driver.find_elements(:css => selector)
430
- rescue
431
- Thread.current["issue"] = name
432
- end
433
- if elements.nil? or elements.size == 0
434
- Thread.current["no_elems"] = name
435
- else
436
- elements.each do |element|
437
- unless link
438
- if element.attribute('type') == 'submit' or element.attribute('type') == 'button' or element.attribute('type') == 'reset'
439
- data[name].nil? ? data[name] = [element.attribute('value')] : data[name] << element.attribute('value')
440
- else
441
- if element.tag_name == 'select'
442
- opts = element.text.split("\n")
443
- opts.each do |opt|
444
- opt.strip!
445
- end
446
- opts.delete ''
447
- data[name].nil? ? data[name] = [opts] : data[name] << opts
448
- else
449
- data[name].nil? ? data[name] = [element.text] : data[name] << element.text
450
- end
451
- end
452
- else
453
- data[name].nil? ? data[name] = [{"link"=>element.attribute('href'), "text"=>element.text}] : data[name] << {"link"=>element.attribute('href'), "text"=>element.text}
454
- end
455
- end
456
- end
457
- end
458
- end
459
- threads.each(&:join)
460
- threads.each do |i|
461
- unless i["issue"].nil?
462
- result[1] = (result[1].empty? ? "Bad selector '#{selector}'! Browsers: "+i["issue"].to_s : result[1]+" "+i["issue"].to_s)
247
+ # should 'TODO somethin' do
248
+ # Unit.hover_over_element "div.menu"
249
+ # Unit.click "a.some_url"
250
+ # ...
251
+ def hover_over_element selector
252
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
253
+ if check_element(selector)
254
+ element = @@driver.find_element(:css => selector)
255
+ @@driver.action.move_to(element).perform
463
256
  else
464
- unless i["no_elems"].nil?
465
- result[1] = (result[1].empty? ? "Element '#{selector}' is missing. Browsers: "+i["no_elems"].to_s : result[1]+" "+i["no_elems"].to_s)
466
- end
257
+ raise(ElementIsMissingError, "Element #{selector} is missing")
467
258
  end
468
259
  end
469
- unless result[1].empty?
470
- result[0] = false
471
- return result
472
- end
473
- result[2] = data
474
- return result
475
- end
476
- #Проверяет наличие элементов. Используется только в блоках should или setup. Возвращает первым аргументом статус выполнения операции (Boolean), вторым - сообщение об ошибке, если она возникнет (String), третьим - текст, содержащийся в элементах ([Hash, Hash, ...]). Хеши имеют ту же структуру, что и в {check_element}.
477
- # @param selectors [Array] массив css селекторов элементов.
478
- # @param link [Boolean] параметр, позволяющий получить значение поля href. Работает только для ссылок.
479
- #@return [[Boolean, String, [Hash, Hash,...]]]
260
+ #Получить значение атрибута элемента.
261
+ #@param selector [String] css селектор элемента
262
+ #@param attr [String] атрибут
263
+ #@return [String] значение атрибута
480
264
  #@example
481
- # class SelWeT::Unit
482
- #
483
- # set_browsers [:firefox]
484
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
485
- # @@somePage = 'http://inventos.ru/produkty/#top'
486
- #
487
- # context "Example" do
265
+ # context "Example" do
488
266
  #
489
- # should "TODO something" do
490
- # status, error, data = Unit.check_elements ['input#email','input#password','a']
491
- # #Получим количество ссылок
492
- # a_num = data[2]["firefox"].size
493
- # ...
494
- #@see check_element
495
- def check_elements selectors, link = nil
496
- result = [true, "", []]
497
- return [false, "Argument 'selectors' must be Array!", []] unless selectors.class == Array
498
- selectors.each do |selector|
499
- status, message, data = check_element(selector, link)
500
- unless status
501
- result[1] = (result[1].empty? ? message+"\n" : result[1]+message+"\n")
267
+ # should 'TODO somethin' do
268
+ # link = Unit.get_attr "a.class", 'href'
269
+ # ...
270
+ def get_attr selector, attr
271
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
272
+ raise(ArgumentValueError, "Invalid value \"#{attr}\" of argument 'attr'") unless attr.class == String
273
+ if check_element(selector)
274
+ return @@driver.find_element(:css => selector).attribute(attr)
275
+ else
276
+ raise(ElementIsMissingError, "Element #{selector} is missing")
502
277
  end
503
- result[2] << data
504
278
  end
505
- unless result[1].empty?
506
- result[0] = false
507
- end
508
- return result
509
- end
510
- #Обновляет страницу. Используется только в блоках should или setup.
279
+ #Получить открытый URL текущего окна.
280
+ #@return [String] URL
511
281
  #@example
512
- # class SelWeT::Unit
513
- #
514
- # ...
515
- # @@somePage = 'http://inventos.ru/produkty/#top'
516
- #
517
- # context "Example" do
282
+ # context "Example" do
518
283
  #
519
- # should "TODO something" do
520
- # Unit.refresh
521
- # ...
522
- #@see go_to
523
- def refresh
524
- threads = []
525
- @@driver.each_value do |driver|
526
- threads << Thread.new do
527
- driver.navigate.refresh
528
- end
529
- end
530
- threads.each(&:join)
531
- end
532
- #Возвращает тег по заданному селектору. Используется только в блоках should или setup.
533
- # @param selector [String] css селектор
534
- # @return [[Boolean, String, Hash]] первый аргумент - статус, второй - сообщение об ошибке, если она возникает, третий - хеш вида !{имя браузера => тег}.
535
- # @example
536
- # class SelWeT::Unit
537
- #
538
- # ...
539
- #
540
- # context "Example" do
541
- #
542
- # should 'TODO something' do
543
- # Unit.go_to @@somePage
544
- # ...
545
- # status, message, tags = Unit.get_tag '#some_id'
546
- # ...
547
- def get_tag selector
548
- threads = []
549
- tags = {}
550
- status, message = check_element selector
551
- return [false, "get_tag: "+message] unless status
552
- @@driver.each do |name, driver|
553
- threads << Thread.new do
554
- tags[name] = driver.find_element(:css => selector).tag_name
555
- end
284
+ # should 'TODO somethin' do
285
+ # current_location = Unit.get_location
286
+ # ...
287
+ def get_location
288
+ @@driver.current_url
556
289
  end
557
- threads.each(&:join)
558
- return [true, "", tags]
559
- end
560
- #Заполнить поле или выбирает файл для загрузки. Используется только в блоках should или setup.
561
- # @param selector [String] css селектор
562
- # @param value [String] значение, которое необходимо ввести.
563
- # @param postfix [Boolean] используется, если в разных браузерах необходимо ввести разные значения. К value добавляется '_имя_браузера'.
564
- # @return [[Boolean,String]] - первый аргумент - статус выполнения, второй - сообщение об ошибке, если она произойдёт.
290
+ #Получить тег элемента.
291
+ #@param selector [String] css селектор элемента
292
+ #@return [String] тег
565
293
  #@example
566
- # class SelWeT::Unit
567
- #
568
- # ...
569
- #
570
- # context "Example" do
294
+ # context "Example" do
571
295
  #
572
- # should 'TODO something' do
573
- # Unit.go_to @@somePage
574
- # ...
575
- # status, error = Unit.fill 'input#some_id', 'some text' #заполнить текстовое поле
576
- # status, error = Unit.fill 'input#[type={"file"}]', 'C:\\path\to\file' #выбрать файл для загрузки
577
- # ...
578
- #@see go_to
579
- #@see post_form
580
- def fill selector, value, postfix = nil
581
- result = [true, ""]
582
- threads = []
583
- status, message, data = check_element selector
584
- unless status
585
- return [false, message]
586
- end
587
- data.each_value do |i|
588
- if i.size>1
589
- return [false, "fill: Element with selector #{selector} not uniq!"]
590
- end
591
- end
592
- @@driver.each do |name, driver|
593
- threads << Thread.new do
594
- element = driver.find_element(:css => selector)
595
- driver.action.move_to(element).perform
596
- begin
597
- element.clear if element.attribute('type') != 'file'
598
- rescue
599
- #skip this
600
- end
601
- driver.find_element(:css => selector).send_keys((postfix.nil? ? value : value+"_"+name))
296
+ # should 'TODO somethin' do
297
+ # tag_name = Unit.get_tag '.element_class'
298
+ # ...
299
+ def get_tag selector
300
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
301
+ if check_element(selector)
302
+ return @@driver.find_element(:css => selector).tag_name
303
+ else
304
+ raise(ElementIsMissingError, "Element #{selector} is missing")
602
305
  end
603
306
  end
604
- threads.each(&:join)
605
- return result
606
- end
607
- #Возвращает состояние для radio и checkbox. Используется только в блоках should или setup.
608
- # @param selector [String] css селектор
609
- # @return [[Boolean,String/Hash] первый аргумент - статус выполнения, второй - хеш вида !{имя_браузера=>статус} (если radio или checkbox: 1. checked, то статус принимает значение true; 2. unchecked, то статус принимает значение false), или, если первый аргумент равен false - содержит текст ошибки.
307
+ #Получить текст, отображаемый на элементе или группе элементов.
308
+ #@param selector [String] css селектор элемента
309
+ #@param all [String] установить true, если необходимо получить текст для группы элементов
310
+ #@return [String/Array] текст, или массив строк, если all установлен как true
610
311
  #@example
611
- # class SelWeT::Unit
612
- #
613
- # ...
614
- #
615
- # context "Example" do
312
+ # context "Example" do
616
313
  #
617
- # should 'TODO something' do
618
- # Unit.go_to @@somePage
619
- # ...
620
- # status, check = Unit.get_status 'input[type="checkbox"]'
621
- # ...
622
- def get_status selector
623
- threads = []
624
- status, message, data = check_element selector
625
- return [false, 'get_status: Element not uniq!'] if data.values[0].size>1
626
- return [false, "get_status: "+message, tag] unless status
627
- status = true
628
- @@driver.each do |name, driver|
629
- threads << Thread.new do
630
- element = driver.find_element(:css => selector)
631
- Thread.current['name'] = name
632
- if element.attribute('type') == 'checkbox' or element.attribute('type') == 'radio'
633
- Thread.current['status'] = driver.find_element(:css => selector).selected?.inspect
314
+ # should 'TODO somethin' do
315
+ # text = Unit.get_text 'div.element_class'
316
+ # text = Unit.get_text('div.other_class', true)
317
+ # ...
318
+ def get_text selector, all = nil
319
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
320
+ raise(ArgumentValueError, "Invalid value \"#{all}\" of argument 'all'") unless [NilClass, FalseClass, TrueClass].include?(all.class)
321
+ if check_element(selector)
322
+ unless all
323
+ return @@driver.find_element(:css => selector).text
634
324
  else
635
- Thread.current['status'] = "#{element.attribute('type')} is not a checkbox or radio!"
636
- status = false
325
+ elems = @@driver.find_elements(:css => selector)
326
+ array = []
327
+ elems.each do |elem|
328
+ array.push elem.text
329
+ end
330
+ return array
637
331
  end
332
+ else
333
+ raise(ElementIsMissingError, "Element #{selector} is missing")
638
334
  end
639
335
  end
640
- threads.each(&:join)
641
- statuses = {}
642
- threads.each do |i|
643
- statuses[i['name']] = (i['status'] == "true" ? true : i['status'] == "false" ? false : i['status'])
644
- end
645
- return [status, statuses]
646
- end
647
- #Заполнить и отправить форму.
648
- # @param selector [String] css селектор формы.
649
- # @param fields [Hash] хеш. В качестве ключа передается css селектор элемента (String), в качестве значения: 1) для текстовых полей - строка со значением(String). Если в разных браузерах требуется ввести разные значения, то вначале строки необходимо поставить символ &. Тогда в поле запишется данная строка без символа &, но в конце будет добавлен постфикс "_имя браузера"; 2) для checkbox, radio и кнопок(не submit!) - значение :click; 3) для кнопки отправки формы - :submit. Если не будет указана кнопка для отправки формы, то форма всё равно будет отправлена; 4) для select - массив значений(String), которые необходимо выбрать; 5) для file - путь до файла.
650
- # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
336
+ #Переход по ссылке. При переходе функция дожидается полной загрузки страницы в пределах времени pageload_timeout.
337
+ #@param url [String] ссылка, по которой необходимо перейти.
651
338
  #@example
652
- # class SelWeT::Unit
653
- #
654
- # ...
655
- #
656
- # context "Example" do
339
+ # context "Example" do
657
340
  #
658
- # should "Successfull authorization" do
659
- # status, error = Unit.post_form ".form", {'#email' => 'admin@example.ru', '#password' => 'admin', '.checkbox' => :click, '.submit'=>:submit}
341
+ # setup do
342
+ # Unit.go_to @@somePage
343
+ # end
660
344
  # ...
661
- #@see click
662
- #@see fill
663
- def post_form selector, fields = nil
664
- result = [true, ""]
665
- fields = {} if fields.nil?
666
- status, message, data = check_element selector
667
- unless status
668
- return [false, message]
669
- end
670
- data.each do |key, value|
671
- if value.size>1
672
- return [false, "post_form: (#{key}) Found more than one form with selector '#{selector}'"]
673
- end
674
- end
675
- check_elements = ''
676
- fields.keys.each do |key|
677
- status, message, data = check_element key
678
- unless status
679
- check_elements = (check_elements.empty? ? message+' : '+key+"\n" : check_elements+message+' : '+key+"\n")
680
- end
681
- data.each do |browser, value|
682
- if value.size>1
683
- check_elements = (check_elements.empty? ? "post_form:(#{browser}) Element of form not uniq : "+key+"\n" : check_elements+"post_form:(#{browser}) Element of form not uniq : "+key+"\n")
684
- end
685
- end
686
- end
687
- unless check_elements.empty?
688
- return [false, check_elements]
689
- end
690
- submit_button = nil
691
- bad_args = {}
692
- fields.each do |key, value|
693
- if value.class != String and value.class != Symbol
694
- bad_args[key] = value
695
- end
696
- if value.class == Symbol
697
- if value != :click and value != :submit
698
- bad_args[key] = value
699
- end
700
- end
701
- end
702
- return [false, 'post_form: Bad args was passed: '+bad_args.to_s] unless bad_args.empty?
703
- fields.each do |key, value|
704
- if value == :click
705
- click key
706
- end
707
- if value == :submit
708
- submit_button = key
709
- end
710
- if value.class == Array
711
- status, error = set_select_items(key, value)
712
- return [false, error] unless status
713
- end
714
- end
715
- fields.delete_if { |key,value| value == :click or value == :submit or value.class == Array }
716
- threads = []
717
- errors = nil
718
- @@driver.each do |name, driver|
719
- threads << Thread.new do
720
- form = driver.find_element(:css => selector)
721
- fields.each do |key, value|
722
- tag = form.find_element(:css => key).tag_name
723
- errors = true if tag == 'select'
724
- begin
725
- form.find_element(:css => key).clear
726
- rescue
727
- #skip this
728
- end
729
- if value[0] == '&'
730
- send_value = value+'_'+name
731
- send_value.slice! '&'
732
- form.find_element(:css => key).send_keys(send_value)
733
- else
734
- form.find_element(:css => key).send_keys(value)
735
- end
736
- end
737
- unless errors
738
- form.submit unless submit_button
739
- end
740
- end
345
+ #@see refresh
346
+
347
+ def go_to url
348
+ raise(ArgumentValueError, "Invalid value of argument 'selector'") unless url.class == String
349
+ wait = Selenium::WebDriver::Wait.new
350
+ @@driver.navigate.to url
351
+ wait.until { @@driver.execute_script("return window.onload = function(){}; ") }
741
352
  end
742
- threads.each(&:join)
743
- return [false, 'post_form: For "select" you must pass array with selected values!'] if errors
744
- click submit_button unless !submit_button
745
- return result
746
- end
747
- #Сверяет переданный url с текущим. Используется только в блоках should или setup.
748
- # @param url [String] url, с которым будет сравинваться текущий url.
749
- # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
353
+
354
+ #Проверяет, открыто ли окно с номером num.
355
+ #@param num [Fixnum] номер окна
356
+ #@return [FalseClass/TrueClass]
357
+ #@example
358
+ # context "Example" do
359
+ #
360
+ # should 'TODO somethin' do
361
+ # ...
362
+ # assert_equal false, Unit.opened?(2), 'Window not closed!'
363
+ def opened? num
364
+ raise(ArgumentValueError, "Invalid value of argument 'num'") unless num.class == Fixnum
365
+ update_window_handles
366
+ return @@handles.keys.include?(num.to_s)
367
+ end
368
+ #Нажать клавишу на клавиатуре. Для клавиш, отличных от алфовитно-цифровых, в качестве параметра следует передавать значение типа Symbol, соответствующее необходимой клавише. Допустимые значения: :cancel,:help,:backspace,:tab,:clear,:return,:enter,:shift,:left_shift,:control,:left_control,
369
+ #:alt,:left_alt,:pause,:escape,:space,:page_up,:page_down,:end,:home,:left,:arrow_left,:up,:arrow_up,
370
+ #:right,:arrow_right,:down,:arrow_down,:insert,:delete,:semicolon,:equals,:numpad0,:numpad1,:numpad2,
371
+ #:numpad3,:numpad4,:numpad5,:numpad6,:numpad7,:numpad8,:numpad9,:multiply,:add,:separator,:subtract,
372
+ #:decimal,:divide,:f1,:f2,:f3,:f4,:f5,:f6,:f7,:f8,:f9,:f10,:f11,:f12,:meta,:command
373
+ #@param key [String/Symbol] клавиша
374
+ #@param state [Symbol] состояние. Допустимые значения: :down(нажать), :up(отпустить). Если параметр не будет указан, то будет сделано обычное нажатие.
375
+ def press_key key, state = nil
376
+ unless [
377
+ :null,:cancel,:help,:backspace,:tab,:clear,:return,:enter,:shift,:left_shift,:control,:left_control,
378
+ :alt,:left_alt,:pause,:escape,:space,:page_up,:page_down,:end,:home,:left,:arrow_left,:up,:arrow_up,
379
+ :right,:arrow_right,:down,:arrow_down,:insert,:delete,:semicolon,:equals,:numpad0,:numpad1,:numpad2,
380
+ :numpad3,:numpad4,:numpad5,:numpad6,:numpad7,:numpad8,:numpad9,:multiply,:add,:separator,:subtract,
381
+ :decimal,:divide,:f1,:f2,:f3,:f4,:f5,:f6,:f7,:f8,:f9,:f10,:f11,:f12,:meta,:command
382
+ ].include? key
383
+ raise(ArgumentValueError, "Invalid value \"#{key}\" of argument 'key'") unless /^[A-Za-z0-9]$/ === key.to_s
384
+ end
385
+ raise(ArgumentValueError, "Invalid value \"#{state}\" of argument 'state'") unless [:up, :down, nil].include?(state)
386
+ case state
387
+ when :up
388
+ @@driver.action.key_up(key).perform
389
+ when :down
390
+ @@driver.action.key_down(key).perform
391
+ when nil
392
+ @@driver.action.send_keys(key).perform
393
+ end
394
+ end
395
+ #Обновить текущее окно
396
+ def refresh
397
+ @@driver.navigate.refresh
398
+ end
399
+ #Сделать скриншот. Файл будет сохранен в каталоге, из которого был произведен запуск теста с расширением .png.
400
+ #@param filename [String] имя файла
401
+ def screenshot filename
402
+ raise(ArgumentValueError, "Invalid value \"#{filename}\" of argument 'filename'") unless filename.class == String
403
+ @@driver.save_screenshot("./"+filename+".png")
404
+ end
405
+ #Устанавливает используемый для тестирования браузер. Необходимо использовать перед блоками тестов.
406
+ #@param browser [Symbol] браузер. Допустимые значения: :firefox, :chrome, :ie, :safari, :phantomjs.
750
407
  #@example
751
408
  # class SelWeT::Unit
752
- #
753
- # set_browsers [:firefox, :chrome]
754
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
755
- # @@somePage = 'http://www.example.com'
756
- #
409
+ # set_browser :firefox
410
+ # ...
411
+ def set_browser browser
412
+ raise(ArgumentValueError, "Invalid value \"#{browser}\" of argument 'browser'") unless [:firefox, :chrome, :ie, :safari, :phantomjs].include? browser
413
+ @@browser = browser
414
+ end
415
+ #Выбирает элементы в select по индексам. Нумирация начинается с 0. Если в multiple select необходимо выбрать несколько элементов, то нужно передать массив индексов.
416
+ #@param selector [String] css селектор
417
+ #@param items [Fixnum/Array] индекс или массив индексов элементов, которые необходимо выбрать
418
+ #@example
757
419
  # context "Example" do
758
420
  #
759
- # should 'Correct link' do
760
- # Unit.go_to @@somePage
761
- # ...
762
- # status, error = Unit.check_location 'http://www.example.com/other_page'
763
- # ...
764
- #@see go_to
765
- #@see get_location
766
- def check_location url
767
- result = [true, ""]
768
- threads = []
769
- @@driver.each do |name, driver|
770
- threads << Thread.new do
771
- unless driver.current_url == url
772
- Thread.current["value"] = name
773
- Thread.current["real"] = driver.current_url
421
+ # should "TODO something" do
422
+ # Unit.set_select_items 'select[name="some_name"]', 2
423
+ # Unit.set_select_items 'select[name="other_name"]', [1,3,6]
424
+ # ...
425
+ def set_select_items selector, items
426
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
427
+ raise(ArgumentValueError, "Invalid value \"#{items}\" of argument 'items'") unless [Array, Fixnum].include?(items.class)
428
+ if check_element(selector)
429
+ select = Selenium::WebDriver::Support::Select.new(@@driver.find_element(:css => selector))
430
+ raise(ArgumentValueError, "Invalid value \"#{items}\" of argument 'items' for not multiple select") if items.class == Array and !select.multiple?
431
+ if select.multiple?
432
+ select.deselect_all
433
+ if items.class == Array
434
+ items.each do |item|
435
+ raise(ArgumentValueError, "Invalid value \"#{items}\" of argument 'items'") unless item.class == Fixnum
436
+ select.select_by(:index, item)
437
+ end
438
+ else
439
+ select.select_by(:index, items)
440
+ end
441
+ else
442
+ select.select_by(:index, items)
774
443
  end
775
- end
776
- end
777
- threads.each(&:join)
778
- threads.each do |i|
779
- unless i["value"].nil?
780
- result[1] = (result[1].empty? ? "Wrong location '#{i['real']}': "+i["value"].to_s : result[1]+" "+i["value"].to_s)
781
- end
782
- end
783
- unless result[1].empty?
784
- result[0] = false
444
+ else
445
+ raise(ElementIsMissingError, "Element #{selector} is missing")
446
+ end
785
447
  end
786
- return result
787
- end
788
- #Возвращает текущий url. Используется только в блоках should или setup.
789
- # @return [Hash] ключ - имя браузера, значение - URL.
448
+ #Устанавливает URL для Selenium Server или PhantomJS. Необходимо использовать перед блоками тестов.
449
+ #Если параметр не указан, то будет использован локальный браузер
450
+ #@param url [String] URL запущенного Selenium Server
790
451
  #@example
791
452
  # class SelWeT::Unit
792
- #
793
- # set_browsers [:firefox, :chrome]
794
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
795
- # @@somePage = 'http://www.example.com'
796
- #
797
- # context "Example" do
798
- #
799
- # should 'Correct link' do
800
- # Unit.go_to @@somePage
801
- # ...
802
- # location = Unit.get_location
803
- # ...
804
- #@see check_location
805
- #@see go_to
806
- def get_location
807
- result = {}
808
- threads = []
809
- @@driver.each do |name, driver|
810
- threads << Thread.new do
811
- Thread.current["name"] = name
812
- Thread.current["url"] = driver.current_url
813
- end
814
- end
815
- threads.each(&:join)
816
- threads.each do |i|
817
- result[i['name']] = i['url']
453
+ # set_browser :firefox
454
+ # set_server_url "http://somewhere:4444/wd/hub"
455
+ # ...
456
+ def set_server_url url
457
+ raise(ArgumentValueError, "Invalid value \"#{url}\" of argument 'url'") unless url.class == String
458
+ @@server_url = url
818
459
  end
819
- return result
820
- end
821
- #Сохраняет скриншот текущего состояния браузеров рядом со скриптом. Имя файла будет иметь следующий вид: browsername_filename.png
822
- # @param filename [String] часть имени выходного файла.
460
+ #Устанавливает максимально допустимое время ожидания элемента (по умолчанию 5 секунд). Необходимо использовать перед блоками тестов.
461
+ #@param sec [Fixnum] время в секундах.
823
462
  #@example
824
463
  # class SelWeT::Unit
825
- #
826
- # set_browsers [:firefox, :chrome]
827
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
828
- # @@somePage = 'http://www.example.com'
829
- #
830
- # context "Example" do
831
- #
832
- # should 'Make screenshot' do
833
- # Unit.go_to @@somePage
834
- # ...
835
- # Unit.screenshot 'TestScreenshot'
836
- # ...
837
- def screenshot filename
838
- threads = []
839
- @@driver.each do |name, driver|
840
- threads << Thread.new do
841
- driver.save_screenshot("./"+name+"_"+filename+".png")
842
- end
464
+ # set_browser :firefox
465
+ # set_timewait 15
466
+ # ...
467
+ #@see set_pageload_timewait
468
+ def set_timewait sec
469
+ raise(ArgumentValueError, "Invalid value \"#{sec}\" of argument 'sec'") unless sec.class == Fixnum
470
+ @@timewait = sec
843
471
  end
844
- threads.each(&:join)
845
- end
846
- #Открывает ссылку в новом окне и переключается на него.
847
- #@param selector [String] css селектор ссылки.
848
- # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
472
+ #Устанавливает максимально допустимое время ожидания загрузки страницы(по умолчанию 5 секунд). Может отличаться от времени ожидания элементов. Необходимо использовать перед блоками тестов.
473
+ #@param sec [Fixnum] время в секундах.
849
474
  #@example
850
475
  # class SelWeT::Unit
851
- #
852
- # set_browsers [:firefox, :chrome]
853
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
854
- # @@somePage = 'http://www.example.com'
855
- #
856
- # context "Example" do
857
- #
858
- # should 'TODO somethin' do
859
- # Unit.go_to @@somePage
860
- # ...
861
- # Unit.in_new_window 'a.someclass'
862
- # ...
863
- #@see switchToWindow
864
- #@see close_window
865
- def in_new_window selector
866
- threads = []
867
- not_opened = false
868
- status, message = check_element selector
869
- unless status
870
- return [false, message]
476
+ # set_browser :firefox
477
+ # set_timewait 3
478
+ # set_pageload_timewait 15
479
+ # ...
480
+ #@see set_timewait
481
+ def set_pageload_timewait sec
482
+ raise(ArgumentValueError, "Invalid value \"#{sec}\" of argument 'sec'") unless sec.class == Fixnum
483
+ @@pageload_timewait = sec
871
484
  end
872
- @@driver.each do |name, driver|
873
- threads << Thread.new do
874
- a = driver.find_element :css => selector
875
- if @@win_num == 0
876
- @@opened_window[name] = {@@win_num => driver.window_handle}
877
- end
878
- driver.action.key_down(:shift).perform
879
- a.click
880
- driver.action.key_up(:shift).perform
881
- old_handle = @@opened_window[name].values
882
- new_handle = (driver.window_handles - old_handle)[0]
883
- unless new_handle.nil?
884
- driver.switch_to.window new_handle
885
- @@opened_window[name][@@win_num+1] = new_handle
485
+
486
+ #Закрывает браузер после выполнения всех тестов.
487
+ #Внутренний метод. Выполняется автоматически.
488
+ def shutdown
489
+ if @@driver
490
+ @@driver.close
491
+ @@driver.quit
492
+ end
493
+ end
494
+ #Запускает браузер перед выполнением тестов.
495
+ #Выполняется автоматически непосредственно перед запуском тестов.
496
+ def startup
497
+ @@driver = nil
498
+ url = nil
499
+ unless @@server_url
500
+ puts 'URL not specified! Local browser will be used.'
501
+ else
502
+ url = @@server_url
503
+ end
504
+ if @@browser.nil?
505
+ raise ArgumentError.new('Browser not specified!')
506
+ end
507
+ if url
508
+ if @@browser == :phantomjs
509
+ @@driver = Selenium::WebDriver.for(:remote, :url => url)
886
510
  else
887
- not_opened = true
511
+ @@driver = Selenium::WebDriver.for(:remote, :desired_capabilities => @@browser, :url => url)
888
512
  end
513
+ else
514
+ @@driver = Selenium::WebDriver.for @@browser
889
515
  end
516
+ @@driver.manage.timeouts.implicit_wait = @@timewait
517
+ @@driver.manage.timeouts.script_timeout = @@timewait
518
+ @@driver.manage.timeouts.page_load = @@pageload_timewait
519
+ @@driver.manage.window.maximize
520
+ @@handles["0"] = @@driver.window_handle
890
521
  end
891
- threads.each(&:join)
892
- return [false, "Window not opened!"] if not_opened
893
- @@win_num += 1
894
- return true
895
- end
896
522
  #Переключиться на другое окно. Окна нумируются в порядке их открытия. Нумирация начинается с 0.
897
523
  #@param num [Integer] номер окна.
898
- # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
899
524
  #@example
900
- # class SelWeT::Unit
901
- #
902
- # set_browsers [:firefox, :chrome]
903
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
904
- # @@somePage = 'http://www.example.com'
905
- #
906
525
  # context "Example" do
907
526
  #
908
527
  # should 'TODO something' do
909
- # Unit.in_new_window 'a.someclass'
910
528
  # ...
911
529
  # Unit.switch_to_window 0
912
530
  # Unit.close_window 1
913
531
  # ...
914
- #@see in_new_window
915
532
  #@see close_window
916
- def switch_to_window num
917
- threads = []
918
- status = true
919
- @@driver.each do |name, driver|
920
- threads << Thread.new do
921
- if @@opened_window[name].has_key? num
922
- driver.switch_to.window @@opened_window[name][num]
923
- else
924
- status = false
925
- end
926
- end
927
- end
928
- threads.each(&:join)
929
- return status, (status ? "" : "Invalid num: '#{num}'")
930
- end
931
- #Закрыть окно с номером num. Окна нумируются в порядке их открытия. Нумирация начинается с 0. Если необходимо закрыть текущее окно, то перед закрытием необходимо переключиться на другое окно.
932
- #@param num [Integer] номер окна.
933
- # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
533
+ def switch_to_window num
534
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'num'") unless num.class == Fixnum
535
+ update_window_handles
536
+ raise "Invalid window number" unless @@handles.keys.include?(num.to_s)
537
+ @@driver.switch_to.window @@handles[num.to_s]
538
+ end
539
+ #Переключиться на iframe. Для дальнейшего взаимодействия с основной страницей необходимо выполнить {to_page}.
540
+ #@param selector [String] css селектор на iframe
934
541
  #@example
935
- # class SelWeT::Unit
936
- #
937
- # set_browsers [:firefox, :chrome]
938
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
939
- # @@somePage = 'http://www.example.com'
940
- #
542
+ # ...
941
543
  # context "Example" do
942
544
  #
943
- # should 'TODO somethin' do
944
- # Unit.close_window 2
945
- # ...
946
- #@see in_new_window
947
- #@see switch_to_window
948
- def close_window num
949
- threads = []
950
- status = true
951
- @@driver.each do |name, driver|
952
- threads << Thread.new do
953
- current = driver.window_handle
954
- if current != @@opened_window[name][num]
955
- driver.switch_to.window @@opened_window[name][num]
956
- driver.close
957
- @@opened_window[name].delete_if do |key, value|
958
- key == num
959
- end
960
- driver.switch_to.window current
961
- else
962
- status = false
963
- end
964
- end
965
- end
966
- threads.each(&:join)
967
- if status
968
- return true
969
- else
970
- return [false, "You must switch to other window before closing this window"]
971
- end
972
- end
973
- #Навести курсор на элемент.
974
- #@param selector [String] css селектор элемента.
975
- #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
976
- #@example
977
- # class SelWeT::Unit
978
- #
979
- # set_browsers [:firefox, :chrome]
980
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
981
- # @@somePage = 'http://www.example.com'
982
- #
983
- # context "Example" do
984
- #
985
- # should 'TODO somethin' do
986
- # Unit.hover_over_element "div.menu"
987
- # Unit.click "a.some_url"
988
- # ...
989
- def hover_over_element selector
990
- status, message = check_element selector
991
- unless status
992
- return [false, message]
993
- end
994
- threads = []
995
- @@driver.each do |name, driver|
996
- threads << Thread.new do
997
- element = driver.find_element(:css => selector)
998
- driver.action.move_to(element).perform
545
+ # should 'show popup' do
546
+ # Unit.to_frame 'iframe#frame1'
547
+ # ...
548
+ #@see to_page
549
+ def to_frame selector
550
+ raise(ArgumentValueError, "Invalid value \"#{selector}\" of argument 'selector'") unless selector.class == String
551
+ if check_element(selector)
552
+ element = @@driver.find_element(:css => selector)
553
+ @@driver.action.move_to(element).perform
554
+ @@driver.switch_to.frame element
555
+ else
556
+ raise(ElementIsMissingError, "Element #{selector} is missing")
999
557
  end
1000
558
  end
1001
- threads.each(&:join)
1002
- return true
1003
- end
1004
- #Получить заголовок окна.
1005
- #@return Hash ключ - имя браузера, аргумент - title.
559
+ #Переключиться на основную страницу.
1006
560
  #@example
1007
- # class SelWeT::Unit
1008
- #
1009
- # set_browsers [:firefox, :chrome]
1010
- # set_selenium_server_url 'http://localhost:4444/wd/hub'
1011
- # @@somePage = 'http://www.example.com'
1012
- #
561
+ # ...
1013
562
  # context "Example" do
1014
563
  #
1015
- # should 'TODO somethin' do
564
+ # should 'Show popup' do
1016
565
  # ...
1017
- # titles = Unit.window_title
1018
- # ...
1019
- def window_title
1020
- threads = []
1021
- status = true
1022
- @@driver.each do |name, driver|
1023
- threads << Thread.new do
1024
- Thread.current["name"] = name
1025
- Thread.current["title"] = driver.title
566
+ # Unit.to_page
567
+ # ...
568
+ #@see to_frame
569
+ def to_page
570
+ @@driver.switch_to.default_content
571
+ end
572
+ #Обновить список handle. Внутренняя функция.
573
+ def update_window_handles
574
+ new_handles = @@driver.window_handles - @@handles.values
575
+ old_handles = @@handles.values - @@driver.window_handles
576
+ @@handles.delete_if{ |key, value| old_handles.include? value }
577
+ unless new_handles.empty?
578
+ num = @@handles.keys.max.to_i+1
579
+ new_handles.each do |handle|
580
+ @@handles[num.to_s] = handle
581
+ num += 1
582
+ end
1026
583
  end
1027
584
  end
1028
- threads.each(&:join)
1029
- titles = {}
1030
- threads.each do |i|
1031
- titles[i["name"]] = i["title"]
585
+ #Получить залоговок текущего окна.
586
+ #@return [String] заголовок
587
+ def window_title
588
+ @@driver.title
1032
589
  end
1033
- return titles
590
+
1034
591
  end
1035
-
592
+
1036
593
  end
1037
-
594
+
1038
595
  end
1039
- end