selwet 0.0.2

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 +7 -0
  2. data/lib/selwet.rb +1040 -0
  3. metadata +113 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f8720c4cffa2e62abbecc43b2aad890a34334826
4
+ data.tar.gz: 639eef52da75979f0fac7bf3c24e3f77fb71a97f
5
+ SHA512:
6
+ metadata.gz: f8f473682e8fb6b9ae03b177fd4354dd6def56182f9e05f813f5dfa8d029bb6d604c0bfca9626db28d6022b1c0a853b8532a9fc49e8270374f4c11ab7b1f710d
7
+ data.tar.gz: 87689728ceca18daf17b58b5d85aa838f1a750a7ced743ccc9b9c183340f2a803ae46a1f32ebf0a538fddbb564aea36b889dec6ee9f4b2add45514833038559f
data/lib/selwet.rb ADDED
@@ -0,0 +1,1040 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'selenium-webdriver'
4
+ require 'test-unit'
5
+ require 'shoulda-context'
6
+ #Модуль SelWeT (Selenium Web Test) позволяет тестировать веб-страницы в одном, или нескольких браузерах. Если тестирование производится в нескольких браузерах, то оно проводится параллельно.
7
+ module SelWeT
8
+ #Класс Unit содержит методы для проверки элементов страницы, получения их текстового содержимого и значения поля href для ссылок, заполнения полей, select-ов и форм, указания файлов для загрузки, кликов по элементам и кнопкам алерта, проверки статуса для radio и checkbox, перехода на другую страницу, обновления страницы, проверки текущего URL, открытие ссылки в новом окне, смены и закрытия окна, создания скриншотов.
9
+ #
10
+ #Тесты пишутся с использованием shoulda-context.
11
+ #@example
12
+ # #!/usr/bin/env ruby
13
+ # # encoding: UTF-8
14
+ # require 'selwet'
15
+ #
16
+ # class SelWeT::Unit
17
+ #
18
+ # setBrowsers [:firefox, :chrome]
19
+ # setSeleniumServerUrl 'http://127.0.0.1:4444/wd/hub'
20
+ #
21
+ # context "Example" do
22
+ # should "About Us" do
23
+ # Unit.followTheLink "http://inventos.ru/"
24
+ # Unit.click '#menu-item-3795 a'
25
+ # status, error = Unit.checkLocation 'http://inventos.ru/about/#top'
26
+ # assert_equal true, status, error
27
+ # end
28
+ # end
29
+ #
30
+ # 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
39
+
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
+ followTheLink @@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
87
+ end
88
+ #Устанавливает URL Selenium Server. Необходимо использовать перед блоками тестов.
89
+ #
90
+ #@param url [String] URL запущенного Selenium Server
91
+ #@example
92
+ # class SelWeT::Unit
93
+ # setBrowsers [:firefox, :chrome]
94
+ # setSeleniumServerUrl "http://localhost:4444/wd/hub"
95
+ # ...
96
+ def setSeleniumServerUrl url
97
+ @@url_selenium = url
98
+ end
99
+ #Устанавливает стартовую страницу при запуске браузеров. Использовать только перед блоками тестов.
100
+ #@param url [String] URL тестируемого сайта
101
+ #@example
102
+ # class SelWeT::Unit
103
+ # setBrowsers [:firefox, :chrome]
104
+ # setSeleniumServerUrl "http://localhost:4444/wd/hub"
105
+ # openLink "http://inventos.ru/"
106
+ # ...
107
+ def openLink url
108
+ @@start_url = url
109
+ end
110
+ #Устанавливает используемые для тестирования браузеры. Необходимо использовать перед блоками тестов.
111
+ #@param params [Array] массив, содержащий одно или несколько из следующий значений: :firefox, :chrome, :ie, :safari. Для :chrome и :ie Selenium Server следует запускать с соответствующими драйверами.
112
+ #@example
113
+ # class SelWeT::Unit
114
+ # setBrowsers [:firefox, :chrome]
115
+ # ...
116
+ def setBrowsers params
117
+ @@browsers = params
118
+ end
119
+ #Переход по ссылке. Используется только в блоках should или setup
120
+ #@param url [String] ссылка, по которой необходимо перейти.
121
+ #@example
122
+ # class SelWeT::Unit
123
+ #
124
+ # setBrowsers [:firefox, :chrome]
125
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
126
+ # @@somePage = 'http://inventos.ru/produkty/#top'
127
+ #
128
+ # context "Example" do
129
+ #
130
+ # setup do
131
+ # Unit.followTheLink @@somePage
132
+ # end
133
+ # ...
134
+ #@see refresh
135
+ def followTheLink 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. Для дальнейшего взаимодействия с основной страницей необходимо выполнить {switchToPage}.
145
+ #@param selector [String] css селектор на нужный iframe.
146
+ #@example
147
+ # class SelWeT::Unit
148
+ #
149
+ # ...
150
+ #
151
+ # context "Example" do
152
+ #
153
+ # should 'Show popup' do
154
+ # Unit.switchToFrame 'iframe#frame1'
155
+ # ...
156
+ #@see switchToPage
157
+ def switchToFrame selector
158
+ threads = []
159
+ status, message, tags = getTag selector
160
+ unless status
161
+ return false, "switchToFrame: "+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, "switchToFrame: #{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
178
+ end
179
+ threads.each(&:join)
180
+ return true
181
+ end
182
+ #Очистить кэш браузера
183
+ #@example
184
+ # class SelWeT::Unit
185
+ #
186
+ # ...
187
+ #
188
+ # context "Example" do
189
+ #
190
+ # should 'Do something' do
191
+ # ...
192
+ # Unit.clearCache
193
+ # ...
194
+ def clearCache
195
+ threads = []
196
+ @@driver.each do |name, driver|
197
+ threads << Thread.new do
198
+ driver.manage.delete_all_cookies
199
+ end
200
+ end
201
+ threads.each(&:join)
202
+ end
203
+ #Переключиться на основную страницу. Используется только в блоках should или setup.
204
+ #@example
205
+ # class SelWeT::Unit
206
+ #
207
+ # ...
208
+ #
209
+ # context "Example" do
210
+ #
211
+ # should 'Show popup' do
212
+ # ...
213
+ # Unit.switchToPage
214
+ # ...
215
+ #@see switchToFrame
216
+ def switchToPage
217
+ threads = []
218
+ @@driver.each do |name, driver|
219
+ threads << Thread.new do
220
+ driver.switch_to.default_content
221
+ end
222
+ 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.selectItemsFromTheSelect 'select[name="some_name"]', ['value 1', 'value2']
237
+ # ...
238
+ def selectItemsFromTheSelect 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} - selectItemsFromTheSelect 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 << "selectItemsFromTheSelect: 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 << "selectItemsFromTheSelect: Option '#{items}' does not exist!"
281
+ end
282
+ else
283
+ status = false
284
+ errors << "selectItemsFromTheSelect: '#{selector}' is not multiple! You must pass a single value."
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end
291
+ 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]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
299
+ #@example
300
+ # class SelWeT::Unit
301
+ #
302
+ # ...
303
+ #
304
+ # context "Example" do
305
+ #
306
+ # should "TODO something" do
307
+ # ...
308
+ # Unit.click 'input[type="submit"]'
309
+ # ...
310
+ #@see clickOkOnTheAlert
311
+ #@see clickCancelOnTheAlert
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
+ puts 'click: '+name+' : Bad selector : '+selector
327
+ end
328
+ end
329
+ end
330
+ end
331
+ threads.each(&:join)
332
+ if status
333
+ return status
334
+ else
335
+ return [status, "click: Bad selector : #{selector}"]
336
+ end
337
+ end
338
+ #Кликает на кнопку 'Ok' в окне алерта. Используется только в блоках should или setup.
339
+ #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
340
+ #@example
341
+ # class SelWeT::Unit
342
+ #
343
+ # ...
344
+ #
345
+ # context "Example" do
346
+ #
347
+ # should "TODO something" do
348
+ # ...
349
+ # Unit.clickOkOnTheAlert
350
+ # ...
351
+ #@see click
352
+ #@see clickCancelOnTheAlert
353
+ def clickOkOnTheAlert
354
+ status = true
355
+ error = nil
356
+ threads = []
357
+ @@driver.each_value do |driver|
358
+ threads << Thread.new do
359
+ begin
360
+ driver.switch_to.alert.accept
361
+ rescue
362
+ status = false
363
+ error = 'clickOkOnTheAlert: No alert!'
364
+ end
365
+ end
366
+ end
367
+ threads.each(&:join)
368
+ return status, error
369
+ end
370
+ #Кликает на кнопку 'Cancel' в окне алерта. Используется только в блоках should или setup.
371
+ #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст сообщения об ошибке, если она возникнет
372
+ #@example
373
+ # class SelWeT::Unit
374
+ #
375
+ # setBrowsers [:firefox, :chrome]
376
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
377
+ # @@somePage = 'http://inventos.ru/produkty/#top'
378
+ #
379
+ # context "Example" do
380
+ #
381
+ # should "TODO something" do
382
+ # ...
383
+ # Unit.clickOkOnTheAlert
384
+ # ...
385
+ #@see click
386
+ #@see clickOkOnTheAlert
387
+ def clickCancelOnTheAlert
388
+ status = true
389
+ error = nil
390
+ threads = []
391
+ @@driver.each_value do |driver|
392
+ threads << Thread.new do
393
+ begin
394
+ driver.switch_to.alert.dismiss
395
+ rescue
396
+ puts 'clickOkOnTheAlert: No alert!'
397
+ end
398
+ end
399
+ end
400
+ threads.each(&:join)
401
+ return status, error
402
+ end
403
+ #Проверяет наличие элемента. Используется только в блоках should или setup. Возвращает первым аргументом статус выполнения операции (Boolean), вторым - сообщение об ошибке, если она возникнет (String), третьим - текст, содержащийся в элементе (Hash). Третий аргумент имеет следующую структуру: !{"имя_браузера_1" =>["текст"], "имя_браузера_2" =>["текст"],...}. Если по данному селектору найдено более одного элемента, то количество элементов в массиве будет соответствовать их числу, то есть !{"имя_браузера_1" =>["текст_элемента_1", "текст_элемента_2", ...],...}. При установке параметра link
404
+ # @param selector [String] css селектор элемента.
405
+ # @param link [Boolean] параметр, позволяющий получить значение поля href. Работает только для ссылок.
406
+ #@return [[Boolean, String, Hash]]
407
+ #@example
408
+ # class SelWeT::Unit
409
+ #
410
+ # setBrowsers [:firefox, :chrome]
411
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
412
+ # @@somePage = 'http://inventos.ru/produkty/#top'
413
+ #
414
+ # context "Example" do
415
+ #
416
+ # should "TODO something" do
417
+ # status, error, data = Unit.checkElement 'a.menu'
418
+ # status, error, data = Unit.checkElement 'a.toolbar', true
419
+ # ...
420
+ #@see checkElements
421
+ def checkElement selector, link = nil
422
+ result = [true, "", []]
423
+ threads = []
424
+ data = {}
425
+ @@driver.each do |name, driver|
426
+ threads << Thread.new do
427
+ begin
428
+ wait = Selenium::WebDriver::Wait.new(:timeout => 15)
429
+ wait.until { driver.find_element(:css => selector) }
430
+ elements = driver.find_elements(:css => selector)
431
+ rescue
432
+ Thread.current["issue"] = name
433
+ end
434
+ if elements.nil? or elements.size == 0
435
+ Thread.current["no_elems"] = name
436
+ else
437
+ elements.each do |element|
438
+ unless link
439
+ if element.attribute('type') == 'submit' or element.attribute('type') == 'button' or element.attribute('type') == 'reset'
440
+ data[name].nil? ? data[name] = [element.attribute('value')] : data[name] << element.attribute('value')
441
+ else
442
+ if element.tag_name == 'select'
443
+ opts = element.text.split("\n")
444
+ opts.each do |opt|
445
+ opt.strip!
446
+ end
447
+ opts.delete ''
448
+ data[name].nil? ? data[name] = [opts] : data[name] << opts
449
+ else
450
+ data[name].nil? ? data[name] = [element.text] : data[name] << element.text
451
+ end
452
+ end
453
+ else
454
+ data[name].nil? ? data[name] = [{"link"=>element.attribute('href'), "text"=>element.text}] : data[name] << {"link"=>element.attribute('href'), "text"=>element.text}
455
+ end
456
+ end
457
+ end
458
+ end
459
+ end
460
+ threads.each(&:join)
461
+ threads.each do |i|
462
+ unless i["issue"].nil?
463
+ result[1] = (result[1].empty? ? "Bad selector '#{selector}'! Browsers: "+i["issue"].to_s : result[1]+" "+i["issue"].to_s)
464
+ else
465
+ unless i["no_elems"].nil?
466
+ result[1] = (result[1].empty? ? "Element '#{selector}' is missing. Browsers: "+i["no_elems"].to_s : result[1]+" "+i["no_elems"].to_s)
467
+ end
468
+ end
469
+ end
470
+ unless result[1].empty?
471
+ result[0] = false
472
+ return result
473
+ end
474
+ result[2] = data
475
+ return result
476
+ end
477
+ #Проверяет наличие элементов. Используется только в блоках should или setup. Возвращает первым аргументом статус выполнения операции (Boolean), вторым - сообщение об ошибке, если она возникнет (String), третьим - текст, содержащийся в элементах ([Hash, Hash, ...]). Хеши имеют ту же структуру, что и в {checkElement}.
478
+ # @param selectors [Array] массив css селекторов элементов.
479
+ # @param link [Boolean] параметр, позволяющий получить значение поля href. Работает только для ссылок.
480
+ #@return [[Boolean, String, [Hash, Hash,...]]]
481
+ #@example
482
+ # class SelWeT::Unit
483
+ #
484
+ # setBrowsers [:firefox]
485
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
486
+ # @@somePage = 'http://inventos.ru/produkty/#top'
487
+ #
488
+ # context "Example" do
489
+ #
490
+ # should "TODO something" do
491
+ # status, error, data = Unit.checkElements ['input#email','input#password','a']
492
+ # #Получим количество ссылок
493
+ # a_num = data[2]["firefox"].size
494
+ # ...
495
+ #@see checkElement
496
+ def checkElements selectors, link = nil
497
+ result = [true, "", []]
498
+ return [false, "Argument 'selectors' must be Array!", []] unless selectors.class == Array
499
+ selectors.each do |selector|
500
+ status, message, data = checkElement(selector, link)
501
+ unless status
502
+ result[1] = (result[1].empty? ? message+"\n" : result[1]+message+"\n")
503
+ end
504
+ result[2] << data
505
+ end
506
+ unless result[1].empty?
507
+ result[0] = false
508
+ end
509
+ return result
510
+ end
511
+ #Обновляет страницу. Используется только в блоках should или setup.
512
+ #@example
513
+ # class SelWeT::Unit
514
+ #
515
+ # ...
516
+ # @@somePage = 'http://inventos.ru/produkty/#top'
517
+ #
518
+ # context "Example" do
519
+ #
520
+ # should "TODO something" do
521
+ # Unit.refresh
522
+ # ...
523
+ #@see followTheLink
524
+ def refresh
525
+ threads = []
526
+ @@driver.each_value do |driver|
527
+ threads << Thread.new do
528
+ driver.navigate.refresh
529
+ end
530
+ end
531
+ threads.each(&:join)
532
+ end
533
+ #Возвращает тег по заданному селектору. Используется только в блоках should или setup.
534
+ # @param selector [String] css селектор
535
+ # @return [[Boolean, String, Hash]] первый аргумент - статус, второй - сообщение об ошибке, если она возникает, третий - хеш вида !{имя браузера => тег}.
536
+ # @example
537
+ # class SelWeT::Unit
538
+ #
539
+ # ...
540
+ #
541
+ # context "Example" do
542
+ #
543
+ # should 'TODO something' do
544
+ # Unit.followTheLink @@somePage
545
+ # ...
546
+ # status, message, tags = Unit.getTag '#some_id'
547
+ # ...
548
+ def getTag selector
549
+ threads = []
550
+ tags = {}
551
+ status, message = checkElement selector
552
+ return [false, "getTag: "+message] unless status
553
+ @@driver.each do |name, driver|
554
+ threads << Thread.new do
555
+ tags[name] = driver.find_element(:css => selector).tag_name
556
+ end
557
+ end
558
+ threads.each(&:join)
559
+ return [true, "", tags]
560
+ end
561
+ #Заполнить поле или выбирает файл для загрузки. Используется только в блоках should или setup.
562
+ # @param selector [String] css селектор
563
+ # @param value [String] значение, которое необходимо ввести.
564
+ # @param postfix [Boolean] используется, если в разных браузерах необходимо ввести разные значения. К value добавляется '_имя_браузера'.
565
+ # @return [[Boolean,String]] - первый аргумент - статус выполнения, второй - сообщение об ошибке, если она произойдёт.
566
+ #@example
567
+ # class SelWeT::Unit
568
+ #
569
+ # ...
570
+ #
571
+ # context "Example" do
572
+ #
573
+ # should 'TODO something' do
574
+ # Unit.followTheLink @@somePage
575
+ # ...
576
+ # status, error = Unit.fillTheField 'input#some_id', 'some text' #заполнить текстовое поле
577
+ # status, error = Unit.fillTheField 'input#[type={"file"}]', 'C:\\path\to\file' #выбрать файл для загрузки
578
+ # ...
579
+ #@see followTheLink
580
+ #@see postForm
581
+ def fillTheField selector, value, postfix = nil
582
+ result = [true, ""]
583
+ threads = []
584
+ status, message, data = checkElement selector
585
+ unless status
586
+ return [false, message]
587
+ end
588
+ data.each_value do |i|
589
+ if i.size>1
590
+ return [false, "fillTheField: Element with selector #{selector} not uniq!"]
591
+ end
592
+ end
593
+ @@driver.each do |name, driver|
594
+ threads << Thread.new do
595
+ element = driver.find_element(:css => selector)
596
+ driver.action.move_to(element).perform
597
+ begin
598
+ element.clear if element.attribute('type') != 'file'
599
+ rescue
600
+ #skip this
601
+ end
602
+ driver.find_element(:css => selector).send_keys((postfix.nil? ? value : value+"_"+name))
603
+ end
604
+ end
605
+ threads.each(&:join)
606
+ return result
607
+ end
608
+ #Возвращает состояние для radio и checkbox. Используется только в блоках should или setup.
609
+ # @param selector [String] css селектор
610
+ # @return [[Boolean,String/Hash] первый аргумент - статус выполнения, второй - хеш вида !{имя_браузера=>статус} (если radio или checkbox: 1. checked, то статус принимает значение true; 2. unchecked, то статус принимает значение false), или, если первый аргумент равен false - содержит текст ошибки.
611
+ #@example
612
+ # class SelWeT::Unit
613
+ #
614
+ # ...
615
+ #
616
+ # context "Example" do
617
+ #
618
+ # should 'TODO something' do
619
+ # Unit.followTheLink @@somePage
620
+ # ...
621
+ # status, check = Unit.getStatus 'input[type="checkbox"]'
622
+ # ...
623
+ def getStatus selector
624
+ threads = []
625
+ status, message, data = checkfElement selector
626
+ return [false, 'getStatus: Element not uniq!'] if data.values[0].size>1
627
+ return [false, "getStatus: "+message, tag] unless status
628
+ status = true
629
+ @@driver.each do |name, driver|
630
+ threads << Thread.new do
631
+ element = driver.find_element(:css => selector)
632
+ Thread.current['name'] = name
633
+ if element.attribute('type') == 'checkbox' or element.attribute('type') == 'radio'
634
+ Thread.current['status'] = driver.find_element(:css => selector).selected?.inspect
635
+ else
636
+ Thread.current['status'] = "#{element.attribute('type')} is not a checkbox or radio!"
637
+ status = false
638
+ end
639
+ end
640
+ end
641
+ threads.each(&:join)
642
+ statuses = {}
643
+ threads.each do |i|
644
+ statuses[i['name']] = (i['status'] == "true" ? true : i['status'] == "false" ? false : i['status'])
645
+ end
646
+ return [status, statuses]
647
+ end
648
+ #Заполнить и отправить форму.
649
+ # @param selector [String] css селектор формы.
650
+ # @param fields [Hash] хеш. В качестве ключа передается css селектор элемента (String), в качестве значения: 1) для текстовых полей - строка со значением(String). Если в разных браузерах требуется ввести разные значения, то вначале строки необходимо поставить символ &. Тогда в поле запишется данная строка без символа &, но в конце будет добавлен постфикс "_имя браузера"; 2) для checkbox, radio и кнопок(не submit!) - значение :click; 3) для кнопки отправки формы - :submit. Если не будет указана кнопка для отправки формы, то форма всё равно будет отправлена; 4) для select - массив значений(String), которые необходимо выбрать; 5) для file - путь до файла.
651
+ # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
652
+ #@example
653
+ # class SelWeT::Unit
654
+ #
655
+ # ...
656
+ #
657
+ # context "Example" do
658
+ #
659
+ # should "Successfull authorization" do
660
+ # status, error = Unit.postForm ".form", {'#email' => 'admin@example.ru', '#password' => 'admin', '.checkbox' => :click, '.submit'=>:submit}
661
+ # ...
662
+ #@see click
663
+ #@see fillTheField
664
+ def postForm selector, fields = nil
665
+ result = [true, ""]
666
+ fields = {} if fields.nil?
667
+ status, message, data = checkElement selector
668
+ unless status
669
+ return [false, message]
670
+ end
671
+ data.each do |key, value|
672
+ if value.size>1
673
+ return [false, "postForm: (#{key}) Found more than one form with selector '#{selector}'"]
674
+ end
675
+ end
676
+ check_elements = ''
677
+ fields.keys.each do |key|
678
+ status, message, data = checkElement key
679
+ unless status
680
+ check_elements = (check_elements.empty? ? message+' : '+key+"\n" : check_elements+message+' : '+key+"\n")
681
+ end
682
+ data.each do |browser, value|
683
+ if value.size>1
684
+ check_elements = (check_elements.empty? ? "postForm:(#{browser}) Element of form not uniq : "+key+"\n" : check_elements+"postForm:(#{browser}) Element of form not uniq : "+key+"\n")
685
+ end
686
+ end
687
+ end
688
+ unless check_elements.empty?
689
+ return [false, check_elements]
690
+ end
691
+ submit_button = nil
692
+ bad_args = {}
693
+ fields.each do |key, value|
694
+ if value.class != String and value.class != Symbol
695
+ bad_args[key] = value
696
+ end
697
+ if value.class == Symbol
698
+ if value != :click and value != :submit
699
+ bad_args[key] = value
700
+ end
701
+ end
702
+ end
703
+ return [false, 'postForm: Bad args was passed: '+bad_args.to_s] unless bad_args.empty?
704
+ fields.each do |key, value|
705
+ if value == :click
706
+ click key
707
+ end
708
+ if value == :submit
709
+ submit_button = key
710
+ end
711
+ if value.class == Array
712
+ status, error = selectItemsFromTheSelect(key, value)
713
+ return [false, error] unless status
714
+ end
715
+ end
716
+ fields.delete_if { |key,value| value == :click or value == :submit or value.class == Array }
717
+ threads = []
718
+ errors = nil
719
+ @@driver.each do |name, driver|
720
+ threads << Thread.new do
721
+ form = driver.find_element(:css => selector)
722
+ fields.each do |key, value|
723
+ tag = form.find_element(:css => key).tag_name
724
+ errors = true if tag == 'select'
725
+ begin
726
+ form.find_element(:css => key).clear
727
+ rescue
728
+ #skip this
729
+ end
730
+ if value[0] == '&'
731
+ send_value = value+'_'+name
732
+ send_value.slice! '&'
733
+ form.find_element(:css => key).send_keys(send_value)
734
+ else
735
+ form.find_element(:css => key).send_keys(value)
736
+ end
737
+ end
738
+ unless errors
739
+ form.submit unless submit_button
740
+ end
741
+ end
742
+ end
743
+ threads.each(&:join)
744
+ return [false, 'postForm: For "select" you must pass array with selected values!'] if errors
745
+ click submit_button unless !submit_button
746
+ return result
747
+ end
748
+ #Сверяет переданный url с текущим. Используется только в блоках should или setup.
749
+ # @param url [String] url, с которым будет сравинваться текущий url.
750
+ # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
751
+ #@example
752
+ # class SelWeT::Unit
753
+ #
754
+ # setBrowsers [:firefox, :chrome]
755
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
756
+ # @@somePage = 'http://www.example.com'
757
+ #
758
+ # context "Example" do
759
+ #
760
+ # should 'Correct link' do
761
+ # Unit.followTheLink @@somePage
762
+ # ...
763
+ # status, error = Unit.checkLocation 'http://www.example.com/other_page'
764
+ # ...
765
+ #@see followTheLink
766
+ #@see getLocation
767
+ def checkLocation url
768
+ result = [true, ""]
769
+ threads = []
770
+ @@driver.each do |name, driver|
771
+ threads << Thread.new do
772
+ unless driver.current_url == url
773
+ Thread.current["value"] = name
774
+ Thread.current["real"] = driver.current_url
775
+ end
776
+ end
777
+ end
778
+ threads.each(&:join)
779
+ threads.each do |i|
780
+ unless i["value"].nil?
781
+ result[1] = (result[1].empty? ? "Wrong location '#{i['real']}': "+i["value"].to_s : result[1]+" "+i["value"].to_s)
782
+ end
783
+ end
784
+ unless result[1].empty?
785
+ result[0] = false
786
+ end
787
+ return result
788
+ end
789
+ #Возвращает текущий url. Используется только в блоках should или setup.
790
+ # @return [Hash] ключ - имя браузера, значение - URL.
791
+ #@example
792
+ # class SelWeT::Unit
793
+ #
794
+ # setBrowsers [:firefox, :chrome]
795
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
796
+ # @@somePage = 'http://www.example.com'
797
+ #
798
+ # context "Example" do
799
+ #
800
+ # should 'Correct link' do
801
+ # Unit.followTheLink @@somePage
802
+ # ...
803
+ # location = Unit.getLocation
804
+ # ...
805
+ #@see checkLocation
806
+ #@see followTheLink
807
+ def getLocation
808
+ result = {}
809
+ threads = []
810
+ @@driver.each do |name, driver|
811
+ threads << Thread.new do
812
+ Thread.current["name"] = name
813
+ Thread.current["url"] = driver.current_url
814
+ end
815
+ end
816
+ threads.each(&:join)
817
+ threads.each do |i|
818
+ result[i['name']] = i['url']
819
+ end
820
+ return result
821
+ end
822
+ #Сохраняет скриншот текущего состояния браузеров рядом со скриптом. Имя файла будет иметь следующий вид: browsername_filename.png
823
+ # @param filename [String] часть имени выходного файла.
824
+ #@example
825
+ # class SelWeT::Unit
826
+ #
827
+ # setBrowsers [:firefox, :chrome]
828
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
829
+ # @@somePage = 'http://www.example.com'
830
+ #
831
+ # context "Example" do
832
+ #
833
+ # should 'Make screenshot' do
834
+ # Unit.followTheLink @@somePage
835
+ # ...
836
+ # Unit.screenshot 'TestScreenshot'
837
+ # ...
838
+ def screenshot filename
839
+ threads = []
840
+ @@driver.each do |name, driver|
841
+ threads << Thread.new do
842
+ driver.save_screenshot("./"+name+"_"+filename+".png")
843
+ end
844
+ end
845
+ threads.each(&:join)
846
+ end
847
+ #Открывает ссылку в новом окне и переключается на него.
848
+ #@param selector [String] css селектор ссылки.
849
+ # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
850
+ #@example
851
+ # class SelWeT::Unit
852
+ #
853
+ # setBrowsers [:firefox, :chrome]
854
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
855
+ # @@somePage = 'http://www.example.com'
856
+ #
857
+ # context "Example" do
858
+ #
859
+ # should 'TODO somethin' do
860
+ # Unit.followTheLink @@somePage
861
+ # ...
862
+ # Unit.openInNewWindow 'a.someclass'
863
+ # ...
864
+ #@see switchToWindow
865
+ #@see closeWindow
866
+ def openInNewWindow selector
867
+ threads = []
868
+ not_opened = false
869
+ status, message = checkElement selector
870
+ unless status
871
+ return [false, message]
872
+ end
873
+ @@driver.each do |name, driver|
874
+ threads << Thread.new do
875
+ a = driver.find_element :css => selector
876
+ if @@win_num == 0
877
+ @@opened_window[name] = {@@win_num => driver.window_handle}
878
+ end
879
+ driver.action.key_down(:shift).perform
880
+ a.click
881
+ driver.action.key_up(:shift).perform
882
+ old_handle = @@opened_window[name].values
883
+ new_handle = (driver.window_handles - old_handle)[0]
884
+ unless new_handle.nil?
885
+ driver.switch_to.window new_handle
886
+ @@opened_window[name][@@win_num+1] = new_handle
887
+ else
888
+ not_opened = true
889
+ end
890
+ end
891
+ end
892
+ threads.each(&:join)
893
+ return [false, "Window not opened!"] if not_opened
894
+ @@win_num += 1
895
+ return true
896
+ end
897
+ #Переключиться на другое окно. Окна нумируются в порядке их открытия. Нумирация начинается с 0.
898
+ #@param num [Integer] номер окна.
899
+ # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
900
+ #@example
901
+ # class SelWeT::Unit
902
+ #
903
+ # setBrowsers [:firefox, :chrome]
904
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
905
+ # @@somePage = 'http://www.example.com'
906
+ #
907
+ # context "Example" do
908
+ #
909
+ # should 'TODO something' do
910
+ # Unit.openInNewTab 'a.someclass'
911
+ # ...
912
+ # Unit.switchToWindow 0
913
+ # Unit.closeWindow 1
914
+ # ...
915
+ #@see openInNewWindow
916
+ #@see closeWindow
917
+ def switchToWindow num
918
+ threads = []
919
+ status = true
920
+ @@driver.each do |name, driver|
921
+ threads << Thread.new do
922
+ if @@opened_window[name].has_key? num
923
+ driver.switch_to.window @@opened_window[name][num]
924
+ else
925
+ status = false
926
+ end
927
+ end
928
+ end
929
+ threads.each(&:join)
930
+ return status, (status ? "" : "Invalid num: '#{num}'")
931
+ end
932
+ #Закрыть окно с номером num. Окна нумируются в порядке их открытия. Нумирация начинается с 0. Если необходимо закрыть текущее окно, то перед закрытием необходимо переключиться на другое окно.
933
+ #@param num [Integer] номер окна.
934
+ # @return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
935
+ #@example
936
+ # class SelWeT::Unit
937
+ #
938
+ # setBrowsers [:firefox, :chrome]
939
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
940
+ # @@somePage = 'http://www.example.com'
941
+ #
942
+ # context "Example" do
943
+ #
944
+ # should 'TODO somethin' do
945
+ # Unit.closeWindow 2
946
+ # ...
947
+ #@see openInNewTab
948
+ #@see switchToWindow
949
+ def closeWindow num
950
+ threads = []
951
+ status = true
952
+ @@driver.each do |name, driver|
953
+ threads << Thread.new do
954
+ current = driver.window_handle
955
+ if current != @@opened_window[name][num]
956
+ driver.switch_to.window @@opened_window[name][num]
957
+ driver.close
958
+ @@opened_window[name].delete_if do |key, value|
959
+ key == num
960
+ end
961
+ driver.switch_to.window current
962
+ else
963
+ status = false
964
+ end
965
+ end
966
+ end
967
+ threads.each(&:join)
968
+ if status
969
+ return true
970
+ else
971
+ return [false, "You must switch to other window before closing this window"]
972
+ end
973
+ end
974
+ #Навести курсор на элемент.
975
+ #@param selector [String] css селектор элемента.
976
+ #@return [[Boolean,String]] Первый аргумент - статус выполнения, второй - текст ошибки, если она возникнет.
977
+ #@example
978
+ # class SelWeT::Unit
979
+ #
980
+ # setBrowsers [:firefox, :chrome]
981
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
982
+ # @@somePage = 'http://www.example.com'
983
+ #
984
+ # context "Example" do
985
+ #
986
+ # should 'TODO somethin' do
987
+ # Unit.hoverOverElement "div.menu"
988
+ # Unit.click "a.some_url"
989
+ # ...
990
+ def hoverOverElement selector
991
+ status, message = checkElement selector
992
+ unless status
993
+ return [false, message]
994
+ end
995
+ threads = []
996
+ @@driver.each do |name, driver|
997
+ threads << Thread.new do
998
+ element = driver.find_element(:css => selector)
999
+ driver.action.move_to(element).perform
1000
+ end
1001
+ end
1002
+ threads.each(&:join)
1003
+ return true
1004
+ end
1005
+ #Получить заголовок окна.
1006
+ #@return Hash ключ - имя браузера, аргумент - title.
1007
+ #@example
1008
+ # class SelWeT::Unit
1009
+ #
1010
+ # setBrowsers [:firefox, :chrome]
1011
+ # setSeleniumServerUrl 'http://localhost:4444/wd/hub'
1012
+ # @@somePage = 'http://www.example.com'
1013
+ #
1014
+ # context "Example" do
1015
+ #
1016
+ # should 'TODO somethin' do
1017
+ # ...
1018
+ # titles = Unit.getTitle
1019
+ # ...
1020
+ def getTitle
1021
+ threads = []
1022
+ status = true
1023
+ @@driver.each do |name, driver|
1024
+ threads << Thread.new do
1025
+ Thread.current["name"] = name
1026
+ Thread.current["title"] = driver.title
1027
+ end
1028
+ end
1029
+ threads.each(&:join)
1030
+ titles = {}
1031
+ threads.each do |i|
1032
+ titles[i["name"]] = i["title"]
1033
+ end
1034
+ return titles
1035
+ end
1036
+
1037
+ end
1038
+
1039
+ end
1040
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: selwet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Motin Artem
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: selenium-webdriver
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.44'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.44'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 3.0.6
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.6
47
+ - !ruby/object:Gem::Dependency
48
+ name: shoulda-context
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.2'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.2.1
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '1.2'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 1.2.1
67
+ - !ruby/object:Gem::Dependency
68
+ name: bundler
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '1.6'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.6'
81
+ description: '["Gem for creating web tests"]'
82
+ email: a.motin@inventos.ru
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - lib/selwet.rb
88
+ homepage:
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.2.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Selenium Web Test
112
+ test_files: []
113
+ has_rdoc: